pax_global_header00006660000000000000000000000064122471710150014512gustar00rootroot0000000000000052 comment=b78e7f8f95e083138ad64e96a2478f46f88f41ec flare-engine-0.19/000077500000000000000000000000001224717101500137775ustar00rootroot00000000000000flare-engine-0.19/CMakeLists.txt000066400000000000000000000136631224717101500165500ustar00rootroot00000000000000Project (Flare) cmake_minimum_required (VERSION 2.6) Set (PACKAGE "FLARE") Set (VERSION "0.18") # Default definitions if (NOT MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wunused -Wshadow -Woverloaded-virtual -Wunreachable-code") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-math-errno -fno-exceptions") if (NOT CMAKE_CXX_COMPILER MATCHES "clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math") endif (NOT CMAKE_CXX_COMPILER MATCHES "clang") set(CMAKE_LD_FLAGS "-fwhole-program") endif (NOT MSVC) if (CMAKE_CXX_COMPILER MATCHES "clang") # clang needs lstdc++ linked explicitly: set(CMAKE_LD_FLAGS "${CMAKE_LD_FLAGS} -lstdc++") elseif () # assume gcc: set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-enforce-eh-specs") endif () if(CMAKE_BUILD_TYPE STREQUAL "Release") set(CMAKE_CXX_FLAGS_RELEASE "-O2 -g0") elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g") elseif(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -g0") elseif(CMAKE_BUILD_TYPE STREQUAL "Debug") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3 -pg") set(CMAKE_EXE_LINKER_FLAGS_DEBUG "-pg") set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "-pg") set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "-pg") endif() set(BINDIR "games" CACHE STRING "Directory from CMAKE_INSTALL_PREFIX where game executable will be installed.") set(DATADIR "share/games/flare" CACHE STRING "Directory from CMAKE_INSTALL_PREFIX where game data files will be installed.") set(MANDIR "share/man" CACHE STRING "Directory from CMAKE_INSTALL_PREFIX where manual pages will be installed.") If(NOT IS_ABSOLUTE "${DATADIR}") add_definitions(-DDATA_INSTALL_DIR="${CMAKE_INSTALL_PREFIX}/${DATADIR}") Else(NOT IS_ABSOLUTE "${DATADIR}") add_definitions(-DDATA_INSTALL_DIR="${DATADIR}") EndIf(NOT IS_ABSOLUTE "${DATADIR}") # Detect missing dependencies Find_Package (SDL REQUIRED) If (NOT SDL_FOUND) Message (FATAL_ERROR "Couldn't find SDL development files. On Debian-based systems (such as Ubuntu) you should install the 'libsdl1.2-dev' package.") Else (NOT SDL_FOUND) Include_Directories (${SDL_INCLUDE_DIR}) EndIf (NOT SDL_FOUND) Find_Package (SDL_mixer REQUIRED) If (NOT SDLMIXER_FOUND) Message (FATAL_ERROR "Couldn't find SDL-mixer development files. On Debian-based systems (such as Ubuntu) you should install the 'libsdl-mixer1.2-dev' package.") Else (NOT SDLMIXER_FOUND) Include_Directories (${SDLMIXER_INCLUDE_DIR}) EndIf (NOT SDLMIXER_FOUND) Find_Package (SDL_image REQUIRED) If (NOT SDLIMAGE_FOUND) Message (FATAL_ERROR "Couldn't find SDL-image development files. On Debian-based systems (such as Ubuntu) you should install the 'libsdl-image1.2-dev' package.") Else (NOT SDLIMAGE_FOUND) Include_Directories (${SDLIMAGE_INCLUDE_DIR}) EndIf (NOT SDLIMAGE_FOUND) Find_Package (SDL_ttf REQUIRED) If (NOT SDLTTF_FOUND) Message (FATAL_ERROR "Couldn't find SDL-ttf development files. On Debian-based systems (such as Ubuntu) you should install the 'libsdl-ttf2.0-dev' package.") Else (NOT SDLTTF_FOUND) Include_Directories (${SDLTTF_INCLUDE_DIR}) EndIf (NOT SDLTTF_FOUND) # Sources Set (FLARE_SOURCES ./src/BehaviorAlly.cpp ./src/Entity.cpp ./src/Animation.cpp ./src/AnimationManager.cpp ./src/AnimationSet.cpp ./src/AStarContainer.cpp ./src/AStarNode.cpp ./src/Avatar.cpp ./src/BehaviorStandard.cpp ./src/CampaignManager.cpp ./src/CombatText.cpp ./src/EffectManager.cpp ./src/Enemy.cpp ./src/EnemyBehavior.cpp ./src/EnemyGroupManager.cpp ./src/EnemyManager.cpp ./src/EventManager.cpp ./src/FileParser.cpp ./src/FontEngine.cpp ./src/GameState.cpp ./src/GameStateConfig.cpp ./src/GameStateCutscene.cpp ./src/GameStateTitle.cpp ./src/GameStateLoad.cpp ./src/GameStatePlay.cpp ./src/GameStateNew.cpp ./src/GameSwitcher.cpp ./src/GetText.cpp ./src/Hazard.cpp ./src/HazardManager.cpp ./src/ImageManager.cpp ./src/InputState.cpp ./src/ItemManager.cpp ./src/ItemStorage.cpp ./src/Loot.cpp ./src/LootManager.cpp ./src/Map.cpp ./src/MapCollision.cpp ./src/MapRenderer.cpp ./src/Menu.cpp ./src/MenuActionBar.cpp ./src/MenuActiveEffects.cpp ./src/MenuCharacter.cpp ./src/MenuConfirm.cpp ./src/MenuEnemy.cpp ./src/MenuExit.cpp ./src/MenuHUDLog.cpp ./src/MenuInventory.cpp ./src/MenuItemStorage.cpp ./src/MenuLog.cpp ./src/MenuManager.cpp ./src/MenuMiniMap.cpp ./src/MenuNPCActions.cpp ./src/MenuPowers.cpp ./src/MenuStash.cpp ./src/MenuStatBar.cpp ./src/MenuTalker.cpp ./src/MenuVendor.cpp ./src/MessageEngine.cpp ./src/ModManager.cpp ./src/NPC.cpp ./src/NPCManager.cpp ./src/PowerManager.cpp ./src/QuestLog.cpp ./src/SaveLoad.cpp ./src/SDL_gfxBlitFunc.c ./src/Settings.cpp ./src/SharedGameResources.cpp ./src/SharedResources.cpp ./src/StatBlock.cpp ./src/Stats.cpp ./src/SoundManager.cpp ./src/TileSet.cpp ./src/TooltipData.cpp ./src/Utils.cpp ./src/UtilsDebug.cpp ./src/UtilsFileSystem.cpp ./src/UtilsParsing.cpp ./src/Widget.cpp ./src/WidgetCheckBox.cpp ./src/WidgetButton.cpp ./src/WidgetInput.cpp ./src/WidgetLabel.cpp ./src/WidgetListBox.cpp ./src/WidgetScrollBar.cpp ./src/WidgetScrollBox.cpp ./src/WidgetSlider.cpp ./src/WidgetSlot.cpp ./src/WidgetTabControl.cpp ./src/WidgetTooltip.cpp ./src/main.cpp ) # Add icon and file info to executable for Windows systems IF (WIN32) SET(FLARE_SOURCES ${FLARE_SOURCES} ./src/Flare.rc ) ENDIF (WIN32) Add_Executable (flare ${FLARE_SOURCES}) # libSDLMain comes with libSDL if needed on certain platforms If (NOT SDLMAIN_LIBRARY) Set (SDLMAIN_LIBRARY "") EndIf (NOT SDLMAIN_LIBRARY) Target_Link_Libraries (flare ${CMAKE_LD_FLAGS} ${SDL_LIBRARY} ${SDLMIXER_LIBRARY} ${SDLIMAGE_LIBRARY} ${SDLTTF_LIBRARY} ${SDLMAIN_LIBRARY}) # installing to the proper places install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/flare DESTINATION ${BINDIR}) install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/mods" DESTINATION ${DATADIR}/default) install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/distribution/flare.man" DESTINATION ${MANDIR}/man1 RENAME flare.1) flare-engine-0.19/COPYING000066400000000000000000001045131224717101500150360ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . flare-engine-0.19/CREDITS.txt000066400000000000000000000034131224717101500156360ustar00rootroot00000000000000Flare v0.19 Engine Credits Programming Anton Golov | http://jesyspa.blogspot.com/ Artur "Zear" Rojek blazindragon Bonbadil Chris Oelmueller Clint Bellanger | http://clintbellanger.net David Bariod Daniel Santos Gallaecio Henrik Andersson | https://github.com/hean01 Igor Paliychuk Joseph Bleu Juan PabloTamayo "morris989" Justin Jacobs | https://github.com/dorkster Kitano Kyle Belanger LongerDev Manuel A. Fernandez Montecelo Matthew Krohn | https://github.com/makrohn Nojan Pavel Kirpichyov "Cheshire" runtime-x86 Ryan Dansie | https://github.com/RyanDansie Stefan Beller | https://github.com/stefanbeller Thane "pennomi" Brimhall | https://github.com/pennomi Distributions Ablu Feillyne Jan-Hendrik (hennr) Peters Manuel A. Fernandez Montecelo miffe ... and many others Translations (be) Belarussian by Mikhail Karalevich (cs) Czech by Nikita Vanku (Zaraka) (de) German by Thomas 'CruzR' Glamsch, Chris Oelmueller, Stefan Beller, and Wuzzy2 (el) Greek by Yannis Anthymidis and Michael Papageorgiou (es) Spanish by Juan Pablo 'morris989' Tamayo and Carlos Sanchez (fi) Finnish by Timo Sievänen (fr) French by Quentin 'acieroid' Stievenart, Bonbadil, Morgan Strauss, and Christoph J. Thompson (gd) Scottish Gaelic by gunchleoc (gl) Galacian by Adrian Chaves Fernandez (Gallaecio) (it) Italian by Giovanni Dalla Torre and Andrea Ranaldi (ja) Japanese by Paul Wortmann (nb) Norwegian Bokmal by Hans Joachim Desserud (nl) Dutch by Bas Doodeman (pl) Polish by Paweł Puszczyński (ru) Russian by Sergey Basalaev and Evgen Pavlov (sk) Slovak by Miro Jánošík (sv) Swedish by Andreas Berheim Brudin (uk) Ukrainian by Igor Paliychuk (zh) Chinese by lonsine Full Credits See the full credits listing including per-file attribution online: https://github.com/clintbellanger/flare-engine/wiki/Credits flare-engine-0.19/Codingstyle.txt000066400000000000000000000065631224717101500170360ustar00rootroot00000000000000## Contributing Code The #1 rule of this project: _all non-trivial code changes must be discussed first!_ Years of careful decision-making have gone into all parts of this project. Some designs are awaiting planned future changes. If you submit a large patch without knowing how it will affect past and future code, **it will be rejected**. Is my code non-trivial? If it touches multiple functions or files, probably so. Ways to discuss a desired code change: * Open an Issue at http://github.com/clintbellanger/flare-engine/ * Email clintbellanger@gmail.com ## Pull Requests When possible, use small pull requests that keep the engine in a stable state. It is far better to have many small pull requests than to wait until your change is too large to merge. If you're working on more than one feature, submit pull requests separately for these. Some times we need to accept one change and reject the other; if your pull request is all combined I have to reject the entire thing. ## Cross-platform considerations To the best of our ability, we want the code to work on Windows, OSX, Linux and more. We try to isolate platform-specific code and use C preprocessor directives when necessary. ## OOP as a last resort My code is simple (some would say not elegant). I start by coding it the simplest possible way that would work. I have a deep disdain for overengineering. Nevertheless Copy&paste coding style should be avoided. Action RPGs are a really simple genre. We don't need fully OOP Entity system to create these games. We have introduced OOP as needed, when the solution makes much more sense than the added complexity. We won't needlessly refactor working code. ## No C++11 / C++0x Maybe we'll allow this kind of code in the future. But Flare has a presence on obscure platforms; I can't guarantee that the compilers have kept up. ## Indentation I try to use tabs. I don't really care though, as long as a single file is internally consistent. ## Naming Conventions Here are the basic conventions, which are not really consistent. Not a big deal, I sometimes clean these up as I go. * ClassName::functionName * ClassName::class_variable * local_variable * ENUM_OR_CONSTANT ## Commenting I try to use Javadoc style comments on functions, especially if they're non-obvious. I try to avoid block comments inside functions (so it's easy to block comment out an entire function). ## Brackets We try to have put brackets in the same line as the adherent command (if, else, while, function) ## Coding style checking in QtCreator In case you're using QtCreator for hacking flare, import the qt.xml file as found in this repository. ## Coding style checking and formatting with artistic style (astyle) There is a script 'astyle.sh', which will automatically format your new code with regard to indentation and brackets. ## Example A piece of code considered good: Classname::function() { // meaningful comment (such as: if player is dead, give no xp for killing monsters) // mind the tabs being equal to 4 spaces: if (variable) { int i = foo(); bar(&i); } else { printf("A fine coding example\n"); } } A bad example Classname::function() { // Having the bracket adding a new line for no reason /* Multiline comments considered bad. */ if(variable) // Mind the missing space between if and opening bracket { int i = foo(); bar(&i); } else { printf("Coding example done wrong\n"); } } flare-engine-0.19/INSTALL.engine000066400000000000000000000075341224717101500163050ustar00rootroot00000000000000## Dependencies To build flare you need the 1.2 Development Libraries for SDL, SDL_image, SDL_mixer, and SDL_ttf. To run flare you need the equivalent 1.2 Runtime Libraries. http://www.libsdl.org/download-1.2.php For easy building I recommend using cmake and make. ### Microsoft Visual C++ If you want to build flare under Microsoft Visual C++, you should get dirent.h header file from http://softagalleria.net/dirent.php and copy it to "Microsoft Visual C++ folder"\VC\include ### Debian based systems Installing dependencies on debian based systems (debian, Ubuntu, Kubuntu, etc): sudo apt-get install libsdl1.2-dev libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl-ttf2.0-dev # for development you'll also need: sudo apt-get install cmake make g++ git There is also a flare build in the Ubuntu (universe), which actually is flare-game. http://packages.ubuntu.com/source/precise/flare ### Arch Linux Installing dependencies on Arch Linux: pacman -S --asdeps sdl sdl_image sdl_mixer libogg libvorbis hicolor-icon-theme python sdl_ttf There is also a flare-rpg-git pkgbuild at the arch user repository: https://aur.archlinux.org/packages.php?ID=57522 ### OpenSuse Installing dependencies on openSUSE: sudo zypper in make cmake gcc-c++ libSDL-devel libSDL_image-devel libSDL_mixer-devel libSDL_ttf-devel There is also a flare build at the openSUSE games repo: http://software.opensuse.org/download.html?project=games&package=flare ### Fedora Installing dependencies on Fedora yum install git make cmake gcc-c++ SDL-devel SDL_image-devel SDL_mixer-devel SDL_ttf-devel ## Building from Source There are several ways to build the game executable. For engine developers the cmake method is recommended as it has low overhead when it comes to changes in the code. However you can also build the engine with just one call to your compiler including all source files at once. This might be useful if you are trying to run a flare based game on an obscure platform as you only need a c++ compiler and the ported SDL package. ### Building with CMake To build the game executable, go to the main directory/folder and run the following commands: cmake . make The executable is called ```flare``` in this repository or in the flare-game repository, but it is subject to change if you're running another game based on the engine (such as polymorphable). If you want the game installed system-wide, as root, install with: make install The game will be installed into '/usr/local' by default. You can set different paths in the cmake step, like: cmake -DCMAKE_INSTALL_PREFIX:STRING="/usr" .. ### Building with g++ If you prefer building directly with C++, the command will be something like this. Windows plus MinGW (depending on where your SDL dev headers are) g++ -I C:\MinGW\include\SDL src\*.cpp src\*.c -o flare.exe -lmingw32 -lSDLmain -lSDL -lSDL_image -lSDL_mixer -lSDL_ttf Linux (depending on where your SDL includes are) g++ -I /usr/include/SDL src/*.cpp src/*.c -o flare -lSDL -lSDL_image -lSDL_mixer -lSDL_ttf ### Optimizing your build Flare is intended to be able to run on a wide range of hardware. Even on very low end hardware, such as handhelds or old computers. To run on low end hardware smooth, we need get the best compile output possible for this device. The following tips may help improving the the compile output with respect to speed. However these compiler switches are not supported on some platforms, hence we do not include it into the default compile settings. * Make sure the compiler optimizes for exactly your hardware. (g++, see -march, -mcpu) * Enable link time optimisation (g++: -flto) This option inlines small get and set functions accross object files reducing overhead in function calls. * More aggressive optimisation by telling the linker, it's just this program. (g++: -fwhole-program) * to be continued. flare-engine-0.19/Launch Flare OSX.command000077500000000000000000000000501224717101500202130ustar00rootroot00000000000000#!/bin/bash cd "`dirname "$0"`" ./flare flare-engine-0.19/Launch Flare Windows.bat000066400000000000000000000000111224717101500203160ustar00rootroot00000000000000flare.exeflare-engine-0.19/README.engine000066400000000000000000000056431224717101500161330ustar00rootroot00000000000000# Flare Flare (Free Libre Action Roleplaying Engine) is a simple game engine built to handle a very specific kind of game: single-player 2D action RPGs. Flare is not a reimplementation of an existing game or engine. It is a tribute to and exploration of the action RPG genre. Rather than building a very abstract, robust game engine, the goal of this project is to build several real games and harvest an engine from the common, reusable code. Flare uses simple file formats (INI style config files) for most of the game data, allowing anyone to easily modify game contents. Open formats are preferred (png, ogg). The game code is C++. Originally the first game to be developed using this engine was part of this repository. As the engine became mature, the game content was moved to an extra repository and is now called flare-game. (happened around sept. 2012) ## Copyright and License Most of Flare is Copyright © 2010-2013 Clint Bellanger. Contributors retain copyrights to their original contributions. Flare's source code is released under the GNU GPL v3. Later versions are permitted. Flare's default mod (includes engine translations) is released under GNU GPL v3 and CC-BY-SA 3.0. Later versions are permitted. The default mod contains the Liberation Sans font which is released under the SIL Open Font License, Version 1.1. ## Links The following links are specific to the engine * Homepage no engine dedicated homepage exists yet, the first game flare-game is found at www.flarerpg.org. Some issues regarding the engine can be found there as well. * Source https://github.com/clintbellanger/flare-engine * Forums http://opengameart.org/forums/flare * Email clintbellanger@gmail.com ## Games made with flare * flare-game A medival fantasy game. In the first days of the engine this game influenced most design decisions a lot. The art is 3d rendered 64x32 px isometric perspective. * polymorphable A game made for "The Liberated Pixel cup", which was a competition about game art and making a game thereof. The pixel art is 32x32 orthogonal perspective featuring a medival setting. The development has finished. * concordia Another game using the art created during "The liberated pixel cup". While this started without stress regarding the timeline for the pixel cup, this story is more thought through and the content is more organized. ## Settings Settings are stored in one of these places: $XDG_CONFIG_HOME/$GAMENAME $HOME/.config/$GAMENAME ./config whereas $GAMENAME is defaulting to ```flare``` in this repository or in flare-game. Here you can enable fullscreen, change the game resolution, enable mouse-move, and change keybindings. The settings files are created the first time you run Flare. ## Save Files Save files are stored in one of these places: $XDG_DATA_HOME/$GAMENAME $HOME/.local/share/$GAMENAME ./saves If permissions are correct, the game is automatically saved when you exit. flare-engine-0.19/README.md000077700000000000000000000000001224717101500173752README.engineustar00rootroot00000000000000flare-engine-0.19/RELEASE_NOTES.txt000066400000000000000000000024221224717101500165700ustar00rootroot00000000000000Flare Engine v0.19 Engine changes: Power specific stat modifiers (Ryan Dansie) Cutscenes (Stefan Beller) Specify data path via command line argument (Justin Jacobs) Minions support (Ryan Dansie) Flare engine man page (Christoph Thompson) Keyboard based menu navigation (Igor Paliychuk, Joseph Bleu, Justin Jacobs) Movement using floating point positions (Stefan Beller, Justin Jacobs Hardcore characters no longer share a stash (Stefan Beller) Credits added to title menu (Igor Paliychuk) Additional event triggers (Stefan Beller) Configurable death penalty (Justin Jacobs) Colorblind mode options (blazindragon) Add chance_flee behavior for enemies (Justin Jacobs) Currency as a stackable item (Justin Jacobs) Inline configuration attribute documentation (Henrik Andersson) New minimap tiles for false walls (Matthew Krohn) Allow custom attack animations (Matthew Krohn) EventManager to handle map and NPC events (Igor Paliychuk, Justin Jacobs) Use paths in config files when referring to other files (Justin Jacobs) Upgradeable powers (Ryan Dansie and Igor Paliychuk) TONS of internal refactoring/cleanup (everyone) Various bug fixes (everyone) New Translators: German (de) update by Wuzzy2 Greek (el) update by Michael Papageorgiou Scottish Gaelic (gd) by gunchleoc Chinese (zh) by lonsine flare-engine-0.19/distribution/000077500000000000000000000000001224717101500165165ustar00rootroot00000000000000flare-engine-0.19/distribution/Flare.ico000066400000000000000000002040761224717101500202540ustar00rootroot00000000000000 (( aF8/-7qd+8j'Q)W) +H -" / 3 # V RF.| QD>& M@RR !K@ &  !"MB 8  !"##$KA!  NT  !"##$%%&G>#""!  h  !"##$%%&&''E<%$$#"!! :  !"##$%&&''((()C:'&&%%$#"!   !""#$%&''(()))))<4((''&%%$#"!  N  !"#$%&''())***=6(('&%%$#"!   !"#$%&''())**>6('&%$#"!  -  !#$%&&'()**@5'&%$#"! }:  !"#$%&'()*C8&%$#!  N   !#$%&'()F;$#"!U !"#$%'(J=#! \  !#$%'J=!a\ !"#%J<h> !"L;o+  0_" !#K;"m" !"#%I;e(  !#$%'(K=" b:  !#$&'(*+J<%#"!]S  "#%&')*+-.G:(&%$"!Tu !"#%&()*,-.01F:+)('%$#! N !"$%&()+,-/0134J>.,+*('&$#!  H !"$%'(*+,./123467K@1/.-+*)'&$#"  D  !#$%'(*+-./12456789LB4310.-,*)(&%#"  @S  "#$&')*+-.01345789:;>=<:9865321/.,+)('%$"!  =  "#$&')*,-/0234679:<=>?>=<;9875421/.,+*('%$"! \  "#%&()+,-/0235689:<=?@?><;:875421/.,+*('%$"! a  "#%&()+,-/0235689;<=?@?><;:875431/.,+*('%$"!hH : "#%&()*,-/0235689:<=>??><;:875421/.,+*('%$"!p 7 "#$&')*,-/0234679:;=>>>=<;9865421/.,+*('%$"!u u "#$&')*+-.0234678:;<=>==<:9865321/.,+)(&%$"!$}R " "#$&')*+-.01345789:;<=<<;:9765320/-,*)(&%#"!( \b !#$&'(*+-./1245689:;;<<;:98764320/-,*)(&%#"!,  !#$%'(*+,./12356789:;;;:998654310.-,*)'&%#" _ ;5!"$%'()+,-/023456789:::998765321/.-+*)'&$#! X v!"$%&()*,-.012456788999887654320/.,+*('%$#! M (!"#%&')*+-./12345677888876553210.-,+)('%$"!I   "#$&'(*+,./0124456777776554321/.-,*)(&%$"!C #/ !#$%'()+,-./123455666665543210/.,+*)'&%#"!? 8 !"$%&()*+-./01234455555443221/.-,+)('%$#" :k B9!"#%&'(*+,-./0123344444432210/.,+*)(&%$#!  /3 3 "#$%'()*+-./011233333332210/.-,+*('&%#"! : ' !#$%&')*+,-./0112222222110/.-,+*)('%$#"  : !"#$&'()*+,-./00111211100/.--,+*('&%$#!  Xab "#$%&()*+,,-.//0001100//..-,+*)('&$#"! vK !"$%&'()*+,--..////////.--,+*)('&%$#"  ;f!"#$%&'()*+,,-.........--,+**)('&$#"!  9 !"#%&'(()*+,,---...---,,+**)('&%$#"   !"#$%&'())*++,,,---,,,++**)('&%$#"!    !"#$%&'())**+++,,,,+++*))(''&%$#"  !"#$%%&'(())**+++++***))(''&%$#"!  @_ !"#$%%&'(()))******))((''&%$#"!  b. !"#$%%&''((())))))((''&&%$##"! !!"#$%%&&''((((((('''&&%$##"!   !""#$$%&&&'''''''&&&%%$##"!   !""#$$%%%&&&&&&&&%%$$##"! In6  Z!Hwd("##$$%%%%%%%%%$$##""! x| .g`""##$$$$$$$$$###""! 6 3H'""##########""!! 2U,"""""##""""!!  w0(!!!"""!!!! NA! !!! bAd !, 3Q $7i w - 7|+ b<Z5!vAk ^   m y Hf N C4  ! V :Z3N#}OiVJIOQ]u???????`????????>>~|???????flare-engine-0.19/distribution/flare.man000066400000000000000000000016741224717101500203140ustar00rootroot00000000000000.\" -*- nroff -*- .TH FLARE 1 "March 2013" .SH NAME flare \- action role-playing engine .SH SYNOPSIS .B flare .RB [ options ] .SH DESCRIPTION .B FLARE (short for Free Libre Action Roleplaying Engine) is a single-player, 2D-isometric action role-playing engine. It uses simple file formats (INI-style config files) for most of the game data, allowing anyone to easily modify game contents. .SH OPTIONS .IP "\fB\-\-debug-event\fP" Switch on event debugging information. .IP "\fB\-\-data-path \fIpath\fP" Set an alternate path to the game data. .IP "\fB\-\-game \fIgame\fP" Set the game that the flare engine should use. .SH FILES .TP The settings are stored in .LP \fB$XDG_CONFIG_HOME\fR/\fB$GAMENAME\fR .LP \fB$HOME\fR/.config/\fB$GAMENAME\fR .TP The game data is stored in .LP \fB$XDG_DATA_HOME\fR/\fB$GAMENAME\fR .LP \fB$HOME\fR/.local/share/\fB$GAMENAME\fR .SH AVAILABILITY For more information about the FLARE engine, visit http://flarerpg.org flare-engine-0.19/mods/000077500000000000000000000000001224717101500147415ustar00rootroot00000000000000flare-engine-0.19/mods/default/000077500000000000000000000000001224717101500163655ustar00rootroot00000000000000flare-engine-0.19/mods/default/cutscenes/000077500000000000000000000000001224717101500203615ustar00rootroot00000000000000flare-engine-0.19/mods/default/cutscenes/credits.txt000066400000000000000000000026771224717101500225730ustar00rootroot00000000000000#this scales art to width of flare window #scale_gfx=true [scene] image=menus/logo.png caption=Flare Engine Credits pause=60 caption=Lead Programmers - Clint Bellanger, Henrik Andersson, Igor Paliychuk, Justin Jacobs, Stefan Beller, and Thane Brimhall pause=300 caption=Programmers - Anton Golov, Artur Rojek, blazindragon, Bonbadil, Chris Oelmueller, David Bariod, Daniel Santos, Gallaecio, Joseph Bleu, Juan PabloTamayo, Kitano, Kyle Belanger, LongerDev, Manuel A. Fernandez Montecelo, Matthew Krohn, Nojan, Pavel Kirpichyov, runtime-x86, and Ryan Dansie pause=600 caption=Default Art - Clint Bellanger pause=300 caption=Translators - Adrian Chaves Fernandez, Andrea Ranaldi, Andreas Berheim Brudin, Bas Doodeman, Bonbadil, Carlos Sanchez, Chris Oelmueller, Christoph J. Thompson, Evgen Pavlov, Giovanni Dalla Torre, gunchleoc, Hans Joachim Desserud, Igor Paliychuk, Juan Pablo Tamayo, losine, Michael Papageorgiou, Mikhail Karalevich, Miro Jánošík, Morgan Strauss, Nikita Vanku, Paul Wortmann, Pawel Puszczynski, Quentin Stievenart, Sergey Basalaev, Stefan Beller, Thomas Glamsch, Timo Sievänen, Wuzzy2, and Yannis Anthymidis pause=600 caption=Distributors - Ablu, Feillyne, Jan-Hendrik Peters, Manuel A. Fernandez Montecelo, miffe pause=300 caption=Special Thanks - Bart Kelsey and the community at OpenGameArt, for giving constant feedback and testing. Thorbjørn Lindeijer, Stefan Beller, and Ranie Jade Ramiso for Tiled and the Flare map exporter. pause=600 flare-engine-0.19/mods/default/cutscenes/intro_example.txt000066400000000000000000000003141224717101500237660ustar00rootroot00000000000000#this scales art to width of flare window #scale_gfx=true [scene] image=menus/logo.png caption=Flare, the... soundfx=soundfx/level_up.ogg pause=60 caption=Free Libre Action Roleplaying Engine pause=120 flare-engine-0.19/mods/default/engine/000077500000000000000000000000001224717101500176325ustar00rootroot00000000000000flare-engine-0.19/mods/default/engine/combat.txt000066400000000000000000000001401224717101500216330ustar00rootroot00000000000000#max_absorb_percent=90 #max_resist_percent=90 #max_block_percent=100 #max_avoidance_percent=99 flare-engine-0.19/mods/default/engine/death_penalty.txt000066400000000000000000000004531224717101500232160ustar00rootroot00000000000000# toggle all death penalties enable=true # force permadeath for all new characters permadeath=false # remove a % of currency currency=50 # remove a % of total XP xp_total=0 # remove a % of XP since the last level-up xp_current_level=0 # remove a random equipped/carried item random_item=false flare-engine-0.19/mods/default/engine/elements.txt000066400000000000000000000001331224717101500222040ustar00rootroot00000000000000# elemental effects and their display names #[element] #name=fire #resist=Fire Resistance flare-engine-0.19/mods/default/engine/font_colors.txt000066400000000000000000000003651224717101500227260ustar00rootroot00000000000000# menus and widgets menu_normal=255,255,255 menu_bonus=0,255,0 menu_penalty=255,0,0 widget_normal=240,240,240 widget_disabled=127,127,127 # In the loading screen the hardcore characters are displayed in this color hardcore_color_name=255,64,64 flare-engine-0.19/mods/default/engine/font_settings.txt000066400000000000000000000003241224717101500232600ustar00rootroot00000000000000# Only .ttf files are supported, due to limitations in SDL_ttf # The font must be placed in /fonts [font_regular] default=LiberationSans-Regular.ttf,12,1 [font_captions] default=LiberationSans-Regular.ttf,24,1 flare-engine-0.19/mods/default/engine/gameplay.txt000066400000000000000000000000731224717101500221720ustar00rootroot00000000000000# Does mod include gameplay data or not enable_playgame=0 flare-engine-0.19/mods/default/engine/languages.txt000066400000000000000000000005601224717101500223420ustar00rootroot00000000000000# If default font should be overriden, specify it in mod_name/engine/font_settings.txt be=Беларуская cs=Čeština de=Deutsch el=Ελληνικά en=English es=Español fi=Suomi fr=Français gd=Gàidhlig gl=Galego it=Italiano ja=Japanese nb=Norsk Bokmål nl=Nederlands pl=Polski ru=Русский sk=Slovenčina sv=Svenska uk=Українська zh=Chinese flare-engine-0.19/mods/default/engine/misc.txt000066400000000000000000000001731224717101500213270ustar00rootroot00000000000000# Miscellaneous engine settings #save_hpmp=0 #default_name= #corpse_timeout=1800 #sell_without_vendor=1 #sound_falloff=15 flare-engine-0.19/mods/default/engine/resolutions.txt000066400000000000000000000002211224717101500227540ustar00rootroot00000000000000# Screen and icon resolution settings menu_frame_width=640 menu_frame_height=480 icon_size=32 required_width=640 required_height=480 flare-engine-0.19/mods/default/engine/tileset_config.txt000066400000000000000000000002721224717101500233720ustar00rootroot00000000000000# Tileset Settings #orientation=isometric # units_per_tile MUST be a power of 2 # and divisible by both tile dimensions #units_per_tile=64 # tile_size: width, height #tile_size=64,32 flare-engine-0.19/mods/default/engine/tooltips.txt000066400000000000000000000001471224717101500222520ustar00rootroot00000000000000# Tooltip engine settings tooltip_offset=12 tooltip_width=200 tooltip_margin=4 npc_tooltip_margin=64 flare-engine-0.19/mods/default/fonts/000077500000000000000000000000001224717101500175165ustar00rootroot00000000000000flare-engine-0.19/mods/default/fonts/LiberationSans-Regular.ttf000066400000000000000000012600641224717101500245620ustar00rootroot000000000000000FFTM]m`GDEFsi GPOSqʏKBGSUBX< 4OS/2˘`cmap*tcvt JKDfpgm~a9gasp  glyf7&+"ohead<6hhea t$hmtx~(\kernZlocaF(dmaxp  name postAgprepGI@CG_<+$+$ j>NC z j  RT\/\33f  Px!1ASC@ Q3>`: 999Ws sIVHh !d9[99sPssgsNs/sRshsisYs`99edesTVVhV9g9 Vs9aV9aV].V  V.V-A999 sjsWsWsVsW9sVsssVssV99sS""\ss:sqsss-sSdk3zdA)HLPwPsS88IVVVVVVhVVVV9 9999a9a9a9a9a9GV-VsWsWsWsWsWsWBWsWsWsWsW9 999sVssVsVsVsVsVdA,sssssVsWVsWVsWhWhWhWhWVsVVsWVsWVsWVsWVsW9gsV9gsV9gsV9gsVss 999 9 999\99 Vs[s~sUssssss9asV9asV9asVaV8V]9V]9V]9V]9.9..9ssssss V-V-ASASASs @s@ s [hWz@QsRtVVY^Xs9g  9V s9aa?VaWV sVVbOl C99.[W.->/-F\]\NsZsY.$sNr9 dV +VsW99asVssssssVVsWVsWB9gsV9gsVV9asV9asV-\D dV9gsVFsVsWB9G,VsWVsWVsWVsW9i9W999asV9asVlsisV]9.9\@~!stV]_A1VsWVsW9asV9asV9asV9asVV-zSSVh s.G13V!)X VsD asVV-ssVs~s=MsVsVsWsWWH5 5K9sVsVx^sssVDnsslsVSV?WfV+++ UU999sT`(1T1\D\l9[9W9a@Ix^k.;sV/OV@V V)o)J8c''aaFg(dhWv43eeee3Cw993PBd,3bbP9..:8Y[O?^>LMK8JLD% G5Ot%ttA8SSSSSSScWu>W>W9F2AVVhX=VA9a9VX 3Z9aVl.V-buV.W9V-VFsj`VtVFVsjsjVsVOVV)`0U3?S`sV`?Ss` .9.9{P?RD9asVrZ;<2 .c edsd VnVnanIG(DbW9aPPVsh [h[VW.UhV]99 u.7V@VUkVcC@9aVh.7vV.UUU.@i`sWx@sWZ1xx ksVUsW#V+zk-+7UsWsWs W99@ s xk r9X.y{zm` _CD9asVm  m  a,U6+ lW rhP %kx@+VsJU]dcZC1 )I(k / >+#hW.#ssV.g1&U+EU+zUs T  T 9cZWh@ kkU+zVsWVsWBVsW^sWcZC1M\Dxx9asV9asV9asVi7777U+zUUV.V.@XsV[V`UM`UG F9gx^.S#RI@ 9asV D+m^`Nh)\DH^jb\D^H)==\\\95BRb?o)3D9F'3P=Fm7H?3) \ {F'3=B@Wii1a06xsV=>A/WCsVsV+UU#`DE?S1kA)U+~ O Q5Q2H1H 0n.Vcf1-4q.o.+4Y--v*o';;-Z;;;80;B^^]];H;;Z [B+] `;:Beg`b <:DssV9ss91s btMI*s` ssV9Vss91sWsVsVsWI54X=s\DW@32'.,;`BBdBdB*BWB3X[[__:7/B"8[W<.%.<bbotVsWVsVsVshWsVsVsVsVsVVsWVsWVsWVsWVsW99gsVssssls9|99VVVssssssss9asV9asV9asV9asVVsVstTV]9V]9V]9V]9V]9.9.9.9.9sssssV V      V.V.V-ASASASs9 sWVsWVsWVsWVs1VsWVsWVsWVsWVsWVsWVsWVsWVsWVsWVsWVsWVs1VsWVsWVsW9Q 99asV9asV9asV9as%9asV9asV9asVa?Va?Va?Va?Va?Vss[[[[[V-V-V-V-VVVVVVVVVV****??FFFFFFllllsjsjsjsjsjsjsjsj*sVsVsVsVsVsV--````````?S?S?S?S?S?S?S?S__VVFFsjsjsVsV``?S?SVVVVVVVVVV****??sjsjsjsjsjsjsjsj?S?S?S?S?S?S?S?S__VVVVVVVVVVVVsjsjsjsjsj"B"B**w99 e eW**``````V-V-Kz?S?S?S?S?Se\'\_/WUs9 Lssk~KKKHssQM7UUXYV`95+-e=6;6shhss: PsV.)+V9gVshE%lX`P"P=];8e9d3W1d8dAdd?dAd"g{mmb))s+kUFQ@;@<fB2ssVsP9zsVA1aL -g0UAJ9999dddw)Bo)3P=FmF'=Z3333BBBRb?o)9F'3P=F7H?3\ {F'3=R3PP|ZjZH-/ HjjjHHHXHHjjmzf#:WWWWWMWRWMWMWFFW5W5WOW-WH-W$W%W%W'W/%WWW6W6W0)WOWLWLWLW^LWWWWWPWLWFWLWLLW/W9W?W?W??W6W5W6W6W65WLWLWLWLWLhWLWFWLWLWLLWWWWWVWWWYWWWV\W8W7W7W8W88WGWEWEWEWEEWWW9W9W:9WWWWWLWWWWWLWLWLWLWOOW0W6W6WW)W/W'W%W%W$%WHW-WOW5W5-WFWMWMWRWMFWWWW7YVVVVVVVV````````````hX=k=kF'F'PPP=FB&\  ~ou~EMWY[]}  " & 0 4 : < > D ^ o u x  !!!!"!&!.!N!T!^!!!"""""""")"+"H"a"e###!%%% %%%%%$%,%4%<%l%%%%%%%%%%%%%%%&<&@&B&`&c&f&k&o,m,w.!6<>ADO# tz HPY[]_  & * 2 9 < > D ^ j t w  !!!!"!&!.!M!S![!!!"""""""")"+"H"`"d### %%% %%%%%$%,%4%<%P%%%%%%%%%%%%%%%&:&@&B&`&c&e&j&o,`,q. 8>@CF 3+&sh. 41)("D7(JI@=:74-&PML/-,)&63ڔaa/  bcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./2345~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~O   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`apcdhvnj#tiB=qDEfu698o@kzXbm<RA7l{8wox@G[ZYXUTSRQPONMLKJIHGFEDCBA@?>=<;:9876510/.-,('&%$#"! , `E% Fa#E#aH-, EhD-,E#F` a F`&#HH-,E#F#a ` &a a&#HH-,E#F`@a f`&#HH-,E#F#a@` &a@a&#HH-, <<-, E# D# ZQX# D#Y QX# MD#Y &QX# D#Y!!-, EhD ` EFvhE`D-, C#Ce -, C#C -,(#p(>(#p(E: -, E%EadPQXED!!Y-,I#D-, EC`D-,CCe -, i@a ,b`+ d#da\XaY-,E+)#D)z-,Ee,#DE+#D-,KRXED!!Y-,KQXED!!Y-,%# `#-,%# a#-,%-,CRX!!!!!F#F`F# F`ab# # pE` PXaFY`h:Y-, E%FRKQ[X%F ha%%?#!8!Y-, E%FPX%F ha%%?#!8!Y-,CC -,!! d#d@b-,!QX d#d b@/+Y`-,!QX d#dUb/+Y`-, d#d@b`#!-,KSX%Id#Ei@ab aj#D#!# 9/Y-,KSX %Idi &%Id#ab aj#D&#D#D& 9# 9//Y-,E#E`#E`#E`#vhb -,H+-, ETX@D E@aD!!Y-,E0/E#Ea``iD-,KQX/#p#B!!Y-,KQX %EiSXD!!Y!!Y-,EC`c`iD-,/ED-,E# E`D-,E#E`D-,K#QX34 34YDD-,CX&EXdf`d `f X!@YaY#XeY)#D#)!!!!!Y-,CTXKS#KQZX8!!Y!!!!Y-,CX%Ed `f X!@Ya#XeY)#D%% XY%% F%#B<%%%% F%`#B< XY%%)) EeD%%)%% XY%%CH%%%%`CH!Y!!!!!!!-,% F%#B%%EH!!!!-,% %%CH!!!-,E# E P X#e#Y#h @PX!@Y#XeY`D-,KS#KQZX E`D!!Y-,KTX E`D!!Y-,KS#KQZX8!!Y-,!KTX8!!Y-,CTXF+!!!!Y-,CTXG+!!!Y-,CTXH+!!!!Y-,CTXI+!!!Y-, #KSKQZX#8!!Y-,%ISX @8!Y-,F#F`#Fa#  Fab@@pE`h:-, #Id#SX<!Y-,KRX}zY-,KKTB-,B#Q@SZX TXC`BY$QX @TXC`B$TX C`BKKRXC`BY@TXC`BY@cTXC`BY@cTXC`BY&QX@cTX@C`BY@cTXC`BYYYYYYCTX@ @@ @  CTX@   CRX@ @@ @Y@U@cUZX  YYYBBBBB-,Eh#KQX# E d@PX|Yh`YD-,%%#>#> #eB #B#?#? #eB#B-,CPCT[X!# Y-,Y+-,-A! ?9U>9UB@A@;3:U839U@@ O P(F(F*F+_O_ F@FF@36FFUHU2UUHU=UU=U@F<P&(Pp@2F?Oop?а/?Э/?ЪO/o$PoF0@pЏO_oF1ts?sP&on<nF5U3U3U`P&_P&\F1[ZHZF12UU2Ul <Ll|Q@dQ@Q58F@Q%(FPIF HF5GF5FFFF2UU2UU?_/Oo?oOTS++KRKP[%S@QZUZ[XYBK2SX`YKdSX@YKSXBYststu+++++stu+++t++ssu+++++++++++++++++s+tstusts++tus+stsststtsts^sstssss+ss+++s+tu+++++++++++++t++^s++^st++++ss^ssssss++++++^}y:wW~j`jy"3kkk{Rni`[^^eoz iq4 HjgaAhLLLLXPHld p $ T 0 ,  h4XlD p@ xh !"##&P')x)*<*p*, ,P,-./H0 01234(5\6 689\9:;< ==>@?AC`EG(GILJJLMN|O<PQRS<TpU|VV@W|WX$XYPZDZ[<[[\L\]L]^^\^_l__``0`d`alaaab,bdbbbc$cddDdtddeexfDfxffgg@ghhi,i`iijkhkkkl$lXlllmn n<npnnoo4oppq q@qxqrPrrrssPs|sstt8thtttu(u\uuvvvw(wXwwwxxDxxxxyy8yhyyyz$zX{({|,|`|||} }D}p}~~@x(XpHt4L(PDt$L4`@t(\0d0`LTT<8X(4p,H\X0@X XD t8|$P| 8h,`0P 8l°8lŠ<tƤ4L|Ǭ`0dʬ@pˠ@p̠@pͨ@xΰHπϰPЀа(ҠXӌӼ4H<(׬,\ؐب@tٸLڐېܐ`ݰHT<TLpp<|pxd(8@4DTxx(P p H   D  8 4ph LHX@` , T !" "L##$%&()*+(,,-h../8/001 1x12l233444`445@5666677L7788H8|889 9@9t99:8::;;h;;<$<=8??@4@A0A`BB,B<BtBCCLCCDDD`DEELEEF8FpFGGGHHDHHI IHIIJJ@JPJxJJKK@KKL@LxLLMMlMMN NXNNNO4OtOOPPTPPPQ<Q|QQR$R`RRS(S`ST TPTTULUtUUV<V`VVVW$W\WXXLXXYY@YYZ(ZlZZ[ [P[\L\]4]l_``X``a0adaab,bc0cdccdd4ddeee0edexeef fpfffggTggghhiiHijkkhkllXnPnooopppppqqqrr(r8rrs s0sssttuv|vxxy y<ypyz{\{|}~T~Px00T<tpxT L8l |H$`l 4DTd\$4Ld,<dt4DTP8HXh`tLDT D$¬DT@PŴ0ƨ0Ȁ$ˀ$X̌|ͬΨθѨ <ҸP՜֔א$ؤ`یlP4`T(@x`8,0H4T|@H0|<p(00<DLd P  t  0      4 8h||HP4Dtp8d$l L @pLdt  D x !`""4"h""##8#l##$$<$p$% %X%&8&'(<()***+,x-@../l001H1X1h12l3@445H5X5h5x556670778 8889L999:;;h;;<D>?t?@h@@AAABBBBBCCDCpCCCDDPDDEFFFGhGHHlII4IIJxJKKL<LM\MNpNOPPdQ QQQQR4RSSTUUVLVWhX8XXXYpZZZZ[[\\]`^^p^_D_`p``a`bbbbccdeLeefffgHghi8ijhjkXkl`lmm|mnLnoopPpqhqrrst|u(vtw wxty yz{{|X} }~~~Hph(x4\DXld<P@P\Dh Td\ xPlX<plHhx` T( 0,\`t,\t40 DÔ84ńdƜLnjLȜ(Lxɠ(Xʌʰ4\ˈ˴ D̼̈,T̀ͬL|ά <hϔ0\ЄаTфѸ<hҐҼ@hӔ PԀԨ4`Ռո<pּt׬0؀شH|٬<tڠ,T|۰P܈$LtݠHtޜPߜ@p,`(X<p8lD|LDp<tH$\4h0\H| T<h@lP(\D(\$P|<p @t,`0`(`8Xx,PP8\(\@dHxH$Hl<p4X|L X P $ X     4 X |     P     H x    < p  PH0\PD@lTD,X4`,h0Tt0|L$L,H  H   ! !0!" ""# #t#$ $@$p$$% %0%T%x%&8&l&&&''T'x'''( (@(((((((((((((())\))**P**+4++,,-4--.H//T//00@003334 4`445 5<566`667 7l789,::::;;;(;= >(>?@BDpDEFGxHILIKLMNOPQQRSTdUdVVWXYYHYtYZ$Z|Z[[\@\\]^ ^_``aPaabclcdeg<gh|hi|ijjjkkHkklldlmm\mnntno,opplpqHqr rrsLst4tu8uvvwwx xyyz8z{{{|,|\|~@4hL<<d4P(|HLT@ \PP|h4l8p\d(Tl 0@P`@(Lp8\ 8l0H`x@xhhX TLT ,L\l|  4H\p0@P`p,$|$x€,t|4ŀ$ƀ8ǀx4Ɍ |$|<̌,̈́TάLϤdXѤl$lӴx8Ռ4֐8נ`بPٴx Xۼ ܄$t4ޘDߔD\dh0|h x `(p(ttld<D@DHDX\L$h(t\ 0  \  h  | 0  <  L\,D\t2@  ?/993310!!!eL5@  @[  r b T D 2 "           r d T D 4 $   g     y I = -           } o _ K ; +           } k [ M = )   7       @[ y i [ K ; -        { k ; +        ` @   ^]]]]]]]]]_qqqqqqqqqqqq_rrrrrrrrrrrrrrr^]]]]]]]]]]]]]]]]qqqqqqqqqqqqqqqqrrrrrrrrrrr^]]]]]]]]]]]]]]]]qqqqqqqqqq?/+_^]]933310#353gW#@  ?3]2993310#3#3jyE iy@h    !     O?O   /333?33399//]q]q3333222233332222993333999910!!#!##53#5!3!33!!NXnVTnTNYnXkXnX@PjNulhhlqlhhlqrR$,3@- ))##$11$%$ 4522sY)))x11w1- 1)%}@H@ @ H*sY#"pUe/2]]]2+3/+_^]+33]]9]]]]]]]]_]]+393333333333310%$7.546753.'#4.'>VFS%|*zuX.|4b\2coU%wx ,F[hI !^i C*FXxQ AT7%, t;R8I '3W@5" (. 541Y[+Y  Y [%Y?+++???+++933333310#"&54632#3%2#"&5464&#"3264&#"326Ԣ;ߟ]M[[QO[XRLZ^PP\WQp %ưH6#/9u@F4* $!0,2  :;2''QY, 70? 7QYPY?+?+/_^]]q9/999+999333310"'#"&5%.54632673274&#">&'326yKiW!0oq:?`pG.8gdV`dA{?Jy웆G AFϸ>FvZϦ+byH[g[r5NZdy7h @  ?]9310#3 X"@   ??93331073#&!,. X+"@   ??933310#6'3+43!S@2    *%   ?]]999399]]3]]3910% '7%73-ww- ZgIHHIk)dG C@&  _ Y 7?3]]3+33_^]_]933310#!5!3!X`TT "@ [[/++993310%#65#5&({^XۨjA~[Op@Y//]q+99105![Р~@ [/+93103539??33103i P# (@  sY sY?+?+993310#"!2#"32#rckj1 +@ tY?+3?33/39331035!5%3!gMW<g >@   sYtY?+9?+3993331035>54&#"'>32!g3Oys Ksu||Vt}qɹR^FN(c@9" "%)*%tYMMsY sY?3+?+39/_^]+++99333310#"&'7!2654&+532654&#"'>32$fbw 뗐srqzoŰ/7 6@sY ??39/3+399333310#!533!qh4 6??Lw^JR^@5 sYtY sYgs?3]]]+?+9/+933393910#"&'732654&#"#!!632 9쑤I~?/!uѯ.7AZh"P@+  #$uY sY    sY?+?3_^]+9/+39333310#"3 &#">324&#"326?S51s巖~~bRn[_֙Яi  *@ tY ??+39993210 #!5! زY UY$/U@.+ % 01 "("(uY"""uY-uY?+?+9/_^]+999333310#"&54675.546324!"3264&#"!26{st}#)Ŋyħy xwyu}ݍ`$T@. %& !!sYsY sY?3]+?+9/_^]+39333310#"&'732#"546324&#"32>+6(tĜNMz  ZmϱG~:'@ [[?+/+9933105353k: .@   [ [[/++?+93310%#65#553&({^XϜjA~eH<@'?0p?o/]33]2]29105 eZ;dXG?@( YO_ @YP/]]+_^]+9105!5!dXeH<@'0p??o/]33]2]291075 5eZ㚙on^T'"R@,!   #$ ?   [  _Y?+3_^]/+_^]99333310#>54&#"'6$3253',R]PHF'>NPM<%KvdD;4sDEhP?99FX;rz =n?N~@F)8G@@!18OPY JYCY     4<<%Y<0044-Y4/+3_^]?+99//_^]3++3/+9333333310#"&57##"&5463237332>54$#"32$7#"$5!24&#"32676nsclBqR't%QPNԝ)Ƒ*7^neZ_c}(ӤXXF{{̵Y^mٞKWpW[af}xҝ\R[@6   _Y P`0/]]]]]]qq?2?39/+93233999910!!#3 !&'~?6[ 1dS1EW h@:  _Y$M>_Y_Y?+?+9/_^]_]_q++993333910#!! 4&#!!264)!26AQs}rbBshy^@9  _Y@P  _Y  ]?+3/_^]?+3/_^]933310"3 #"$5!2.(WɣlB.G1%NIQ~<{e ,@ _Y_Y ]?+?+993310#!! )!26ef:~ T@2  _Yy_Y _Y ]?+?+9/_^]]]q+933103!!!!!-2< 6@ _Y_Y ]??+9/+93310!!#!ggb@;  _Y_Y _Y0@ `  ]]]?3/]q+?+9/_^]+933310!2.#"32675!5!#"$gpM$O<ӝJ[UpWx6xnTHr}K  r@  _YP@.Iy      p ` P  ]]]]]]]]q?2?39/^]]+]q+99333310!!#3!3asT|@a@0 9p`P@P@p`P@ ]]]]]]]]qqqqqqqqrrrrrrrr^]]]]]??931033 hF@*   _Y _Y@ `P@ ]]]]q?2/]+?+93310 73265!5!C~_hxrtE#? 4@    ?3?399333310!#33 R͸>/@_Y?+?9931033!R@   pdD4 t`T4gtPD$dD4tT47tD$ dK4pP@? ^]]]]]]_]]]]]qqqqqqqqrrrrrrrr^]]]]]]]]qqqqqqqqrrrrrrrrr^]]]]]]]]]]]qqqqqqqq?3?33399333310!47#/#3>73V 1'8!w%3 pe@noT/;(  P@/    p`P ]]]]]]]]q?33?3399333310!#3&53: aXHXa0@ _Y _Y ]]?+?+993310#"$5!2#"32שŦrJ< MR},- <@  _Y_Y  ]q??+9/+9933310#!#!2)! bQ@a}$?@$%&_Y"_Y _Y & &]]/+?3+?+93310327#"&'&$5!2#"32)f7<]U>rJ< #~p  CR},-h W@/    _Y_Yp ]]]?2?+9/+3933339310!!#!24&#!!26I;͗Iվ{]-@ #/. HI Y i  #@9HF#V#f# #  # _YoYK  _Y`RD?3]]]+?3_^]_]]]+99_^]]+]]+9333310! 732654.'.54$!2.#"R г?r`d53EAvgL+f%w{EV8&%J[zOē!pepoAU;++:Tr.0@ _Y{ K ; $       _ O 0  g    _ O       p _ @     o _ ?   7    o P /      o P @        ` @ ?   ^]]]]]]]]]]qqqqqqqqqrrrrrrrr^]]]]]]]]qqqqqqqqqrrrrrrr^]]]]_]]]]]]qqqq??+39310#!5!о圜)I@,  _Y p`P ]]]]]]]]q?+?3993310"$&5332653ۭĹӾ~d M>@& P 0 ` / ?3?3]]q9333310!#373TT  @  |H9* xi:JZ) h|k\K<+ m_M/?m}[M;- 8@o{mK[9+ }k]K=+_  ?333?333^]]_qq_qqqqqqqqqqqqqrrrrrrrrrrrrrrr^]]]]]]]]]]]]]]]qqqqqqqq_qqqqqqqrrrrrrrrrrrrrrrr^]]]]]]]]]]]]qqqq+q933_^]333]]33]310!#&'#3637>3.$a-&?8 "Ttdngו#s.+ @     K    4 D jT d ; $       { d 0 $       p d @ 4   9      D t $ T T d @  0 wx ?2?39]]]_]]qrrrrrr^]]]]]]]]]]]qqqqqqqqqqrrrr^]]q9333310! # 3 3 XYP} h)b-)@ H v b T F 6 $          p d @ 4 $   i        t ` P D           t d T @ 0 $      t T D $   9    p d T 4 $    @3    T 4       p ` 0 /  ]]]]_]]]]]qqqqqqqqqqrrrrrrrrrr^]]]]]]]]]]qqqqqqqqqqqqqqrrrrrrrrrrrrrrr^]]]]]]]]]]]]]_]qqqqqqqq??39^]33993393910#3 3 HH9aA J@+  _Y_Y p ` P @ ]]]]]?+3?+3393310)5!5!!ZVW)&@ YY?+?+9310!#3Wu9??33103i W&@ YY?+?+931053#5!Ws 7@o )i~FVVfN&6f6vFVHKH@LBEHDTutTATTtUXH@-;>HrpBRbr9`d_^]^]r^]++^]qr^]qr^]++^]qr^]qr^]^]?9333310 #3΢pry i@ Y/+33105!ij)@[/?/]+993310 53WsN#0@V )).21QY )QY?o  PY$PY2222p2`2P2022]qqqqqqqq?+?+3/_^]q9/+9?+93333310"&546?54&#"'!2327#"&'#'2>=pxyn .*;!DGd[EZcYF_;rRZ$.PQpip|gZSY0dQX`#]@7  $%PY !PY%?%%p%%%%%]]]qqqrr?+???+9999333310!"&'##6533>324&#"326r{32zxy"Yc 6YAXhZWNf@E  PY p`p  PY ]?+3/_^]q?3/]+9333103267#"32.#"`ri"hl ZjV"V@1$#  PYPY$p$$$$$]]]qqq?+?+99??99333310%#"!23'3#.532654&#"52z{2xyhZ6Zby6t*pWNw@F PY  PY PY p`P0qqqqqqqqq?+?+9/_^]+9/93333103267!"3 '.#"uaݺ^H- <@h  PY PY/O_?;_/@VdH@',H 0`@]q++]qr^]q??3+3?+929333210##5354632&#"3iK4-#E>Iz F\aVWK .@d! (0/ %PY+PYPY @0 0000 00P00O000/00000^]]]qqqqrrr^]]]]]qq?2^]]+?+?+99?93333310"&'73 5##"32346734.#"32>${d 3wǻs.HS~vUHWKQ;hiia68Ƅed`@; PYp]]]]]]]qqrrr?+?39?9933310>32#4.#"#3=:}*`Ujc/ro4~= =n@H SY       p         O  ]qqqqqqqrrrrrrrrrr?+??933310533 :W=@  PYSYo?oP@0 O?/=pOp]]]]]]]qqqqqqqrrrrrrrrrr^]]]]]]]]qqqqqqqqqrrrr^]]]]?+?+?933321053#"'52653xxM2>E8 Z Hh @g     ?  ? _   ? _  9 @SVH`   `   0 @  ????9^]qqr+^]qr93323993310!#33 0Ima />v@QpOp]]]]]]]qqqqqqqrrrrrrrrrr??9310334#N)~@)! !  +*%PYPY ! d+K+?++++++++++{+o+;++ +j++++++[+O+++++++++d+K++++++++++k+4+++9+++++t+[+K++++ +++++{+[+K+++++++`+O+@ 0+/++^]]]]]]]]_]]qqqqqqqqrrrrrrrrrrr^]]]]]]]]]qqqqqqqqqqqqrrrrrrrrr^]]]]]]]]]]qqqqqq?22??+99?+9933393310!4&#"#4'33>323>32#4&#"Vps:l{8qVpvxS*,9OsZbkm`/xNa@<  PY  p]]]]]]]qqrrr?2??+99933310!4.#"#4'33>329*\Y>ykv4S*,9Op]/VN H@, PYPYp`P0]qqqqqqq?+?+993310#"!24&#"326꽅!0WM$]@7 &%PY "PY&?&&p&&&&&]]]qqqrr?+???+9999333310!"'##4'33>324&#"326rV0ƽzky?{"ʼY61fd]ZVWN"@T$# PY PY@$ $$$$ $$P$$O$$$/$$$$$^]]]qqqqrrr^]]]]]qq?+?+99??99333310"!234673#7#4&#"326{66Ҋxy6We;6k[>N#@  ???3399331034'33>32&#"+pf$%$r%f 9K*d@<" +, "PY PY,,,,,`,,?,,]]]qqqqrr?3+?3+999333310#"&'732654&/.54632.#"!XbJʳnzt0^~I(+WQTT@P"(MnP~HMJK.<*%$=Ja*,E@$   PY    @PY]?+?_^]3+393332310%#"5#53733#327*Y]}5x3?$D҃UN?:_@;  PY  p]]]]]]]qqrrr?2??+3993331032653#.'##"&5:*\Y>y:Rkv4s*,9Op]: \@     ` T D          ` T D   g    T D       [ D       [ K   7    [ K ?          ` T D         ` P /   ^]]]]_]]]]]]qqqqqqqqqqqqrrrrrrrrrr^]]]]]]]]qqqqqqqqrrrrrrrr^]]]]]]]]]]]qqqqqqqq?3?39333310!#3?3ew 8#':@(uv:@    vfTF6$fTD6itfF6$iVD6r`T$8tK0$@0{dD4d?^]]_]]]]]]]]qqqqqqqqqrrrrrrrrrr^]]]]_]]]]]]]qqqqqqqqqqqrrrrrrrrrrrrrr^]]]]]]]]]]]]]qqqqqqqq?3?33^]3]93233333310!#'#37373ѽ$ &Ѳ$.Ͱ-0:!J[: T@    v D T d 6 $         v d   & F V g F V  d V D 6 $      & 6 F 7f  @6=BH9 "       t ` T @ 4   @"H   P p  ?3?393^]_]+qqqqqqqqqqr_rr+r^]]]qqqqqqqqr^]]]]]]]]]qqqqqqq9333333310! # 3 3 ! D,[W:@  PYtdRB4$tdVB4$gtdVB4$p`TD0 p`TD0 7@Z`TD `P0 P/^]]]]]]]qqqq_qqqqqqqrrrrrrrrrrrr^]]]]]]]]]]]]]]]]qqqqqqqqqqqq_qqqqrrrrrrrrrrrrrrrr^]]]]]]]]]]]]]]]]qqqqqqqqqq?+?33339333310"'532?373J2&.bSLF`CtW +5' ƭSS: b@ PYPY      t d T @ 4            t d T D 4 $        t d T D 4 $   7      d D          d D $        p P   ^]]]]]]]]]_]qqqqqqqqqqqqrrrrrrrrr^]]]]]]]]]]]]]]qqqqqqqqqqqqqqqrrrrrrrrrrrrrr?+3?+39331035!5!!S]s&ڋ"W#_@: "$%YO//O Y!Y?+?+9/_^]qr+9933310"&54&'5>546;#";inmj?[MjXYiM[?Wiussujkl^ajmN]A@t`TD4$td hpdTD4t;+oP@0 8p`P@0 p@/^]]]]]]]]]]]]qqqqqqqrrrrrrr^]]]]]]]]]]]]_qqqqqqqqqqrrrrrrrr^]]]]]]]]]]]qqqqqqq/?9103N~"W#_@: #$%YO//O ""#Y"Y?+?+9/_^]qr+99333102654675.54&+532+5^[OhYVkO[=#534632.#"!!!27PFYVē"oGrph\M7.yym9@Ks}~w)qs'B@!" ()) Y@%Y /33+22+_^]993333331047'76327'#"''7&732654&#"Ndhcrrah`PRdfermiffNsrqqrdgeRPai`urdieNPiifruvuv@O   QY QY/  @)-H   ??39/]^]33]+q2+3+333933333933223310!!!!#!5!7!5!3 3A}@[sw}/}yN]U@  t ` T D 4 $       t d    h   p d T D 4      t ; +        o P @ 0    8   p `      P @ 0         p @ /   ^]]]]]]]]]]]]qqqqqqqrrrrrrr^]]]]]]]]]]]]_qqqqqqqqqqrrrrrrrr^]]]]]]]]]]]qqqqqqq?/99//93331033  sT3@@_$4 11+.:++BAy$k$\$8$>>5>7 7z7;7 F    7>$!QYQY?2+/3+9_^]]_]]]]qq]]]]]]]99399333322323102&#"#"&'732654.'.5467.5464&'>L}uȽ`r tLMP©!ܧܨ$#yh!ED#-@Q,!''./(YH H$$Y P  Y///p/`/P/@/]]]]]]]?+3/_^]3/+39/3+++99333333310"&546?54&#"'>32327#"&'#'26=l~FQCQ #1"IQIZvTtgt|7>54&#"'>32!+kaXGJDX zd3gEJDp:>KIDk{nZ\-q'%@O"   &'#  Y?O/?O  YY%5E?3]+?+3_^]]9/_]]+9993933933310# '73254+532654&#"'>32 =9P\JGDT VZ[jt mHA?>733267#"$#5,R]QGF'>NPM<%q2KvdD;4sDEhP?99FX;rz R&$N&%+5+5R&$@ &L%+5+5R&$`@ &%+5+5R&$ ^@ &&%+5+5R&$l@&%+55+55R&$+@&6ESs"b%+]]]]55?55o@;  _Y _Y  _Y _Y?+??+39/_^]+9/+9992223239910!!#!!!!!#! E !d<?hNy&&x : %+5&(? &  %+5+5&(@  & (  %+5+5&(w & %+5+5&(y@  & %+55+55 &,&%+5+56&,F@ &E%+5+5h&,@ & %+5+54&,@&%+55+55e T@+    _Y  _Y _Y?+?+9/_^]3+399333339103! #!#%)!!!26fj:~!`H9 &1 @ & # %+5+5a&2&ش%+5+5a&2%@ &%%+5+5a&2@ &!!%+5+5a&2 &$$0%+5+5a&2@ &%+55+55s #@   /q933310 7   bh^^i`fJb`g_iiaG$E@#  &%""_Y_Y &]?3+?3+999933339910#"'#7&!2734'32&#"שxȮrJyɬb;ze|pKR}n[-UX)&8&%+5+5)&8@ &%%+5+5)&8@ &%+5+5)&8@ &%+55+55-)&<@  & A %+5+5 6@ _Y _Y  ??99//++99333310#!#3!24&#!!26tۖb߀ŏ1m@A,' ', 23$+    $$PY$  PYp3O3?3]]]?+??+99_^]_]]]]]93933210#"/32654&'.5467>54&#"#4632p4E\bUa\[96:5mqO"7R0'1(VO@f:6V=d-0T2M]案gH1&;9 |Ws&DC11&225%+5+5Ws&DtT@ 1&1 14%+5+5Ws&D22&771%+5+5Ws&D11&::F%+5+5Ws{&Di@ 11&5ʴ53%+55+55Wss&D@ 44&7ȴ71%+55+55BN'4;@^- "4;4455&&&<=5'PY 555 " $$8PY$(QY ?o  PY 0PY PY ?3/]]+?+?+3/_^]q9/+?+999/_^]+99333933399333103267! #"&546?54&#"'!263 %32>5%.#"uafOҒoy~q .cvPÅBd]fW^H-u;oP\$5eJWaYVīWNN&Fx ( %+5W&HC& %+5+5W&Htp@ &T %+5+5W&H@ &   %+5+5W{&Hi@& %+55+55 &C&´%+5+5/&t?@ &?%+5+5i&@ &  %+5+55{&i@&%+55+55V''s@$   "()   PYP@  H$ 4 D   R    %%PY?+?99//_^]]+]3+3/99939210"54632&'57&'3%4&#"3266^m}mPZ2ӫ<;rr^WG$Bp\j&Q@ &$$0 %+5+5V&RC&%+5+5V&Rtg@ &I%+5+5V&R@ &%+5+5V&R@ & ,%+5+5V{&Ri@&%+55+55A$u J@*   YP @YYO?]++_^]+99933310535!53ި,\"}@N $# PY PY$$$$$$$$$$p$`$P$@$ $$]]]]]]]]]]]]]qqq?3+?3+9999339910#"'#7&5!2734'326%&#"XvdSs[QDCbt֊0[iɅ\X݂U1Q&XC& %+5+5&XtW@ &5 %+5+5&X&!! %+5+5{&Xi@ & %+55+55W&\t@ &6 %+5+5W!>@  "# PY PY??+?+99?9933331033>32!"'##4&#"3260rVzky?{YAXd]ʼYZW{&\i@ & %+55+55R&$hI@ &%+5+5WsS&D11&2ʴ21%+5+5R&$ y@ &%+5+5Ws&D11&4̴4:%+5+5`c&$ ϴ%+5WUsN&D:´::%+5hy&&S@ &~ %+5+5W&Ftg@ &r %+5+5hy&&@ & &  %+5+5W&F@ &  %+5+5hy&&"%@ &' %+5+5W&F,@ & %+5+5hy&&@ &&" %+5+5W&F@ &" %+5+5e&'f&%+5+5V&GK@ ++S++%+5?5eVm*s@-%+,QY/ (PY@ H"PY?,,]r?+?++99?9/_^]3+3?99333339210%#"!23'5!5!533##.532654&#"52z{2,xyhZ6Zby)6t*p&(zI & %+5+5WS&H@ & %+5+5&(  & %+5+5W&H@ &# %+5+5&(% &  %+5+5W&HD@ & %+5+5U&(P´ %+5WUN&H}###%+5&(o & %+5+5W&H&" %+5+5g&*@  &%"%%+5+5VW&J@ 00&55/%+5+5g&* @ &"'"*%+5+5VW&J@ //&228%+5+5g&*5%@ &'!%+5+5VW&J-@ /&//1%+5+5gN&*N #.#%+5VW &J877&//3%+5+5 &+@  &  %+5+5>&K@&%+5+5@#   @(H _Y_Y @ ?2?399//]q33+33+_^]+]q99]]333333333310!!##5353!533#5!fs-  s@#!"@"P"`"@"""""@HQY PY H?++?39?9/3+3+_^]]qr393333310>32#4.#"##5353!!=:}*`U,YjcWro4= &, @ &  %+5+5&@&   %+q5+5 1&,I@ &%+5+5 1S&@ &%+5+5l&, @ &%+5+5l&@ & %+5+5\U&,  %+5U}&L@ %+5]|&,'%@ &%+5+5v: @$t4$n@4$tdk4$8td+{k@0 p`@ ^]]]]]]]]]]qqq_qqqqqqrrrrrrrr^]]]]]]]]]qqqqrrrrrrrr^]]]]]]]]]]q??931033´:I&,-W&LM@o0]55]]55 &-7@ & %+5+5W/ @ [/? PY?/o?oP@0 O?/=pOp]]]]]]]qqqqqqqrrrrrrrrrr^]]]]]]]]qqqqqqqqqrrr^]]]]]]]?+?/_^]+9333393310"'52653#'##53MM2>E8xjihW Hh@nN?&.ʹ  %+5N&NN  %+5: A@%   ?  ?2?39]]39333310!#33 0Il~: //&/&^ %+5+5[>&ON@ &K%+5+5N/&/ %+5~NG&O%+5/&/@  %+5?5i&O$K)@O/p  %+5?5]]q/&/ _%+5&OBT%+5/ F@%   @    _Y?+?9/_^]]9993333310!!573%hyUU I@+   O    p  ]]]]]]??9/]99333331035737zz||DDXHGz &1@ &I %+5+5&Qt@ &a %+5+5N &1 %+5NN&Q[  %+5 &1& %+5+5&Q&# %+5+5P&Qb$$״$$ %+5?54$=@ !!&%_Y_Y?2+???+9933310"&'732>54&#"#336$32_;ZjIU&wyHMJJsnOBheD=aqWN#;@!!%$ PYPY?+???+9933310"'52654.#"#4'33>32M2>E8*\Y>yxW Hhkv4S*,9Op]a&2I@ &%+5+5VS&R@ &%+5+5a&2 @ &&%+5+5V&R@ & %+5+5a&2 @&]$%+55+55V"&R @&g %+55+55a _@4  !"_Y _Y _Y _Y_Y"]?+?+?+?+9/+9992399310!# !2!!!!!%27&"#"CpFkiLoR4,I OLy <WV2N%,}@E! ,&-.,PY ,,, )PY  PY #PY  PY ?3/]]+?+?+99?+9/_^]+933333993103267! '!"3 6! %4&#"!26.#".uay|u~?*^H-!'S@h&5& %+5+5&Ut@ &J %+5+5Nh&5 %+5NN&U^ %+5h&5f& %+5+58&U8& %+5+5]-&6tI@ .&.[.1%+5+59&Vt9@ +&+]+.%+5+5]&6r@ //&44.%+5+59&V@ ,,&11+%+5+5]N&6x 2(2.%+59NK&Vx //+%+5]&6s@ ..&006%+5+59&V@ ++&--3%+5+5.N&7x^   %+5N3,&WxP@))/)_)o))?)O)_)o)))))/)_)))))))/)?)o))))) ))_)o)))))))/)?)o)))))) ))?)O)o))))))) )%+5]^]qr^]qr^].&7!& %+5+5&WK%+55.J@*   _Y _Y   ]]]??9/3+3+3933310!!#!5!!5!&85@'`pg&6FSs%+]]]55?]55s&X@&!! %+55+55)&8 @&Q%+55+55&X@&d$ %+55+55U)&8 &g@% ) )P)`)p)))))]q+5U:&XW$$$ %+5 &:y&  %+5+5&Z&%+5+5-)&<[ & %+5+5W&\@ & %+5+5-)&<h@ & %+55+55A&=@  & J %+5+5S&]t5@  & ] %+5+5A&=|%@  & %+5+5S&]  %+5A&=8@  &  %+5+5S&] & %+5+5 c@)`p@"%H?`  PY??+_^]]q+qqrrrrrrr93310!#4632&#">K4-#E> F\ +h@1&&,- )PYQY#PY H??+]q+9/3+3?+99?93333310353!!3>32!"&'##65#4&#"326 12zr{3Uxy9AXhZYc 6f!*\@/ ''"+,''_Y' ' &`Y_Y?+?+399//+99333339310#!#"&5463! 4)!264&#!!26MBsQADG18J=}~rbBs U@  `@#H _Y _Y_Y?+?+9/+_^]+]99333310#!!!!24&#!!26Hy%H@%  &'PY SY #PY?+??+?+99993333310!"&'##65!!3>324&#"326r{32zxy"Yc 6AXhZ 4@  _Y  _Y?+?9/+99333310#!'5%3!24&#!!26uە%8{i!x &@@ !!  '( $PY PY ??+?+99?9933333105%33>32!"&'##654&#"326 32zr{3xy!YAXhZYc 6_[f:@   _Y _Y ?+?+99//9933310%2# '6$3 ! 7ݗX7Bj<-؈* :Nx]1%NIQ~GM<{W$O@(  &%PY "PY PY ?+?+99//9+99333333103267#"32>32&#".#"`j v/4$+B7ri"hl Hy GMZje<@ ! `Y_Y?+?+39/933310#!#"&5463! )!26MBf:~DG18J=Q ?@   _Y  _Y _Y?+?+9/+993333104$3!!5!!"$73!!"Q|R%K@'  '&PY SY #PY?+?+?99//3?+993333310323&5!5!#.5## 32654&#"Rz23{ryx"ZhXA6 cY0VWN>@   !PYPY PY ?+?+?+9933339910!&/.532!4&#"32>dniZDdq}?YWX քUY :@   _Y _Y _Y?+?+9/+9331035!!5!!5!Y2-Ĝ^E@# ! _Y  `Y _Y?+?+99//+993333310%27!&$#"'6$32#"$547 'Ǜ9N30͢~y9M%>X&X@- #$$'(`Y## _Y !_Y?+?+9///+9993333339910".5467$4$32.#"!3#"3 `키 F2~bGGwUgw7Ш=vtevMW:@ _Y_Y _Y/+?+9/+933310!!#"'7325!g=R#3$hCNC@#    PY QY //]+9/3+3993333310&#"3###737>323;<@OF J^-g^a*X@.#** ,+!&_Y!_Y_Y _Y?+?+99//9++933333310.#"32675!5!#"$5! 54632&#"<ӝJ[UppM!z6B8 G>xnTHr}KWx{GM W?@"       _Y/+?3993392310"&54>73 34&'326s*OY?4""4.((.Wz-iivAy9GG:5;:$E@$ "" %& PY PY?+???+9?93333310"&54&#"#3363232653scnyzlɴE|~= ͺyy3>@ ??9310334! ,@  `Y??9/3+39333103#5333#Ħa`?H@$  _Y?3?+?99339933333910!#4632&#"3 R͸BB29~idU@+ SY QY??399//+?+9/33339339103 ##4632&#"IBB2B:/m ,@  PY??9/3+39333103#5333#ppmma`A@!         ?3?99//9993333310#&'#''7'37ʟþ)+D.I6:?Apf.kʽCvE͓9!F@$ #" _Y_Y?+?+?3399?93333310"'# 332653323#'\xc0cXwodw 2gGGCfUQUW 1@ _Y ?2?99/+993333103&53##"'5325 H1,8sHXa֐ VN3@   PY  /???+9993333104.#"#4'33>329*\Y>yVXkv4S*,9Op]aa%H@% &'`Y _Y #_Y?+?+?99//+99333333310#"$5!2>5#53#"32שŦrJLHXEXs} MR},jIj{=jw,-VN G@#  !"  PYPY?+?+?99//99333333310#"!265#534&#"326Xxp!0Aj0GaXL@@    _Y _Y/+?+9/3?3/933310%#"$54$32%3#/&#"327mwȥ:ԣ+d eU45LGG@m..VWNB@"   PY PY??+?+9/3?3933310##"!2%3"327&9QR3D+z@84W?',!0+Ar.B@"  _Y   `Y ??+399//+93333102#!##"&5463)! bMB{@DG18J=VW)F@%$ +* PY SY  'PY?+??+?+999333310!"'##4632&#"3>324&#"326rV6'%8<}0ƽzky?{"ʼY[d]ZCI@%  _Y_Y/??99//++3993339922310 !#3!2 4&#!!26g}uQվ{b*;@% ,+$ (( _Y( `Y?+3?+993993333104>7>54!"'>3 !2>7! $b>xP32^Kvf4~ZgK>Y@w!ĵMuUD()IgMB~%OK%;@!&' ##PY#  PY?+3?+993993333104>7>54#"'>32327!"&OQ\1oҷLd3:L{+[{Q##+=.V`RqN"'/C3ƧlRCW$;@ &%QY SY"QY?+?+9/+9333104632327#"&5#"&732654&#"Co^;:64EA=ThM<01<;20<ZeDK  gU1<<10<<W*,E@$  QY PY SY?+?+?3+393333310#"'5326=#"5#53733#327*CD82<6}5x3?$DBGq҃UN?3@   _Y??+39/933310##"&5463!оMBn圜QLr@@   `Y _Y?+?3399//+9933333310"$&5332653>5#53ۭĹӾysXé~dmt_j:%R@*$ $&' QY   %!PY!??+?339///+39933333331032653>5#53#.'##"&5:*\YsYXÐ>y:Rkv4sb#oej/*,9Op]W#K@& ! !%$ _Y _Y _Y?+?+?+99993399332210 47+5!32654'5!#"'њ6MM6O&Ts _` q&-@ _Y _Y?+??+9933310".53324&#"'632N[:2CNc ]-,@    _Y?+??9933102.#"#3 ><;T^%$1 rT7x-3-0H9aVGW<@  !  !SY PYPY?++?9?+99339910"'532?37>32&#"J2&.bSLF* McQlRDHa3D]W +5' XYj0]>T>G@%   `Y _Y_Y?+?+9/3+39333310!!5!!!!!5!> S l].8/:E@$   PY PYPY?+?+9/3+39333310!!5!!!!!5!/ 84_{iF[-VJ@&  `Y  _Y _Y?+3/+9/9+933333310 !5!#"$'7!2654$+SvGHFVF@% _Y`Y _Y/+?9/9++393333310#"3 # 4%5!!AGcqvS%j؋lHA3ꡜ]U$;F@$QYPY PY/+?+9/9+933333310!#"3267#".54675!KRQQ׍uؽs}\bx mNV:(R@+(#*)PYPY#(&PY/+3?9/99++39333333310#".54>7>54!5!3 7(ҊiUrddtOa4BeL\OnN+*Q:J=*w wRlH+".A0IRZ $N@( &%$$`Y_Y `Y?+3?+9/3+3933333310!>54&#"'>323!!!5>7!ZPJIys {A}d[%lPEOt}qɹ:ppt?WrY&D@$ _Y_Y `Y?+?9/9++393333310#"&'732654&+#5!!32&"#qJN«~uʜ._:G@%  PY PY PY?+3?+9/9+933333104!##5!!32#"&'732ۧ B6Ѽ" \U ]u$)B@" '$  ) +*&"#"QY'#PY?3+?39+3?9333310#"&'732654.'.=#5373[!RLfH2!j$HkFkTD-"*2CR7WQPX1?*+}[NWVM8@  PYPY??+?+999333310#33>32!"> ,pӾppdiEa`RKd@ ??9310334 @ ?2?3993310333344r:R@*   _Y _Y ??99//3+33+39333333310!3!!!!#!5!!rrrtt:̙`4 j7&''=d &+5 a&'']H &+5V&G']d --&+5&/-W &/MW&OM /&1-W&1MW&QMdR&$c@ &%+5+5Ws&D22&4۴4:%+5+5l&,@ & %+5+5& 0G&@. %Opqr]qr+5+5a&2&$%+5+5V&R@ & %+5+5)&8&%+5+5&X&$ %+5+5)+&8 1@& %+555+555k&X'i?@%&& &0&@&P&`&p&&&&&& %+555+55/]q]5)+&8 2@!!& %+555+555&X'it)@&&&& %+555+55/]5)+&8 3@$$& %+555+555&X'i)@&&&& %+555+55/]5)+&8 4@!!& !%+555+555&X'iCp)@&&&& %+555+55/]5VNA@!  PY PY PY ?+3?+9/+993333104&#"'!2# 53267ZuaX#C^H-?R+&$ 1@&%+555+555Wsk&D'i!@?<<<0<@<<<11&+55/q]5R+&$ 5@&%+55+55Wsk&D'.!@7?77707@7744&+5/q]q5&I&C%+5+5BS&X@ ==&>>?'%+5+5g &j@9%% && (' &&`Y_YO  _Y !_Y ?+?3/+99//_^]]+3+39333333310!5!5!3##"$5!2.#"32675!L[UppM$O<ӝJ\kYr}KWx6xnTHVWhK)6h@81 ** $$78' QY$ @4PY@ H .PYPY?+?+?9/++2+399333393310"&'73267!5!75##"&632346733#4.#"326${dixr3wƼs.QHT~wWKQX\5hiia6v[Ǭg&*@  &""(%+5+5VW&J00&228%+5+5?&.@ & %+5+5&N &ʹ %+5+5aU&2lVUN&RraU&2'lI@ 0&00/%+5+5VUS&R'r@ ,&,,+%+5+5-V&w!@ &$ %+5+5DW &R@ & % %+5+5W(&@ &W %+5+5 j&'= a&']V&G]dg&*G@ $$& _ #%+5+5VW&Jtk@ 44&0d03%+5+5a@  _YP@Iy `Y ??+??39/_^]]+]q+9333331032653#"&5!#3!3 vu3̲#sTW:@   _Y _Y /??+?+999333310#3>324&#"6Կ?oÐ_V#;H*Xabbu:- &1W& %+5+5&QC & %+5+5R>(.@j " )-  0/0000@0p0000 ))Yp&+++++@ H`++ ?&&&&/3//]]3339/]32/]+]9/]+3/_^]]q993933293310#!#.54632!&'4&#"326573;.á~$1=dd 5jN89NH6 :Lp7aDsc8Z1U&D'UtcZB@&N?NONNNpNNNNFF&IIL%7Դ71%+55+5+55/]]q5&& %+5+5B&t@ <&<&<ٴ<4%+5+5N&(tj@ & %+55+55W&H@ %%&"" %+55+55$&(j& %+5+5W&H:@ %&%% %+5+5ilN&,j@ & δ %+55+55WZ&@ & %+55+55P$&,,j@ &%+5+5B&@ &%+5+5aN&2j@ &&&## %+55+55V&R@ ""&%+55+55a$&2 j@ &&&&%+5+5V&RD@ "&" "%+5+5hN&5lj@ ""&e %+55+55&U@@ & %+55+55h$&5j"&"" %+5+5l&U@ & %+5+5)N&8j@ &ϴ%+55+55i&X@ &&&##  %+55+55)$&8j@ &%+5+5&X2&&&& %+5+5]N&6 228%+59NK&V //5%+5.N&7  %+5N*,&W@!X!!/!}!!/!?!O!o!!!!!!! !!/!_!o!!!!!!! !!/!?!o!!!!!! M!!o!!!!0!!!<@!!! !0!!!!@!!E%+5]qr^]^]qr^]qr^]_^]@U"F@!  $# _Y/3/?+3/9/33993333399105$54&'5,54&#"'>32W^*%IuAs>Uq8U@Pha2I(r𧆉TlOftY\<!V.N$D@ "  &%" PY/3?+3/9/3399333339910%5>54&'5,54&#"'>32.p@)! `eefiyr2@[0X_vGGuhA<ёmeV[!b{8) &+ & %+5+5&K@ &"%+5+5W1@    _Y  /???+999333104.#"#36$32E?yoRJWT}DbRO\VVt!-9g@7.4( " ;: 7PY +PY1PY%PY?+3/+?+99?/3+99333333310%#"!23'3632#"''67532654&#"4&#"32652z{2A G=4?hZ6ZbywSq>u`pU0AP^9]w'2^@2.$(  34!+!+`Y`Y!! 1`Y '`Y?+?+99//++9999333333910#"$54675.546732654&'4&#"3 ~~彩܉ARŢ|%}aSTY^yl|_,'4P@)"  1%+65((QY"!.PY?+?339/+99993333339102654&'7#"&54675.5467"32654.E}QII{po{IIQ}Ij}Q~#qDp ɏԐ pDq#~Q~WNA<@ _Y @_Y?+3?+39333107!5!!2'654&#!AZ|GMV~MM"8 G>1 ::@  PY PY?+3?+39333107!5!!2'654&#!18jGM&psGV"1'?<R&$%@ &%+5+5Ws&DJ44&2۴24%+5+5N&(xWNN&Hx2a+&2 1 @""&  %+555+555Vk&R'i%@!!?!!!0!@!!!&+55/q]5a+&2 6@'&''3%+55+55V&R'J@/22?2O2_2o22&+5/]q5a&26%@ &%+5+5V&RE@ &%+5+5a+&2 5@&!!"%+55+55Vk&R'K!@?0@&+5/q]q5-)&<eI@  & %+5+5WS&\@ & %+5+5V>@ PY   PY ?+?9/99+393933310632#"''674&#"326>D;H{JOnb9:&> G=4?swSq>uV0AP^9VtN(4f@9  /$()(& 56$(""2PY""" "PY ,PY?3/+??+9/_^]+99333333104.#"#4'33>32632#"''674&#"3269*\Y>yD;}H{JOnyl9:&> G=4?kv4S*,9Op]nySq>u`0AP^9,%]@1  '& PY #PYQY@QY?+?+?3+9/3+3933333331053733#632#"''674&#"3265xD;H{JOnyl9:&: D<4?wSq>u`N30ATZ9W=: @  PY?+?39310#"'52653=xxM2>E8 HhS!-9c@6.4( " ;: 7PY1PY +PY%PY?+?+9??+?+?933333333310%#"!23'33>32!"'##532654&#"4&#"32622z{22zrdxyxyhZ6ZbyYAXhZïpSWL!.:_@55)/ " ;<%PY 2PY8PY ,PY?+??+?+?9?+933333333310!"'##7##"!23533>324&#"326%4&#"326rV4}50ƽzky?z*xx ̼YegU6Xdd]ZR f@7  _Y_Y `Y ?3?+9/99+3/+93933333210!!#7#33 3.'3#q¢A?fݢTq6, 1&Pkh1Sqhy%@O  !$ '&#@P @_Y$  _Y ?+3/_^]9?+3/_^]9933333310%&5!273&'3 #"'#"&VwwlBNtz=?p(Wл[I-[{b.Q~1W%NDe& W%e@9 !  '& @PY!  #PY?+3/9?+3/99333333107&323&'3267#"'#&#"I<Ɂ "7Q`tXŎ -0",Y5=VD..#hl %F˰e / ?@   _Y  _Y ??+9/3+399922231033!!!!#qy*W.L@)    _Y _Y ??9+3/+9339933210 ##!5!733#A@C(;iiGVK;R@), 33&&=<3))0PY-)  PYPY?3++9?3+999933333310#"'3267#"/&'&'732654&/.54632.#"!FE"6`8g8~ICM9uXbJʳnzt0^~I(+ !q;*RTaWX=TT@P"(MnP~HMJK.<*%$=Ja1V:;@ PY PYPY?++3?+9933331072327#"./.+5!5!>QBD2 4<`8g81NE:%DN8/P#Dq;18G, $3L8@ `Y `Y??+39/+933310!3 4&#"'6$3 4KT$ ƹuvPN<@  QY PY ??+3/9/+933310!2654&#"'>32bmףۣ{Ï&!&i@5# # ('#`Y#_Y##_Y"_Y?+?+9/+9/3+39993333333399103! #!#%4)!!!264&#!!26!ć\sQA}UGrbBs)M@&   ! _Y_Y?3?+9/33+3399333333331033!33##"$&=#26=!)uuuu)XX~~s M8@ o 0 /  ??39]]]]93333103#'#H?zTT|  @U _Y _Y@ _Y _Yy_Y_Y?+?+9/_^]]]q+3/+?+?+933333933107#!733#!!!!!!3!kLFFS:|kj5<DX&"&*@J' )  "## ,+"#PY""**PY**%%PY)PY ?3+3?+399/+9/3/+?933333933310&323!3267!"'&#"%&'D^JͿX4Bua`PL3?M| E8ppi HhO欬aW#D@" !%$ _Y_Y_Y?++?+?9999333310327#"&=# !27327&#"5873/:NrJàvs sQC[UR}M8gdVWN ,I@&! '.-PY $PY *PY?+?+?993?+9933333310%7##"!234673327#"&54&#"32656{687&02J|xy1k[6We;lQC hO@'  _Y _Y ?3?+9/3+339933339922310!!##53!24&#!!26I;͗IIվ{NE@# SYPY ??9/93+3?+993339333103#5354'33>32&#"3#zz+pf$%$<r%f ϒ-)D@$   `Y  ??39/933+3393932103###53'3!73!ؾғ2?Ha'W:"X@. $#PYPY PY?+?9/993+33/+?9933932103##"'532?#533!3?!yoCtYJ2&.bhuFF+LS +NUUo'N#0W@.) .12QY)QY!)) PY$PY?+?+3/9/9+?+93333331023267!"&54&#"56323>"7>54&֣px{m .|*;!DGd[@]cYF_N;rTXܻPQpipxkZSY0cRX`VN">@ $#  PYPY?+?+99??99333310%#"!23'53#.532654&#"52z{2xyhZ6Zby/6t*p~N">@ $#  PYPY?+?+99??99333310>32!"&'##4'34&#"32682zr{2&xyhZZby/[6t* ,F@%!'' .-$PYPY *PY?+??+?+999333310!"&'##654632&#"3>324&#"326r{3BO:E?E2zxy"Yc 6ӏLHhZ=N6@  PY PY ?+3/?3/+99333104&#"'>32#"&'7326ir٧`"jZẜ lhMN+d@8 $* ,-*'PY   PY  PY?+3/?+9/_^]9+993333310"''67&532.#"63 '2>54&#"1p4#|H%cri" e}Sq=@32cltpt`Z]pi^ʢy!^]W`\NR]C5N3~@G1#// *541PY&,SY/!! &&PY PY?+?+9////_^]q93++9933333339910#"&'732654&+532654&#"'>3273267#"&'cltpt`Z]pi^ʢ"/2%=";~U[!y!^]W`\NR]e\DC4yp7KN&T@- !!'( PY   $$PY$PY?+?+9/_^]+9993339921032654&+532654&#"32#"C~rltpt`Z]pi^y,[^]W`\NR]Co V':<@  QY PY QY??+/+?+9333310733##"'5326=#5۴K4-#E>ӃI F\{VW'5T@,( /6"7$PY ,PY2PY PY?3+?+?+99?+39933333310%!"&'73 5##"3234632&#"4.#"32>;{d 3wǻs. &729@AHS~vUH8KQ;hiia1 NFyedVWKJ^NE@#PY PY PY?+?+99//+993339210!#"32.#"3275#@Kzrig^DK"ZjCW:A@$  PY ?3?+993392310%3 3#"&54>4'326w5>l}kj}%LK'$%'!]umm(Z\SQ.43A 8P@- !4$!,9:4$/++//(PY/ PY PY ?3/+?+?+3/993310%4.'322'&#"#"&54?.#"'>32?> )  GHL8r!??#-3R}kj}P1-#?>"r8Lau)77(u*3L00/]`\o2[55^QjxxjV]055[2o\`WnFFmXo;-@  PY?+?39/9933310%#"&5332653#??;{*`Um`Rro4~4J7@ !PY PY?+?39?+933310>32#4.#"#!2&#"=:}*`UEI5B~ jc/ro4(`?W'B@$ # )( %PY  PY PY?+?+?9?+93333103>32!"'53254.#"#!2&#"C :}3U:=u*`UEI5B~J?jc!ro4( 7@  SY  PY ??9/3+3?+933310333###53qrrqqi/<V: @   SY?+?99310327# 3 97!,2-%QF (#D: 7@  PYPY?+3?+3933310%3!53#5!#Rό#D@" PY  PY ??9/+3/3/3/+339333103&#"#>3332673#"''kT7 Z`#0/h|yB/0rrxZH@%  QYQY   ??99//3+3+393333310###"&546;33!5#"3Zdf3;nYYkc{ <3iW @  PY?+?39310327# 3:977/E-sQC(MWOW@.  !  PY PYQY???9/++3?+9/933333331033!#"&'732>54&+5!璼'7aORn䁘_aS$:)H@%"( (*+) %PYPY ??+?+?339993333331032653#.'##"&'##"&533265Vps:l{8qVpv:Rxs*,9OsZbkm`RxsW:#D@# "" %$ #PYPY ??+?+?3399933331032653##"&'##"&533265Vps7n{8qVpv:RxsXkXbkm`RxsW#N1Q@, 1((-23*/PY*$PY$  PY?3??+99?+?+933333104&#"#4&#"#4'33>323>32!"'5325qVpvVps:l{8q3U2ExxxS*,9OsZbkm`WN":@""$# PY  PY ??+?9?+9933333104'33>32#4.#"!"'5325>y*\Y3U/HvS*,9Op]/kv4 WN"=@ #$PYPY?+???+9399333310327# 4.#"#4'33>32u>,@;*\Y>ys(/kv4S*,9Op]:.@ ?3?39999333310 '3#&'#<%3(!:SJ}:GbAg:VN K@)PY PY PY?+?+9/_^]+99333310#"!2267!"!. I !04XVN!k@: #"QY PY PY PY PY?+?+?+99?+9/_^]+9333333310!!!5#"!25!!4&#"326GWsvq]q!0q]SWN(H@% &&*) ##PY#PY PY?+?+?+9/9933931032654.#"326= #"&'#"5uprwiiwrpUM|ʸzM`úoo䗻`xz}%NVWR@-   PY PY PYPY??+?+??+?+9333333310&%34&'>%ihrqiejlcW2~-fD++:*@ SY ??+?9993310#/##"'53265%"?[E$%$32&#"+pf$%$32&#"327# +pf$%$r%f YQC (N@ SY??+9931034>32&#"\;%$<}mf  WN@ SY ??+993104&#"5632fnx<$%;\W f0: I@%    PYPY ?3?+9/+3933399310!#!2##!254&#Bθؕctk:?\[0: B@!  PY   PY ?+?39/3+9933333991033#!32654#!BLٷ2ls?:O[\9WK5T@-**44$$.4672,PY2)''PY'PY?3+?3+9?+933333331032654&/.54632.#"#"'327# XbJʳnzt0^~I(Эoz9*"$+WQTT@P"(MnP~HMJK.<*%$=Ja>; (WN(@  SY SY?+?+339310"'532>54632&#"O7<96=k,1BMKW,UhiuW F@%!"! PY SYPY SY?+?+?+?+3339933310734632&#"3##"'532>=#Y21BMKO7<96=޲iGF,Uh%W:N(@  SY SY?+?+339310"&54&#"5632327KKB1,W849<7W ffW,VK&Q@*"  '("  $PY SYPY?+?+9/+93399333310/#".54632!2&#"%3265&#"FTQI{I@D$k,1BMKlyvA/>IN9:6VXe=qTv+bi`86_O1A*A@"  QY QY PY?+?9/+3/+39333106323##5#534&#"Y]}5x3?$D}ԃN?W*,6@  QY PY?+?3+3933310#"5#53733#327*Y]}5x3?$DokN?Q:&R@)  ## ('"PYPY ??+?39/933+3399333333310!33##.'##"&=#5326=!:ll>ykk *\://*,9Op]{=Xkv4T6:/M@)$(- -10"%PY"( PY PY?+?+9?+993399332210"547>54&+53232654'&546;#"ET3!++R|YmCDCDnX|R++ 4TԌvH@*gW_tt]]tt_Xf*>Iv:)@  PY?+?39933310#"&533 4'3ŵpA15:;cav: *@   ??3993333103#'#4#':uv>:+@   ?2?9?3933103?3#.'#&'#0ѯ#' /+&:Mg]#.խ"&3,@   PY?+?39933102&#"#.'#>BJ2&.bHD@r +V6O:V :&@ ??39933310!3 3g,5[{K1Wr:;@  PY PY PY?+?+?+3933310327#"5!5!5!!+75%C:,8jsQC (&1N): Y@/ "!PYPYPY ?3+33?9/++39333993310%>32+'7!5!5!%"32654&eav0"78j./dFMF6{gxy^T=u&ڷQf,7'-DW :P@) PY PY PY?+3?3/+9/+393339310!#"&'732654&+5!tsv،RA:Nj wǤlVK; *j@<(#   +,PY#  %PYPY  !QY?+3?99//++9+3933933310'#".54632654&+5!5!%27&#"|_RCsA>CaISxVEzJuDEp8Ii:5=J9<@  PY  PY??+3/9/+933310!32654&#"'>32l.=ir٧ۺjZ~[:@  PYPY ??3/+9/+933310!&532.#"327ri=. Zj93@ PY PY?+?3/+?93310#"&'732654&#" ri=.j꬗Zj9WVN9@PY PY?3/+/+3/9933331032.#"3267#"Wri`Zjjhl a<@   SY SY?+?+99//99393210#"$5!2#"32%53שŦrJ< MR},-:!p@  "#0##@(#H#/## QY PYPY?+?+9/_^]+9_^]+q99333339102#!32654&+32654&#4rmCpw؀mfy:]|k:KU]eSHZRLIN&R@*!! (' PY   $$PY$PY?+?+9/_^]+999393332104&#";#"32>7#"&547.54632]jq\Z`uosms>omӻ,ZUN\`W\_`ƕ੓)"qX^'X@.'' !)(#PY PYPY PY?+?+99//9++923333310.#"3275#5!#"32>32&#""rigKzj v/4$+B7ZjCۉ^DK"Hy GM: W@   @ P ` @   @HQY/   ?3?39/]++_^]qr99333310!3#!#: :6:W) R@+ "!SY PY  PY?+?9/_^]3+3?+99333333310"&546;33#'26=#"53WOV\MAQW}~$%bYkk<98A;nz: >@        ??3939933333991073## n%2:m4i:@PY?+?99310)3!:[VW(G@$ #)* PY  PY&PY?+?+99?+?399333310"!234632&#"#7#4&#"326{66'%8<}6Ҋxy6We k[>/f@9  !QYQYPY?   PY?+3/?99//_^]++3/+9333333310!32654&#"'>32!!#5!/=.=ir٧K ۺjZn{Oc@6   !QYPY? PY??3/+99//_^]+3+39333333310%!#5!5!5&532.#"327!ôKri=.={n ZjV%(c@5 && ' )*''PY  #PY PY&&PY?+3?+?+99??+39333333310!.5##"!23'3!!32654&#" !C2z{2rVxyYt*hZ6Zbynڋ$VV1=@I((8##)8*.2?>.'PY.**PY ;PY PY5PY?++?+99??+3?9/+993333333339310%#"!23'3!# 732654&+5!#.532654&#"52z{2{܋X#oRxyhZ6Zbyn'[P͜26t*pVN&25?@G'33-99"5=@A4#4PY #:PY6PY5PY 0PY*PY?+?+99??+/+?+?3+393333333333310%#"!23'3!3>32+'7!.532654&#"%"32654&52z{2sTeav0"7,xyM/dFMF6hZ6Zbynڪ{gxy^T=ut*pɯ#Qf,7'-)d,"5_@2&. 22 .76&PY 1QY  QY 5PY?+?+?+?3+9993333333310#!"5#5373!632.#"2654&/.547#3d}5xJ\nzt0^~I(IyXbJ(3?+ƒ~HMJK.<*%$=JaFK@P"(MnPYBeNB)W%-d@7( #++# #./PY*QY@ &PY PY?+?+?3+3?+39_^]]333333310"'532>=#"5#5373354632&#"27#O7<96=XY}5x՗k,1BMK&=3W,Uh+҃0iu6 cN?,0<|@E & 5--;(=>#PY (;++8PY++  QY PY1PY?+?+?3+39/+9?3/+933333333310"'#"&5#53733#327&532.#">3 '2>54&#"w~z}5x32!"'53254.#"#'###5354632&#":lV!kv4SdIz F\a.N@)- ''/0 **PY*-PY???3+9?+99933333103332654&/.54632.#"#"&'NXbJʳnzt0^~I(ڊSRQXWQ@P"(MnP~HMJK.<*%$=Ja>G32#4&#"#432&#")oTvs{FRXf{10"/VbMD{qR}h>O udDp.@  YY?+/+?393331053#"'52653hzPS9*0%zyykbb4HFg-@  Y ???+999333104'33>32&#"ktJF%NOJq@bGt}r(.@  Y ??+?93993310#'##"'53265tLF%ONq@`It}6@   Y @Y?++?93993310327#"=#"'53265n&&'3&NH$MO9/ qPEt}d D@"  Y  Y ?+?39/3+9933333991033#!3254+ވ]f}z5x\fse.@   ?3?3393393310#&'#373?3u  y| x'~0IR9<U>M1@     Y/+?99?339933107"'5267373t1#98]+܃C/A_XtZˋh  WH @  /9/933910546733%+y_YaC}v? @  /9/993310#65#5?%+y_Y̒aC}S @  /9/933910##.=MY_y,$}F^x @    /9999331026544#*77*TeeT8117UfWWgx @  /99993310"&5463"3UddU*77*xhVWfU71184>@  Y Y??+9/+3/93331032654&#"'>32*iYWh~pb hs 3<@ Y  Y??+3/9/+9333105.54632&#"327Cq~hWYi* ĥsh eHeH!eF@ /3/9910%# #3FeF@ //39910%#3 3fHK !@  [/+9993310#'##53ih !@ [/+9993310#53373hi/9310#3qqL3XS@ Y/]+9910!5!X%/991053ǂ/9910'53ςj/9310#3qqjLChk/9910!5!h%wj/9910'53jςjj6/991053j:@  ??910#'73e ee e:c:?9910#'e e:\ @    /99993310726544#*77*TeeT8117UfWWg\ @  /99993310%"&5463"3UddU*77*\hVWfU7118 @ /339310%!53533{q{l @ /239310##5#5!{q{gl ,@   /9933933310##5#53533{q{{q{ }}l||/39910!5!pw 1@  P` Y/+_^]]q23910"&'33273)uu P@ Y/+931053 3s J@/  Y     @Y/?O/]+_^]]+993310#"&546324&#"326dddclN89NL;:Ldded8NN87RQPU9@# @ HY P`p/]q+/+993310#"&54673327?LijWD4+1-6=pfUF&-;F'*0@  Y    /   @Yyi[I9+ tbRB2"grbRD4$tdVF6"vfVB0 7@tp`PD4$tdTD4p?/^]]]]]]]_]]]qqqqqqqqqqqqqrrrrrrrrrrrrrrr^]]]]_]]]]]]]]]]]]qqqqqqqqqqqqqqqqrrrrrrrrrrrrrrrr^]]]]]]]]]]]]]qqqqqqqqqq/2+_^]]q+3/3310".#"#>323273*TNG76 [ 0Q?,TNEd\d%-%>9fi=%-%wx $@  [/2+392331053353e @    /999933107327#"324P;~U*N#D<(4 - ,@    /3299939210''7'77XXXXXXXX;@  ?3/3933339331033#"&5474&'32ف*,UIJSJ!34ToH(L[[LT@Cc7 %d@ ??93103dz,'@@!  () Y Y?3+?3+999333310#"&'73254.'.54632&#"lbW!=xg[3znSO6APyW4luVk=9v$- 6M9imXci36(2!6T/N3p@ ??399310!#!5!pp$@ ??9/3993310!#!5!3pHp$@ ??9/3993310!#!5!3pH^p$@ ??9/3993310!#!5!3pHVp@ ?3?99310)5!3p0HbIp@ /399310)3!I_p bIp @  /9/3993310!#3!Ittswp}Xz @  /99993310!5!!5!ppvvPN 0@  /329/39933993210#65#5!#65#5%+y_Y%+y_Y̒aC}ÒaC}%@ /399910#373|Rr``r%@ /299910#'#3%r``rRV@ /9993310%5᪪r``rRV@ /999331057'5窪Rr``rW  @  /32993310#"&546324&#"326xPPxwQRv`;--<<--;QnoPPnnP-77--99 B/9910 53ϱB @     /32339910 53!53cϱGϱB @  /2233991053353lx@    /32993310".#"#>323273*TNG76 [ 0Q?,TNEd\dl%-%>9fi=%-%wx~$@ //99//9333105353| @ /299310!#! QP| @ /299310!#5!W @ /]299310!3! jWPW @ /]299310!53!jW$@ /3]2993310!3!53WPX@ /]2993103!!iYȇ:Xq 8@ @ H @ H  /]3/+2/+9310!#53!qVpp M# /10'53ς  # /1053 K  /32910#'##53KihS Y/+10!5!%#T Y/+105!#$  /2210"&'332673xi cLJciw;IG=zZ Y/+1053Zլ{Y/2+31053!53sӥø+ @ p+/H/+q99104&#"'632#5>3*HFZjQ[pE0"c;U 2x8b  /3210#"&546324&#"326xPPxwQRv`;--<<--;QnoPPnnP-77--99 /221053353K /2910#53373khi: /10#3:qqLY/3210#3#36qqqqLL /2]210 53!53$G$d  /222/10"&'332673#5xi cLJciw;IG=z$  /32102#.#"#>wibJLc i{>FI;wd /9/10546733e&({^XjA~d /9/10#65#5d&({^X̨jA~d /9/10##.=^X^{(&~@hd /9/10#65#5d&({^X̨jA~[i/]10'53NςiOj/]1053j?_!@_o/]^]9/310#5#5353oo_sqr^_!@_o/]^]9/31033##ooKrqsy /210#!5!y9> /9/10#65#5%+y_Y̒aC}W_  /q9910"&5463"3_UddU*77*WhVWfU7118LW@ /]2310!53533{q{WlMW@ /]3310##5#5!{q{glKW @ o   /]9/33310##5#53533{q{{q{}}l||9c Y/+10!5!9p֍W /]2107!"'53253U2ExW /]2107327# xE2U3(u WY/3+31053!53sӥW8W  /3q210#"&546324&#"326xPPxwQRv`;--<<--;QnoPPnnP-77--999b @    /]9/10#65#53b,(u^XWu/dZJD /29310!"'53254&+739!1%=HAk'^^bV(*dSLU  /210#"&54673327?LijWD@S1-6=pfUF&$}B*0WCo/]10#3CW^Wy/3]210#5!#!yWPc}@   /^]3322310#"&533265332653#"MD^\a..7A\A7..a\^r&5lLCJEEJDKlWE[ @/^]3]2910#'53373ehiWWA[ @   /^]]2910#'##573Aihlr$v @  /^]3210"&'332673xi cLJcirw;IG=zr$v @ /^]22102#.#"#>wibJLc i{>FI;wWgc@    /^]3]29910".#"#>323273*TNG76 [ 0Q?,TNEd\dW%-%>9fi=%-%wx; Y/+10!5!%iT Y/+105!iW9@ 0/]q9910!5!!5!9ppvvg /2299107".#"#>323273*TNG76 [ 0Q?,TNEd\d%-%>9fi=%-%wx_/310!5!_BV/310!5!VW} /3/310 'ccba//10 #X N\ @    /]q991026544#]*77*TeeT8117UfWWgWy/3]210!3!53yWPDW/3q210!!5#x_Wx纺^@  /39333/310&#"#4&#"#>32>32J7<\<7Jb ZNp9 N6N_ JJEEJJNZ[3(ZN%r% @   /32910''7'77WVWVUSUSli/3299105>54.5467i/PS,1#_s-0# 1?$ M&*15<"DN L$,25; U0/99105!%5!W ffff /10#5x  N /10#5Nx  ]@  /2/2/9910".#"#323273*GAA%/3 e,IDA$[fi%49%mze /9/10#65#5e%+y_Y̒aC}S   /339/310#553!53u| 쬬W @   /^]q210327#"=3>!,&!p y"/3210#5!#!yP W~@/^]]q99105!5! jjjjGW@ o/3]210#3#33W^^5W/]310!#5!Yuf@  /33229910&#"#>3273273#"''Q(c[ 0Q?>O=a=*d\dU;Q=azfi=0l6lzx1m7bp )@   //99//99399210".#"#>32326735353+QLE72 h 0R?,RKD62je7 '!53Y]6!'!72kլp1@ +.&! /22992/329910".#"#>3232673".#"#>3232673+QLE72 h 0R?,RKD62jeU+QLE72 h 0R?,RKD62je '!53Y]6!'!72k '!53Y]6!'!72kW //99105#'735vvOW@ /q9/3105#7#;v|W %-5=EKQYaiqy@ZNGG0488<ITTX ll$p (tt,x@D \`dhP|4557449 885667775558849*557sNsmmIt}! /91057'5窪xRr``rx\  /2210"&5463"3\UddU*77*xhVWfU7118$ @    /299//3102#.#"#>53wibJLc i{>FI;wO%B @   /32910''7'77WVWVUSUStV/22910%5r``rRtV/3291057'5窪Rr``rV @  /329/291057'5#'#3窪r``rRRr``rx]  /321026544#\*77*TeeT8117UfWWge  /104632#"&8''89&'8'89&'88AV)@   /]2993399333107''7'7'3 ]CKNB^ S3K%z)~)y%L5WE+@ # )/3//3/9910#"'#"&5463263232654&#"4&#"326EiNY33YOhiNZ22ZOh=,,;;,,==,,;;,,=NeIIeNNeHHeN36=,,=6336=,,=68g4 ?10#7!3_q@_q@SW  /3310! 332$7^JK^6svvS2 /3210! 332$7^JK^2svvS/310!5!JSU/310!5!JS /329910#"%$#"#>32327-^t-{Y͑9VUT\(-VS6  /3210#&$#"#! ^^0/ÂvvsSW//99105!5!5ϖlv^Hd= ?9/1053332#4&#"#3)oTvs{FRXf{{bMD{qR}h>pkc@  Y ??+/104'33>32&#"tJF%NOJq@bGt}rWr7YvO @  /3?3910 #33DŽ :r(v6/991053n uWx/9910#5n߈W6>Nb@A  PY p`p o  PY ?+3/_^]?3/^]q+99333104&#"'>32#"&'7326ir٧`"jZẜ lhWN&FG(@4Td%+5/_]]5>N&3(@4Td%+5/_]]5/991053E!$%A :@   Y ?/]]33/+393331053%53!53EؖB!p%R&$6l|- @%/P0`?5]q]+5~@@w|HRb 0@p@ goHDTcfH\_HW[H@QVH$4D@CFH0$<@ 8;H@+-0H  0  HY/++_^]]]q_qqqr+rr+^]]]+]]q++++r+^]]_]+]q991053'(6(|-@ q@%/]]_]5+]5?5 '+6%|6@Pq@%/o]5+]5?5]U',6|@@ + 4 f@%/O_o]]_]5+]5?5]]&26|%@ ^@ %/]55+]5?5A'<6t|@ (HXhx8X Gg77WgwWw<'g'7GWw '7W 6vV&&Vv@6fv &F@Vfv%Eq%5Ueu %5EUe uA$DTt tbsx   @ ` p @ %]5+]5?5_^]^]q^]qr^]^]qr^]qr^]q^]qr^]q^]qr^]qr^]^]qr^]qr^]&X 6|6@ +&$$$>@$$!!%_]q5+]5?5]A&h7@/?O/?Oom/8/_ @Ps p= &ܴ %+555+555^]qr^]qr^]r^]qr^]^]qr^]qr^]qr^]qr^]R$%/@_Y??+99310!#/8=>@!   _Y ?2?+33_^]]93333103!7%.'C#3 + ^J oj(A= +aO@+  `  _Y  _Y _Y?+?+9/_^]+_^]9933910#"$5!2#"32!!שŦrJ< KMR},-f|,?. N>@$ vo 0 /  ]]]]?2?3]9333310%#'#3N|TTz? 0 1Z ;@  _Y _Y_Y?+?+9/+99399210!!!5!5}9\a2 ?@     @ H_Y?2?++_^]q993310!!#!ax 3l E@#   _Y  _Y?+3?9+3999932231035 5!!!lmCC|.7-)<u(~@, $ )****$*D*d*****@ H# #`Y &&`Y  ??99//3+33+3+_^]_]]]]9333333310+#5#".54!3533 !#326%;#"SS~HG0884o.+;|@9 D`DT 0 @ H `Y  ??339/]3+3+_^]]]]]]q93333310!#".53;332653+SǬ88ÿS-Iǯ1UW#S@*  ! !$%% _Y _Y?+?3+33333_^]993333993310 ?3!5654&#"!53&5/[QQ[s_`qU&O4&,@&%+55+55-) @     Y H vbTF6$pd@4$it`PD tdT@0$tTD$9pdT4$@8T4p`0/]]]]_]]]]]qqqqqqqqqqrrrrrrrrrr^]]]]]]]]]]qqqqqqqqqqqqqqrrrrrrrrrrrrrrr^]]]]]]]]]]]]]_]qqqqqqqq??39^]332+393310#3 3%53!53 ӥHH9ayVe&`6!@ '&''*%+5+5Fj&d6@ '&'I'* %+5+5jX&f69@ &d %+5+5&h6@ &    %+]5+5A&t7!@ &"%+555+555VeN&U@- !!('(( !  $PY PY?+?+??9_^]993333333310%#"323673#.'3267.#"K?y~-22T;/#rxwyyywtjbg=!1WI)Y@- # +*  PY &PY PY?+??+9/+999333339910#"'##463232654>54&#"Iܷߔ@Qqyn^rXܷW+1zbpX:M@   @0`@ H  ?2/?933+]q933333103673#674z": @:]?C?[ZtV ?@  !"  PY PY?+?99+39933932104.'326'#"5475!`5ST54.'.55!5!0]6oZ:$/~ *Ss[O7={CS5#"9XD,mO8R$0$&5KeBa#jXNM@  @H PY  ???+9?+_^]]q99333104.#"#4'33>329*\Y$>yXVkv4S{l'i)p]j  U@`@#HPYPY PY?+?+9/+_^]+]99333310#"!22!"!  *#}}t : @    O ?  j   p `      ? `   7     ? /     o      ?   ^]]]]]]qqqqqqrrrrrrrr^]]]qqqqqrrrrrr^]]]]]??933103.53 +% ENAz(: A@%   ?  ?2?39]]39333310!#33 0Im: /D@' 0`   PY ?+?399_^]9333310.#"'632#&'#D++6'#C>kK)+żd; Apf.kw:L@ @H PY?+/?3?99+_^]99333310!.'##"&'##332653^54.'.VܖJzM0]6r^=$/~ -Xs[O7b! qg}kEZ4 CS5#"9XD,mO8R$0$&5KeVNRO+:J@(  !!/! PY PY?+??+33_^]933333310"&5!#6="5>3!#37fsfn4.4:Bk4%*4VMqH+P SLEW;OR@   @#H  PY PY?+??+9_^]]+]9933310#"&'##4324&# 326;n@Վ~7XDK54&'.54>32&FRZn$/~ dMOoeAt_zy?#F,mO8R0B,0qo^6DwdV:/@   PY PY?+?+39933310#")#''#"!260,9QG|Y* %yzc:L@  ? @HPY PY?+3?++_^]]]q9333310"5>3!!37#"&5Bk4D*4VMBsf SLEq:C@ `@H  PY?+?3_^]+]]q993310#"&5332654'3ɵu}F,5:;c.UvUWR"V@.   #$$ PY PY PY??3+3?+3/+_^]933333310#&4746324&#">|WP5i  * ڸDXPp@ $  @(H   H PY ?3?+?9+_^]]^]]+^]]9933922310%#.#"'6323 #IC&"5AVkPi9WJ dGW,<`@:   0`0@p PY  ??3+3?33/_^]]]qq93333310%>53#$&533.򵐸w|kzSO*z@ ""((+,,0,,,@(#H,,, ,@, )) %%PY PY ?3+3?3+39/9_^]]+]qr93393991032654&'7#"&'##"47326=3srfrqzeϾ~""~worfvϹ灊@ λ{&hi@  &ٴ  %+55+55{&ti@ &%+55+55V&R6)@ &F%+5+5&t6@ &%+5+5S&x6@ +&+7+.%+5+5s#'1^@4.("  23%PY0PY 00 00 +PY QY ?+?+99//_^]]9++99333992310>32#"&32#"32654&#"4&#"32;&*c֦l^Yy\NN)s*tK]<${o=tQrƑ6=HHO P+3]@2,**  1$$ 54 PY , PY*,,,''/QY'PY?+?+99//93+3+933333310## 47654#"'6323265&$&5463234&#"Pa:1`jO]hRFg^̪av 1]]#<16cX2]]2BI;av{9 .@     _Y?+??99933102.#"#3 > <;T^%$1 rT7x-3-0H9aVG'|0#?59 &y@ &%+55+55PW+R@-   PY PY PYPY??+?+??+?+9333333310&5%34&'>%_pzzpktujW4q .Zǽ˷+R:-[@/+ (""(/. %PY)) PY PY?+33?+9/?+993333333310!##"&'##"467#2654&'!32653Rl09Ͼ~""~63itt>01-N@+ *&! ./'PY'#SY SY ??+?99?+?+933333310 !4#"'632!327#"'5326=.547tw8"BK|z6$  oyw*2@C+578ca5"PiuI DQdBaW2@  _Y_Y/?3+?+933310$!2#"32rJ< W<R}ep,-VWN 3@  PYQY ??3+?+933310&!24&#"326ܺЅW0erP:@  _Y  _Y ??+99//+933310!&$&54$32.#"37%#X3ߓo =  C~ovIZWN,;@ & .-'# #*PY# PY ?3+?+992993333104.'.532.#"#"&'5326(PgVvi,D\9mW5]2nDvvw)6%ԗ ZjKkL3% B6u˄0{~xt9cVi1@     ??993333933310%54''%&''%%7i.7,F~-GGpj6ΒwqU3X}+Q@*$!* *!,-+"'`Y`Y@`Y?++?+?33999333331032653#!5!26=##"&'## 33265]st`ӯ桙*z{%^[tw |gYXWVc} ~X:-O@)&#, ,#./ -$PY )PY PY?+?++?33999333331032653#!5!26?##"&'##"&533265VpsaӮI8p{8qVpv:Rxs2lm`bkm`Rxsd7@ _Y_Y  ??9/+?+99392310&#"32673##"54632HUww^IݶTx346$~S'&E@& PY  SY ??+?9/_^]9+933310!#"&5!2&#"3265393|3U:=u*`U)[P(|ro4~4X8@ ! _Y_Y?+?9/9+99333310!2>54&#"#3763 #!.Z1UWF$7j"MВ0*P:y> '2]@3, 1$ $ 34 1"/"PYPY// PY (PY?2+?+99//++9?993392210267#".#"#46323 4'# 54>"327&p4#|H%crɅC_H7=mTOWVO "bSq=@7>54&#"'6$!232654'7! $n+NlOl?05c`r?ǻ5CMsT=-($6Q?nqep!ƳNz[K%&8VEzYh6zun,E@#&.-&PY,,)PY?+3/?+3/99933310%! $54>7>54!"'6$3 3267+NlOl?/ 5c`r?ڽ+?۾MsT=-($6Q?il!öNz[K%&8VEy("%V@0 %#$$ # '&%  _Y $ $_Y _Y?2+?+33?+399339102'&#"!5.#"'>327>!L@f"FA)1|;6|2)AE#f@L_t(CB%t>eln3f&.*.&f3nle]qma HA#O@- !$% !PYPY PY?3+?+33?+399331032'&#"!5.#"'>3276cmL8h!B$<@!! %&SY SY ??+?99?+9333310 !4#"'632!327#"&547tw8"BK|z6$  oyw8"BK|z5"PiuIBbWDN,@@!  '.-PY  *PY $PY?+?+9?9/+999933104>32#"'32#.#".4.#"326b6wz`B$O{E%?}paQ없H$VY =lUWNFW=MaP9:G@%  PY    PYPY?+?+9/_^]+99923310)"3!!"!!)9w# 'P9:E@% PY  PY PY ?+?+9/_^]+9333107! !5!4&#!5!2#!P #wUWhy& 9@    ?3?9/993?9333310!##3 3VE=l(UW:5@ ?????999333310!##!67!#?4. Gk}rs W;O&Q@)   '(PY @ $PY?+/9/3/?+9933333310#"&'#!!#5#534324&# 326;n@?zzՎ~7XDK32!"&'7326=4&#"#!5!uT^Eo!!24&#!!26 `13_:%5C:::*~or A)ByP@*  _Y _Y  _Y?+??39/+3/+933333310#!!#3!3!24&#!!26¿>VGsTy./e@<  ` _Y  _Y ?2?+39/3+3_^]]qr993333310!4&#"#!5!!$3 q ?zm2 圜;&@ &% %+5+5&T&%+5+57:&^J@ & %+5+5h G@(        _Y/?+3?3/_^]]q933310!3!3!""hhR$ _@  `@%#H _Y 0  _Y_Y?+?+9/_^]+_^]+]99333310#!!!!24&#!!26!~oHy%/ChEL@*   /  _Y _Y/3?+33?+_^]93333310%3#!#36!! 2Nm%CԺ1%Z?h8a_#Ae(G#@Q #""# #%$/%% %0%@%% !`Y/ #?33?339/]q3+39933_^]^]_]9333333993339910"&'#&'3332>73###R%oU0o`XKKZbk0Um' U#ϧk(k)o1f# {Cp'@B" %%()"  _Y? @ H_Y_Y 0p H?2/+]q+?+3/+9/_^]+9993333339910"$'7!2654&+532654&#"'6$32mVwGG~3FMvw{k{u=ǩ  8@  /  ?22/?3/3]99333310333#47ުdrzZ:&J@ &%+5+5P@)     `Y/ ?2?39/]+39_^]9933333991032>73###KZbk0Um')o1f# {7@_Y _Y?+?+?_^]93310! #"'532>!#^13_:%5C:::*r A)B0 +a2P@   P ` p ]q]3hy&.77=@    _Y?+3?3/993393310"&'732>73 3L>.Q^H3EFfUj}& ;'_z8v(j@< # )**`***?** $ $`Y &&`Y  ??99//3+33+3_^]]]q9333333310+#5#".54!3533 !#326%;#"((~ W o.+;h A@!     _Y/?+3/?3/_^]99333310%#!3!3ŴP@ @H _Y/  ?3/?9/]3+3+_^]q9933310#"&533273#Gھ"R{l1 U@1      p @    _Y?+3/?33_^]]_]]]]]93331033!3!3h/W@0  0@`/   _Y/?+3/3/?33_^]]]93333310%#!3!3!3/-ӺҺ. E@$   _Y _Y _Y?+?+9/+_^]99333310!2#!!5!4&#!!26B5s3-Ҿym R@  @ H_Y_Y?+3/?3/9/++_^]99333310#!3!24&#!!263~oy B@% o@P _Y_Y?+?9/+_^]]9933310#!3!24&#!! ~o@yiyy@J  _Y_ _Y@P  _Y?+3/_^]?3/^]+9/_^]q+93333310"'6$3 # 7327!5!&$ɘ-G.BlVE rv<tNa@8  ! !_Y _Y  0   _Y?+??9/_^]^]+?+_^]93333310# !#3!! #"32ٿ*W6\f;s$E,+`  Y@0     _Y?Oo _Y ?2/?+9/_^]+3993333393103.54$3!#!3!!"`I;_֝IWsNDx? "W@ $#$$$@#H PY   PY?+/_^]39/9++_^]993333104&#"3262#"4>%>.b~]d+ʿûBN|L56b}:!x@  "#0##@/#H#/## QYo PYPY?+?+9/_^]q+9_^]+q99333339102#!32654&+32654&#4rmCpw؀mfy:]|k:KU]eSHZRL:@PY??+99310!#:I:h:F@$ PY PY  /3?+33?+9333333310! !#!#36!3B%Z@FңwKn.mh}nIWNHS:#@I ""##$%%%p%?%o% %%%%P%`%%/%% @) H!PYO_O #?33?339/^]q3+399+33_^]]]]]qqqqq9333333993339910"&'#&'3332>3###SAa#]ؼBH;.04Bü]#aA PEj]$&3\; #1^N$@R  ""%&&  PY    P`pPYPY`p ?2/]]q+?+3/_^]9/]q+9_^]993333339910"&'732654!52654&#"'!2ʧ-5`qc]Yq .KΑgy},^[ȉTXJVJF~e  m: F@+   p   ?33?33]qr993333103#467#< Ŭ:e$:&@ & %+5+5:d@9  /  PY?O?  ?2/?3/9/^]q+3_^]3333933991032>3###04Bü]#aA:&3\; # :M@3 pp 0`p PY PY??+?+_^]qr93310!! #"'5326!h;@JmV2,+7C7#,LϜJ nE:F@&  ? ?333?333]]933333310!##!67!#?4. G,:k}rs: g@   @ P ` @   @!HPY? ?2?39/^]qr++_^]qr99333310!3#!#B紴:6:VNR:C@+  `   PY?3?+_^]]qr993310#!#Ǵ/:I:WMSWNF#:;@" ?    QY?+3?_^]]]]9310!!#!#d:IW:\VW>%2@@g3:,, & BA ##6PY#0PY)PY >PYBBBtBdBTB4BBBBdBTB@B0B BBB]]]]_]]]]]]qqqqqqq?+??+?+??+9933333310#"'##47##"!23'33>32326754&#"4&#"326>O.omp-.rmvzwylnkx^j7zwn"WSYmChZ6Zb\hY\ɿ:[hf: :@    PY ?2/?+3_^]99333310!33#!Bݴ:II:z:8@   PY?2?9/]3+399333103273##"&5.nN~:n/8: W@!  d 0     @ H PY?+3?33+_^]]_]]]93331033!3!3:IIhf:c@;   `@P?    PY?+33?33/_^]]]_]]]9333331033!3!33#:III-: i@ @'#H QY   O   PY  QY?+?+9/_^]q++_^]^]993333102#!!5!32654&+ gʂxtp6\c^W2: R@0  QY   O   QY?+3?39/_^]q+93333102#!332654&+3&gʂxt<p:6\c^W :: j@H /Oo @#'H QY   O   QY?+?9/_^]q++_^]q99333102#!332654&+8U܂xtp:6\c^W7N@B  PY  o     PY `p @""Ho @ H PY?+3/+_^]?3/+^]+9/_^]q+9333331073267!5!.#"'>32#"&7d c ߫; lhNO@+   PY PY    PY?+??9/_^]+?+93333310#"'##33!24&#"326 ޴!׽x~|:6: S@*  QY QY ?3?+9/_^]+399333339310 #&463!##";Xxk|63\]^]W&HC&ʹ %+5+5W{&Hi@& %+55+55 W){@A )) * ++@+P+`+@+++0+@+)PY QY%PY H??++9/3+3?+?9_^]qr]3933333103#5353!!3>32#"'52654.#",:}xxM2>F6*`U= jcљ Hhro4&t@ &U %+5+5WN@\  PYo  PY /   @ H  `p @ "HPY?+3/+_^]?3/+]+9/_^]q+_^]93333310"32&#"!!!2674 ҋc d!ħgm 9KV=L%{&i@ &%+55+55W=M :#}@ %$ %%@5#H%% #QYO PYPYQY?+?+?+9/_^]q+_^]]+q933333102#!! #"'5326!32654&+M>e;@JmV2,+7C7#,xtpLϜJ nE6\c^W,:z@  `@1#HQY PYO  QY ?2?+?9/_^]q+3/+_^]+]93333331032#!!#3!32654&+fNʂxt:6:6E\c^W  o@<!"@"P"`"@""""0"@"QY  PY H?++3?3?9/3+3_^]]qr393333310>32#4.#"##5353!!=:}*`U,YjcWro4= &t?@ &Q %+5+5&C& %+5+5W&\@ &  %+5+5h: L@.   @ P ` @  0 @ P  PY/+3?3/_^]qr93331033!3!#:Ihr F4Z@. '-!!65$$*_Y($1_Y_Y _Y?+3?+?+?3+9/99939333210332#"'>3 # '!"$5!2&#"3267J#tMϓBllBMtO2qLV;,h|GANQ~AG|hXR:8@     ?3?339939333310# #33654'2o S\0:y]x:nnKzM@)  _Y`Y_Y??+99//3+3+93333310!53!!!2#!!4&#!! ut@דҾyK@(  QYQYPY?2+3??+9/+93333310!3!!!2#!!3254&+-*:t:o娟^f@!@K!!  "#@P _Y _Y   _Y/??9/]3+3?3/+?+3/_^]933333393310333! .#"!!3 # #a+2Гz$c1N<~$Mñ]5xN!@Z !!#" p`p PY PY o      QY/??9/]3+3?3/_^]+?+3/_^]q999933323310333>32&#"!!!267#"'#֫ ҋc d:+ħgm R @@     _Y  ?33?9/9+393333310##3###!&'T?6мY 3'YEW: @@    PY   ?33?9/9+393333310!#####3 tpBpp:n$R@*    `Y ?222??9/93+339333333331033!3#####!!&'n)6м 3('YEW:Q@)    PY ?222?39/93+339333333331033!3###### !tp:Bppqny)Y@-     `Y_Y ?33?+9/33+3933333333310#54.'##5%! ![Ƥ[  GCx/ʹ\r\ |}z:_@0  QYPY?33?+99//3+3933333333310!#54.'#"#5467!!;|>ȔMOFDQEFFkƯi~!k@7  ! #"`Y!_Y ?222??+9/33+3393333333333331033!!#54.'##57! !GE[Ƥ[Cx|/ʹ\r\*|v:!$m@8 "#!! &%  PY$#PY ?222??+9/33+3393333333333331033!!#54.'#"#5467!!BȔM;|>8<O:kƯFFDQEFF+Q~`WpT@M)&6KA@ &,,&@KUVC=_YC CCH)`Y2OOH#AHH8_YH#@### `Y#?+3/332/2/+39/93+93/_^]+9333333933104&+532654&#"'>737>32&#"32>32#4#"#"&54>7>GG~37[H6S-B X0Rsm;:kc]-^mJVl~CTlW?#vw{k{u=SC8M> [\;$ 3)l!dM"zWn>%>Y WM@LDC1 - *9*1CONF@PYF FFK5- PYK 'CKK;PYK#'@'''QY'?+3/332/2/+39/9+933/_^]+9333933233104>7>54!52654&#"'6737>32&#"32>32#4#"#"& Hk9c]Yq $Լ[H6S-B [pgyRpO*:\RN-[jJEWlD{Nc<-L=ȉTXJVJF,YC8M>fe  m_P.$t$}hM#C<@  `Y ??339/3+393333310!".'33332653+cr\30PmP8¿S6k-GD̯;UDW:<@    PY  ??3+3?3393333310%>53#.'33w\(#TWwrkQRia.P@+,!0/*_Y$_Y$ *$*$ _Y _Y?+?+99//_^]++99333310#"$5!22$7#".#"">32327&שŦrJ}=Q>}LOq7vcMR}4+5+Is("$%!9VN (N@*" )*PY$ PY $$PYPY?+?+99//_^]++99333310#"!2"3267#".%27.#"632xE= I64WNJ&?= >?2OKO!0#ð !)!!!(! V&@ _Y ??9?+9310!#3?632&#"(,;-LK0TMa37 iN+7)E3GN&@  SY ??9?+9310!#37632&#"ew 8JBrQAT.8:@( [?4L VL&"mh@  &>%+55+55&#@ &Q %+55+55aW (O@*"!! $%% )*# $$!PY _Y _Y?+?+?+?39993333310#"32#"32"'532?3 3J2&.bg2tVwWS|-+ +5vUWN 'M@)! $ ()"## PYQYQY?+?+?+?3999333310# 324&#"326"'532?3 3d|˻crsifnwfFJ2&.bq(~P2 +5v6t0J@&% ("." 21""_Y+(.( (_Y ?33+3?3399+39333310%>32#"&'$>32654'#"&'6X'T43U(YݾV56UX87YZ89Z3+55+~-87-30<<01/1>>1+-I@$#,&   /.  PY) ,& &PY ?33+3?399+3993993321047>32#"&'&7>32>54&'#"&'+R43RR33QU65S{ts{T55S-77,,75+$00<:.ն.:9-7l 1EP{@A2+LFOO< RQE223 # '!"$5!2.#"326732#""&'.#"#>323%#65#5HNR@jˡj@SMKCg5AA4hCferFv ߤAo\ %jSNW#mmLR}# VEEV?, 58?.mp*@91b*<4:bGWw%0D~@F1,/'../;FE1;//+000;++;0>>7QY>> >PY #PY ?3?+?+?3/_^]+9///_^]9/39933933221044#"'#"4>3"3267326#65#5"&'.#"#>323p㻃pٕX1-Z %jSNferFv ߤAo\"ĖSS:-+<rb*<4:bG58?.mp*@91r F& Ph??&@@5!%+5+5& l@  &!! %+5+5hUl4@  _Y _Y?+?3/+933310$!2.#"327n@.G1ٕ(,Uy7T<{ PWL1@ PY PY??+?3/+93310&532.#"327ri=.W" Zj ?@     //993993999333310%%#%7%73)Nd))\M)a~^_`5]^^_{` ?3210#!#"&5463!54632`I5C.2BI5[C.2Bq2<8<@42<8<@L  /333/310#.#"+53267632LY55!B&thfi4X*aFcgJ@&H .}Ib /9/10##.=bYNw#̺^k3rLIb /9/10#65#5b%wNY̒Jm:k^;.  /32210"&'.#"#>323.ferFv ߤAo\>58?.mp*@91% '1;EOh@5F#K>C HH%M2 7 449(-**/KCM79-//-97MCKA</3/39////////33333333333333333333104#"#324#"#324#"#324#"#324#"#324#"#324#"#32%4#"#32rrgrrgrrg-rrgrrgrrgrrgrrgĕ敕&k '1;EO%@OME@C0'%  /3/3/3/33??33/310#65#5546733#"&'5353%32&##&'''.'77'67'77>7EdBKdBKjzD])XQzD])XQ=V0/ G95nEV0/ F95o V1S1Gl:5nV0T1Gn95m;zD])XPzD])XPdBK4dBKW0T1Fm85nV0T1Gm95n>V0/ G:5nV1. G96mf:\@1  _Y p ??399]29?+993333333333103333##47  33273X dr,zZ@[@-  @ SY ??+?99?299933333333331033##467#% 33273< ٬y :Ceg(77:v@N@(  _Y`Y_Y??+99//3+3+993333333103533#!2#!#4&#!! +@דҾyN@(  QYQYQY??+99//3+3+99333333310533#!2#!#532654&+ww ?z.xtl\c^W\@0      _Y_Y??+99//3+399933922910#!#!2)!27'76(wbQVtks~MslflGʟn}`-|ao6W!M-[@1*,$$ /.  PY),++''PY?3+39???+999933333910'#"'##4'33>324&#"327'76^bd^WyV0ƽzky?X8ve_#"jZe6Y61fd]Z*[hb#@ _Y/??+9933103!# %@ PY??+/993310!#!3!B٣8:/ =@     `Y _Y?+?9/3+39933933103!!!!##8\&\@m: ?@  PY  QY ??+9/3+3999222310!3###53˴zz:τW O@)"!_Y_Y _Y?+9?+9/9+93333310#"$'732&#"#!!63 <-α:qj_& !ZM% %1[W: P@*"!PYPY PY?+?9/?+9/9+93333310%#"&'732654.#"#!!632tӋ.yfUbtfaSts|\{ TKpV c:t#uhN'|@@" &&' ' ')("%`Y! !_Y! '?3?33/?+9///3+3339333399333339910"&'#&'3332>733####R%oU0o`XKKZbk0p1Um' U#ϧk(k)o1f# {hS:'|@@!#  #)(!  QYQY  ''"QY'% ?3?33/?+99//3+3+33933333399339910##"&'#&'3332>33##uAAa#]ؼBH;.04Bü]#N% # PEj]$&3\;3CWp5o@:(%%+0 +763`Y3.@(`Y".. `Y .""_Y"?+3/?33/+9/+9+9333333399103254'.'7!2654&+532654&#"'6$32#"'7YVQwGG~3FtsS#PAMvw{k{u=ǩ |R_n"1W^N3r@;%" ."")) 45%PYPY1QY1@, PY ?3/+3+?+3/9/+993333333991032654'.'732654!52654&#"'!2#"'WN@;,5`qc]Yq .KΑgy!wxgT"=?OG|~,^[ȉTXJVJF~e  m}kVkq!hQ@( `Y _Y?2/?+99//+?99333333991032>733####KZbk0m.Um')o1f# {h:T@+ QYQY QY?2/?+9/++?33333933991032>33####04Bü]#N%A:&3\;3 #\@.   `Y   ?3?39///333+339933339933310##3273>3##:1@+s!v0s{'.f#k:\@.    PY    ?3?39///333+339333339933310##32733##%(iݼ]#ai#:& IvU@+ `Y`Y ?3?399//3+333+9933333399103533#2>73####KZbk0Um'ד)o1f# { [@. QY QY ??9/3+3?39/3+33339333339910353!!2>3#### 004Bü]#aA93\; #)N@(  `Y  _Y?+??39/3+39333339910!2>73###!)KZbk0Um'?)o1f# {(O:G@$  QY  PY?+??39/3+99333339910!2>3###!(04Bü]#aA:&3\; #hC@#  _Y _Y ??3/?+9/+93333310!#3!33##asThW:F@$     QYQY??3/?9/++39933333310!#3!373##)y:6G =@  _Y _Y ?3??+9/+9333310!!#3!!!a@sT : =@    QY PY?+?39/+?9333310!!!#!#BӴ:6ʋQ:W!S@+ !! #" _Y _Y_Y?3+9?+9/9+933333310!!#!63 #"$'732&#"ax <-αJ[ZM% $31W:"V@- !!$#PY!""PY" ! PY ?+?39/?+9/9+933333310632#"&'732654.#"#!#ts|tӋ.yfUbtf":#uޗ{ TKpV cN:>+7Z@3 //5$$'2 892' ,_Y  _Y _Y)_Y?+?+?+3/+99333310%#"'# 4632&#"327&5432327"654&kȀ眄WOFkZRQhII@ 5j{2DGvy0D07./46/.5#7%%-Nu޲'xvti44hWy'v@E%$$  )(% %%!!_Y!`Y @P  _Y ?+3/_^]3/+9?+3/_^]93333310"3 #"'53254'&$5!2.(KtsSYV֝lB.G1%N|R_n"#PAHQ~<{WWN(@R# *) p`p &&QY&!!QY! PY ??3/+?+3/?+9/_^]q]9333331032654'&32.#"3267#"'WN@;ri`{"wxgT"=?OG Zjhl wNkq!.h 4@   _Y _Y?+?+3933103##!5!Ќ圜#h: 5@    QY QY?+3?+93310!5!!3##{dt_ "@   ??39933310#373<&--'HH9gfAW: @   ??399333103?3e 8:]W8P(5W_6@   _Y ?3?9/33+393333310!373!!#!>F&--'FffgfA_HW:6@  PY ?2+3?39?933333103!3?3!!#!d>e 8:]>´:P(5Ɗ.hBO@*      _Y ??3/?+9993333333910 # 3 3 3##P}6h)bh:O@*      QY ??3/?+9993333333910 # 3 3 3## *d.D,[U1h9>@!    _Y _Y?+3??+3933310!!!33#!!1&h^;?@!    QY PY?+3??+39333310!!!33#!!&Lݴ;Ih:<@  _Y _Y?3?+9/+9333310#"&5332733##Gھ"R{l1E&:@ PY PY?+?39/+9333310###".5332733nJ?Y8ft-4ouɅaD$6nV@-  `Y  _Y  ?3?9///3+33/+933333310"&533673##W۾z{xj{³Rxl1 ") z:V@-  QY  PY  ?3?9///3+33/+933333310"&533673##6pBvwApyn 0"/-@  _Y  ?3?9/+9933310!4&#"#3$3  ?zm2 ;K ")^@1& ' *+_Y&  #`Y _Y ?+3/?+99//_^]3+39333333103267# #"&5473;!2"!& Λ9RCvz'f!4_ ryFU1:;;2p.X$?  N$V@,$  &%  PY$ !PY PY ?+3/?+99//3+39333333103267!"#"5473;>3 '.#"ua 4zݺ^H-=>;2p %,m@9)) *## -._Y)  &`Y @  _Y ?+3/3?+99//_^]3+393333333103267#$#"&5473;!2"!& Λ9IÆCvz'f!4_ ryF$S:;;2p.X$?  N&k@7&   '(PY& #PY @  QY ?+3/3?+99//3+39333333333103267#$#"5473;>3 '.#"uXۆr4zݺ^H-&(=>;2p|,G+&];@ $$&&&,%+5+5S&Y@ $$&&&,%+5+5W"S@) $# `Y _Y?+9?39/+3993333333910%#"$'73254$!##32>73<.~ǿKZbkp45Ѽߝ]Ox)o1f2W:#V@+!%$!QY PY?+?9/?39/+3993333333910%#"&'732654.+#32>3rҎ.yfn|04BüT&\z TK] :&3\;|$fR:@ _Y_Y _Y?+?+?+933310! #"'532>!3##^18`~:%5C:::*Z A)B, ::@ QY PY SY?+?+?+9333310#! #"'5326!3Y~;@JmV2,+7C7#,Ϊ7LϜJ nEg(W F@#   _Y   _Y ?+9?39/+993333331032!#3!3!"$'p.Լ9h\NsTlW:M@&   PY QY   ??39/+?+9/99333333103265!#3!3#"&'Ilk~xų"VJ:6f=@   _Y   _Y?+??39/+993333310#!#3!33pfsT,:C@"   QY  SY ?+??39/+9933333310!33##!#B紻¬:6g(7:h@@! _Y @_Y ?3?+9/+9333310%3#"&533273##eGھ\"R{l1hzh:<@   PY  QY ?+?39/+93333103273##3#"&5.n}lN~:n/hJ8f"G@%!#$"  @_Y?+?3?9?933333310%3##4?#./#3>73ļ (' Dw%3 p}"k@pT/;(:G@% @SY ?3?9??+933333310!##!67!3##?4. ¬zG,:k}g(7rs>OR&$ z@ &%+5+5Ws&D11&4Դ4:%+5+5R&$n@&%+55+55Ws{&Di@ 88&6д64%+55+55BN&(  & %+5+5W&H@ &# %+5+5^&O@ ''&%%#%+55+55W{&i@ !!& %+55+55G&m@ ++&))'%+55+55S{&ik@++&))'%+55+55Cp&)@//&--+%%+55+551^{&i@,,&**("%+55+55MT@+  `Y_Y_Y?2/+?+39/+3933393310"$'7!2654&+5!5!wVw?7M𡇅q ܲuDW :R&I@ &%+5+5S&@ &  %+5+5&@ &%+55+55{&i@ & %+55+55a&2@""&  %+55+55V{&Ri@&%+55+55a?@ _Y _Y _Y?+?+9/+99333310#"$5!227!"!&$שŦrJ~_τz.WKG@& _Y?+?9?99333333910#"'532654. # 3 3 K;I:=5CUP}LtX 4@ _Y  _Y ??+9/+99333104>3!3!"$7)! XsܖH{}m%,VG[9 &N@(! !!('$`Y$ _Y `Y?+?9/9+3/?+993933931032>=!"#"$54$3!332653#"&|UL~q後QnbW⻾T7śEoV{)U@,$ $+*  'PY !PY PY?+?+?+9/99?9333393103# '#"!23'33265%32654&#"Ƶ_:Ȏ{2q~~pMxyzib6Zby韟j`")Q@* $''*+`Y%%_Y"`Y?+?+3/9/3/+99333310"&54&+532654&#"'6$323 3dݾGG~3F{|~tw{k{u=ǩ :EUN&Q@* !$ $('PY"" PYPY?+?+3/9/3/+99333310 .#52654&#"'!23253O.c]Yq .KΑgz dKgUTXJVJF~e ca{t=`h#S@+ #! $%`Y!##_Y# _Y?+3/?+9/+9933333104.+532654&#"'6$323##JGG~3Fujz5w{k{u=ǩ UhNU@,   ! PY PYQY?+?+3/9/+993333310%3##4춮&#"'!2_wc]Yq .KΑg%jdTXJVJF~e A"C@#  #$ _Y _Y `Y?+?+?+9/933310"&5! #"'532>!32653^18`~:%5C:::*xwTZ A)B6E : C@# !" QY PY PY?+?+?+9/933310"&5! #"'5326!326=3;@JmV2,+7C7#,~y&LϜJ nEzÞG@$   _Y  `Y?+??39/+3/93333310"&5!#3!332653swsT6E:C@# QY  PY?+??399//+93333310!3326=3#"&=!#B~x:6zÞ\:g*^N".t9@  _Y `Y?+?+39/93310"&5!5!!32653twXҞE#:<@  PYQY?+3?+9/933310!!326=3#"&5!#du~~x뿾:&R&Z@-#$$('`Y _Y ##!_Y?+3/?3/+9/+9993333339910"$5467$54$32.#";#"3 [槛G4{GGuYCФ=r{k{wvMIvN%^@/ "# #'&PY PY "" PY?+3/?3/+9/+99933333399310"&54675.5463 .#"3"327ݿՖ|kѥK. pZ]coe5-l  cFJVJWUfaTf,}W;@!_Y_Y _Y_Y?+++?+93310 #"'532>!#"'5325=18`~:%5C:::*;@,B{Z A)BX W:5@   QYPYPY?+?+?+93310!"'53265! #"'5326!=@,D7:;@JmV2,+7C7#,΁CQ2LϜJ nEa}4VWNT ::ZD!@ @P`/]]29/3310#54&#"#546753f&03'dCFfHC/6..6/1XZ ^^ [W+N #(@ @ H!>?3+]q223104632#"&74632#"&4632#"&+. ".." .. ".." .r. "--" .o -- ".." -- "..".." 00mN >?10#7'7'7vVVVVVVVVVV^N "@ @ H>?3+]q2104632#"&4632#"&`. "0/# .0 0/!".m"--" ..".0 0.`N (@ @ H>?3+]q2104632#"&4632#"&3'." 00 ".. !/." .om"--" .. 0/!"...nN/]2103"&5DtfR\ijhX >?10'7P+! @    >?]99//3310"&5463232654'7#"&'.%9mRA/Q5(7 %9mQ>2S4,19&%@H&xAR5J9/&%@H)uAR6I>*N>?]21044oqhN\hmB/10#'73B)@ @ /3]29/10#52654632#"&ev. !/." .Rji\ 0/!"..NH>?]210463"fsNme_NHNH@ >?2]22310463"!463"fsIfsNme_me_; )+7!@//))55 P##/]333]223104632#"''7&732654&#"'#"&546324&#"326Z~Y[~|];-XRXy7'(:<&$:XRX-;\}~[Y~y:$&<:(&8RY~}ZY~XTX/<(89''98(?]29/310#"'#3326=WW"ee !0&2Xf fL -72D!@@P` /3]]9/3310#5.=3326=3EFfCFd'30&ffZZ \\ Z[1150051H/]210!535#j^/10#'73j/]210#5265ftRjj[H@ /2]22310#5265!#5265grgrRjkZjkZb @/]1057'%㍪3P3L\N;)@ /  P/]3]210'#"&546324&#"326=XTV28YXWw:&':8)(8R=.XTX|[Z}~Y(89'(88D^N >?10#'73NHN>?3]10!535jHP){) / /3]2104632#"&732654&#"~YY~|[[|w8((8:&&:RY~~YY~~Y(88((88P @ @ /3]q2104632#"&4632#"&P/!".0 00 0/!".b!/0 ..".0 0.- #/;'@39!@!!!- '/33333]q223104632#"&74632#"&4632#"&%4632#"&4632#"&. ".." .. ".." .r- #--# -I. ".." .0 0/!".` .. ".." .. "..".." 00".." ..".0 0.@@ /3]q29/3105!74632#"&4632#"&G8-# // #-- #--# -mm@".." .. 00 "..!@@ /3]q29/33105#5!#74632#"&4632#"&nGj-# // #-- #--# -rmmr".." .. 00 "..PB  /3104632#"&P/!".0 0!/0 ..=D  /333104632#"&74632#"&0 0/!".. !/." .".0 0." 0/!"..= #@!@!!! /333]q2104632#"&74632#"&4632#"&."".0 0. ".0 .u0 0/!".b".0 0/!".."".0 .. 00\ /]310!!H}j\/105#5!#5oHkujjuPF  ??3104632#"&P0 0/!". 00 00PF #@ @!!! /3]29/3104632#"&4632#"&4632#"&. ".." .0 0/!".0 0/!".`".." ..I 00 00H".0 0.qP  /3104632#"&P0 00 0#--# --7/310537nyL/33310!!<L\+ /]310!!H+j`//9103` wPFPF91@  CYCY:?++9333105353jP  /3104632#"&P0 00 0f 00 "--jP  /3104632#"&P/!".0 0!/0 ..6@  A @Y9 @Y:?+?+3339104>;#"!!CIN!yY:5 /10##57#5!m͠kBK@       :9?2?39933333323339999103673##>7}Ö 7.+5aiD94qTM2!#.Hl24>9E ~J}Ɖ//}Nvvif9=??93103#Hy6@  A @Y 9@Y:?+?+333910)5!4.+532yy!NJD;Y˷3A@  @Y ;@Y9?+3?+333933310467#5! ! 32654&#;'Cy3X5?w5X)B 3@    <9?3?399333393107 7363)HzCi3Xd1X=@   @Y = @Y9?+?9/+3333910 #4&#!3!VRRqL@ @Y A @Y 9@Y:?+?+9/+333393104&#!3!! )5!265R ]R 6@  9=??39/33333393310#4.3>?3,f٬c \h5 YwP}, G@  9@Y:?+3?39333333993310)5!3>?3P}MF 7f]?!!ی`%P{H?@  A ;=@Y9?+??39/33339310#!25654&#!f3ub)x^OІf' &  :@Y9?+?33910!#4&#!5! yѶ3P@BY9AY:?+?339/+933993310332>7337>73dt1M?@r{IlV Q#/d ?y=A@@Y: @Y9?+3?3+33339310#5! #4&#!+532>5𸕹C FP"!1ѸY3lmd&d&Fd&H@ 6?933310#3`{-@ 6?329933333310#3#3`׉{{: ?@!   PY /   ?3?99//]9+9993310!#!#3 vutF5:3:^@4   PYPY PY    PY?+??99//_^]+++39339933310)!#!!!!!!#Kb? @^L:KBL'4;@R-" ;(;5&&;=<$8PY$'5PY(QY '"( ('('(   PY 0PY PY ?+3/?+?+3/_^]99//]99++?+933333399333105!"'! >323267#"'# 57>54&#"3267< uaXAfOҒoy~q cv#ÀLd]fV Cq^H-u;oP\?/bRWaYWī):&^@0#  (' PY PYPY?+?+9/_^]33+33993333333333103!23##!#!!2654&#32654&#uK!-2u)yfnqyffyb؞dF]3RRYSURRVWNF:(@  PY PY?+?+993310)! 4&+326n(ĸ-:ʵ: P@)    PY   PY PY?+?+9/_^]3+399392223103! )#%4&+3#326n(dĸ񻷷pIʵŠ: G@%   PY PY PY?+?+9/_^]+99923310)!!!!!$d:1^N$b@2  ""&%&  PY PYPY?2/+?+3/9/+9_^]993333339910"&'732654!52654&#"'!2ʧ-5`qc]Yq .KΑgy},^[ȉTXJVJF~e  mn=: @ ??933310#5#=欬 :0:.@  PY PY?2/+?+9939210 73265#5!{4_@O^'dZhrc:: <@       PY?+?99//99333310)5737!wwweep:A@% ? ??3?39]]9333310!##!67!#?4. G,:k}rs: H@,   p   ?3?399]qr993333103#467#< Ŭ:e$:VNR=N>1 &@SY SY/+/+993310 ! 4$"32654&n꽅Ak*@  SY /333/+93310".54$! '>54&whl Zj"`ri/^"D@'   $# SY SY/2+/3+99333310% $547'563 ''27"654&sbt֊0[iɅ\X݂U1Q2vdSs[QDMCW3N%,m@:& ,!,-.&PY  )PYPY #PY  PY ?+3/?+?+?+9/99+933399333104&#"'! 6!2# '! 53265!"3267[uaXz|u~#֤C^H-籱?'Cd:%E@!  &'@  #QY ?+?39/99993333339910#"&54675.5332#"326MyСxyf\!lrtnmq:ҿC VN &@   PY ?+29933104&#"#!2`0V &@   PY ?+299331032653#"!: 4@  PY  PY??+9/+9933310!#!2#!!2654&#Bβظivuj:ze`^c: I@$  QYQY ?3?+9/+399333339910 #&463!##";Xxk|63\]^]: D@"   QY  QY?+?39/3+993333399103!"&573#";P;|kxpƖ36}]^]\#:;@" ?    QY?+3?_^]]]]9310!!#!#d:I:tDX*@  /2/993333310!2>54&#!5!27#!Dkv4S*,9Op]/ *\Y>yEX"H@" !"$#"  /2/99//93333333310!2>54&#!5!27#!3#3#\kv4S*,9Op]/鸸 *\Y>y>-?Y)<@ ! %!*+) !  /2/9/3993333339910!2654&#!5!27#!5!2654&#!?xS*,9OsZbkm`/x|Vps:l{8qVpv:Y:ZS:]1^:R@)  QYPYPY?2/+?+39/+399333339910"&'732654&+5!5!ʧ-5`y06},dZkb)A+L'd@5 $$()'QYQY '!'' !!PY! PY ?+3?+399//99++9333333310#"327#"&5467532654&#"'>32;xgbT5˗š;xgbT5˗šPQ@Vt|PQ@Vt)M+D@$( !!-,(  $$PY$PY?2+??+399933910"&'7326?'.546323267#"&/-Wu8X!Z-"G]J:ù:J]G"-Z!X9sXWz:779y7?s'4"#[CCZ#"4's?7G[UUZH:@QY??+99310!#:I::L:C@+   `   QY?3?+_^]]qr993310#!#Ǵ/:I::3~6:@@!  PY/   ??339/]3+393333310!".53332653#|6lwc̛4yj :R@7 pp 0`p QY PY PY??++?+_^]qr93310!! #"'5326!h;@JmV2,+7C7#,LϜJ nE5@  Y?  ?3?39/]+33339910!#3 !&mXo/ V{!!e"\AR 6k@;  Y Y    Y Y?+??+399//_^]]++93333993310!#!!!!!#!=&UZ/6!trtug75 P@) Y YY?+?+9/_^]+9993333310#!! 4&+324+326{[VUUosha7rkO{fOBXa"X@,    #$ Y YY?+?+9/33+3399333333399103! 3##!#4+3264&+32$^[VFL{^rj6ha-jBxDm˧XOB2n (@ YY?+?+993310#!!24&+326nt؊< ɠz궿1' E@$  Y Y Y?+?+9/_^]+99333310!!!!!1%itrt  E@$  Y  Y Y?+?+9/_^]+993333105!!5!!5! i%tRr6t0C@# YY Y?+?+99//+9333310432.#"32675!5!#"04)jX5H s{)TO̻73wN\.A 3@   Y ?3?39/+99333310!#3!3 6^c@ ??9310#3V4@   Y Y?+?+9/93310"73265#5!70 R>CND TZb`GtH1[ >@     ?3?39399333339910 #33 väg]P-@Y?+?993103!-t45@     ?33?9?933331047#&'#3?3_!d  z$gGMDiRj!a.A .@   ?3?39999333310 #3&53 6lT\.A ,@    ?2?3999933331033#47.u;ZH+ (@  Y Y?+?+993310#"54324&#"326 ̻4%J@$#  &'Y  Y ?+/39/+999933333399102653#"&5467.53"32654&SbSGVa`WHR^YcseqqcrĀply{rvzcxx- 4@ YY??+9/+9933310#!#!24+!2⡍-r Q@)      Y Y?3?+9/_^]+399333339910!#!24#!!26Ǧ{l3_pf☆mUí_*F$@ Y??+39310#!5!Xntt'F%@   Y?+?3993310"&5332653ԍ|ɯxd&@   ?3?39?910#&'#3?33%ȓvPbpquiVM;#/k@:- ((01 *Y/ YY$Y?+3/+?+3/_^]9/+9933333310"&546?54&#"'6!2327#"&'#'2>=poMQQL (3,F;/y@Bi=}bAyjx~*_N:? ΄}99O LMVJ_@m<>OQ?C#/g@%) -01)Y )@ H))Y@H Y$Y?+?+3/+?+9/+9+93333331023267!"&54&#"56323>"7>54&poMQNL (3,F;*}ADi;}bAyjx~*_N5D ΄}H99O LMSM_An:>OQ?C;"=@ $#  YY?3+?+99?99333310#"&5!23473#&532654&#"/#oTTp#uuQ]h^^g\SeJ?AE3F*e8*Q-(4;@.5( #;4;-;(<=(5Y((% )Y #!)@ H))!@"H!!Y!!%%8Y%0Y Y ?+3/?+?+3/+3/+9/+99+9/+9333339933105.#"'>32>323267!"'# 57>54&#"32674g^P`k%oG7crrLRRO CQgD?Fj9 a]Vc B3 _UcRyjx~*_N6C bbRN=EAl324&#"326To#vz#oTQ]h^^g\Skq?E'"8eylJ?ʝ;"?@#$  YY?3+?+99?993333310#"&5!235'3#&532654&#"/#oTTo#zuQ]h^^g\SeJ?@E?323632#4&#" 8NN\zs&eLTaCpey8ON[kXzsFX`#NCFKkXwvF]8@   YY?+??9?+933310#"'53254&#"#'33>32)*-PBWWg{s,mS{n t h5lWzsFX`#PA; (@  YY?+?+993310!"&5!24&#"326J[jl`^fn_htƞH6@  Y Y ?+3/?3/+99333104&#"'>32#"&'732!Wb~ou{ XBk nv̿˃nLI;h &@   Y ?+29933104&#"#!2L[jl`Jh;h '@   @ Y/+2993310!"&533265^fn_htɖZ$=@  %&Y "Y?+???+9999333310!"'##/33>324&#"326<zv"lVTZk[^g\SkqG$*I?ˢ 9@  Y @Y?+?3+39333310#"5#53733#327<@UZ$R"+-]]7, [1@    Y?+3?39993331032653#'##"&5BWWgzt*nT{nnUzsLD+ f6@  Y  Y /3+3/+993333310!2654&#!5!7#!+nUzsZDMCBWWgzt*nT{n]-&J@%  %% ('& Y"Y?+3/+3?33999333331032653#/##"&'##"&5332658NN\zs+bJTa hWqdy8ON[kXzs`#S>FKCNkXwv @   ??3933910#3>304C!'C@#  )( Y $ Y?+?9/9993?+999310"&'732?'&546323267#".'3S+<4>7 EhY%4b@"4=;+R3';4DI27#2RA)Wndgwwf-aE{W.$R2#,]`+`(X@. " )*Y  %Y Y?+??+9/_^]93+99333339910#"'##463232654>54&#"ꥒ{]{es&qMtefp;6bnex ɾ`(˯e6@  Y ?3?+?93233910#'.#"'6323#g,t/."/9H9`-Fd6\By|ex%gxs`jssxsvba(W@- " )*Y  %Y Y/+//+9/_^]3+993333339910%#"'##463232654>54&#"륒{]zfr$v9beuoWLTIbZB먚u@'o]eodbVGMkx`r$@  /3/933993103>3#67 " .1 /r$fA*d<`#I@' %$ Y!Y @ HY/+/99//+9++9933333107!2!"&'32#.#".4&#"326<JPh%bo7B[jl`_en_s51^8Ue:aM"L@&   $# Y YY//+3/+/+33933333310#.546746324&#">MtSXdfikp:7bne `˰eM|N#*l@8 *$##+,*PY** 'PY  PY PY ?+?+?399?+9/+9/933333393103267!"'#"&533265363 '.#"횔ua~3˵-e`s|ݺ^H-PIRmt4}Vj-9l@7%44    . :;#  '++1PY+ 7PY?+???+9999//9933933333333310!"&'##65&#"#>35332673#'3>324&#"326r{3'kT7Z`72zxy"Yc 60/h|i/0rrtAXhZV,8f@4 33& !!&-&:9($!! 6PY0PY?+?+99?99//9933?933333333310%#"!23'5&#"#>35332673#'#.532654&#"52z{2'kT7Z`7xyhZ6Zby0/h|i/0rrF6t*pZ+m@7*##- )  ,- ) )QY) %PY QY ??+?+?+99//993393333333333331032673#'#&#"#>3#5354632&#"3iZ`7'kT7K4-#E>m/0rrb0/h|Oz F\aN/9B@M3++&"*9//=: *DC+6PY.00<<: :),,#2%:22:%@PY????+9////3333333333?+?999333333339333310!$'##46754'33>323>32653#&%54&#"%54&#"ЏEmZ:l{8q?b_-VpvVpt: RXܽ*,9OsZbkm`$|wH 4w9 x 7yxN'3h@5-#'( '54& , ( ,##, 1PY????+9////33333399933333333310!.'##46754'33>3265354.#"9A{:,-za>yNoaT_?*\YM (.- ;&]ٽ*,9Op]$}wp=? kv4WM.;]@0/6$ =<(,,2PY,# 9PY?+?99//9933??+999333333310!"'#32673#"'#5&#"#>34'33>324&#"326rV Z`#'kT30ƽzky?{"ʼ/0rrv0/h|ǧ61fd]ZN*L@&** $,+* ' $$*SY??+?99//99339933333103&#"#>34'33>32&#"32673#"''kT/+pf$%$32&#"32673#"'#&#"#>3\;%$<|nZ`#'kT/f /0rr0/h|K7Q@)(64! 89640 0(%PY" PY?3+?3+933333993333333310#"&'732654&/.#"#67&54632.#"32673!TgU+Kʳnzt+MlAK/a!+WQTT>L%(i)5J~HMJK)7((3,<K,,`@0 ,'' ,.- #    QY@QY*PY?+?+?+99//9933993333333310%#"5'"#>3#53733#32673#"&'327*Y]&'kT)}5x3Z`:3?$D0/h|5/0rrN?1:![@0"#PY PY?+3?99//9933+393333910"'!!5&#"#>32!5!326733{38'oU5~8J*Z'w 0/h| =00rrW K,K@&& .- )PY #PYPY?2+?3/+9/99+99333333102.# 3632#"&'##6532654&#"R{diǻs. HS~vUHKKQŮiafS6;:edb ?@!  Y@ H  ?3/?3/9/++99333310!#3!31wwXxC(3MW/: ,Q@*** $ .-!PY  'PY PY ?+3?+9/9+933333331074>3.546?!5!#"."32654&M~ރ )+9%-=]k]=玏{횣8y <&)<,$6CUtexw履*3@H%%& ,& 3&54 2//*PY/%'!PY QY@ QY?+?+??+?9??+9993333333333923107&5#53733#33632#4.#"#327#"'# }5x]9E*`UC$DY]I0.}-;҃u~^T/ro4&D: 2@    PY ??9/3+393333310333###mrrmi/:WiM%,l@7*"")#.-#@))   PY &PY ??+?+9/_^]9933/22?99333333333310354'33>323#!"'###267!"!.l0 NMVlA}|  {i61fd]YQB:U@+    PY PY?3?+9/_^]33+3399333333331033!33##"&=#26=!geegwwi//{Ÿ{XX :#,k@8 '' **#!!.-)##PY  $PYPY?3+3?+9/_^]33+339933393322223103>7!5!!.'5!!3##"=#26=! ][iNwMwNg\_LJ;iQf&zy&eR$ W$0S@,%++ 21""(PY".PY PY?+?+???+999933333210!"'532=#"&'##6533>324&#"326^;I2E}?H{32zxy"wYc 6YAXhZVWB ,W@/''!.-PYPY *PY$PY?+?+99??+?+933333310%#"!23'33!"'532=#.532654&#"52z{2Y;I2E}VxyhZ6Zbywt*pW<!P@,  #"QYPYQYPY PY?+?+?+?+?+933323103!"'532=##5354632&#"3iT6E/?}_K4-#E>wz F\aVWK.<w@@)(/ 6 )>=%(PY ((3PY9PY,PY,, PY5 &  ?3]]+3/+?+?+9/99+?9333333331032=!!"&'73 5##"3234673!!"'4.#"32>+-(v;{d 3wǻs.).HS~vUH f8KQ;hiia6MedWS@,  PY   PY?+???9339?+99333339102=##33 3!"'5}'IZq;I2wma /2W-@   PY  PY?+??+9331032=#33!"'+5dW-@ w WN5c@6- +"55 &"76- PY-$)PY$1PY PY  ?3??+99?+?+?+93333333310!4&#"#4'33>323>323!"'532=#4&#"Vps:l{8qb;I2E}kVpvxS*,9OsZbkm`wxWHN&N@)$   ('"PY" PYPY?+???+9?+993333333102=#4.#"#4'33>323!"'5"}f*\Y>yZ;I2wkv4S*,9Op]WM%2W@.&-  43##)PY#0PY PY?+?+???+99939933333210!"'5326=#"'##4'33>324&#"326|;I2E=@67V0ƽzky?{"ËCQp Y61fd]ZWNI@& ! PY SYPY?+??+9?+99339333102=#4'33>32&#"3!"'5o}^+pf$%$r%f g9WK4Q@)%$$ +65+ !!(PY%! PY PY?+?3+?3+99993933232310!"'532=#"&'732654&/.54632.#";I2E}l!XbJʳnzt0^~I(3WQTT@P"(MnP~HMJK.<*%$=Ja>W%N@+  '&PYPY # #PY# PY ?+?+9///++3933331032>5!2&#"!!"'532=!#"'Y5!6;=pxyn .]!v(-.) EZcYF_;rRZ$. (y |gZSY0dQX`VVN"._@2 ##!! )0/ &PYPYSY,PY !PY ?+?+++?+99?99333333310327# 5#'5##"!23467334&#"326-v(-.)Q6{6Dxyx (w;k[6We;jVW".R@+)""#0/ PY PY  ,PY &PY?+?+99?+?+9933333310%##"!23'5!2&#"327# 32654&#"92z{2AF:;yz@*?=xyhZ6Zby((WWN$[@. $$&%$PY$$!PYPY PY?+?+?+9/+9/993333333103267327# 5#"3 '.#"uz@*?=hݺ^H-(D IWZN/s@;"--$ ($ $10+&PY+PY PY ."" PY?+3/9?3/+9/+9?+993333339933310"&54675.5463 .#"3"327327# 5ݿՖ|kѥK. pZ]coe5z@*?=cl  cFJVJWUfaTf,(<5WbN/j@7&##* *10&PY /- -- PY- PY PY?+?+3/?+3/99/+993333339910327# 732654춮&#"'!2#"'z@*?=5eoc]Yq .KҎj{c{(k,eUafTXJVJFc  m<XWN%`@1%% '&PY  "PYPY PY ?+3/?+?+9/3+39933333333104&#"'!23327# # 53267\uaX z@*?=#C^H-D(;?W|?@! SYSY PY?+?+??+933333310 5#3332753_[z@*?LW(:aɬ=WN#F@% ""%$ PY PY  PY?+3/?+3/9?+93331032654&#"'>32#"'327# `ir٧fz@*?=NlhjZG(WG!?@ #""PY PY PY ?+?+9/+33993310%327#"&=32>54632&#"<|/;@*?=<927k,1BMKέ B:'NgiW:$K@'  # #&% PY  PYPY ???+?+?+99933333310326533327# 5#.'##"&5:*\YYzA$?8M>y:Rkv4sa(,9Op]DW :%s@>   $$'&PY  QY@ H ""PY"  PY?+3?+99//_^]++3+3/99933333910732654&+5!5!#"'327# RvUsy׊vD>@*?=̃ugUgel2IK(AW!A@! #" YY?+???+999933333310>32!"&'##4'34&#"326"oTTo"{uvP]h^^fZUjJ?p@EU!]1J@.@  Y Y ?+3?3+9933103267#"&54632&#"BV |wr~bVlILmľxl 3'S@."&)($Y& Y Y`?]+?3+9/9+93333310"''7&54632&#"632'2>54#"|lM#TJCr~aW?y[8M)Tpc/874Aufxl _E=^9^0K32'Z@/   ")(    Y%Y?+?9/9+33/99933393310"&54632&'57&'374&#"326y^@JV̔?f4?Аp{(]mn_bbodݵ*P]PB5;0]OAia}}}'Q%x@D#!! '&#Y@H@ H@HY Y@?3/]+?+3/+_^]9/+++9993333339910#"&'732654&+532654&#"'>32Q| y KMMNA=?MCEuz oxRXduwz E?=DdA76E jyra}0b.E@#  YY Y ??+9/+3/+993333310##5354632'"3{ggX\96/*a\Uh\a1AD\,D@"  YY Y ?/+9/+3/+99333331033##"'526=#5{ggX\96/*\h\a1A\;h`9@  YO _ o  ?3?9/]9+99333310#"&5332653#475)oTwr{GQXf{{MD}tO}hp. @@!   Y@ H??9/+3+3?39333333310#5333#53dSSyQQyyjX9Xyyd@ ??93103dyd@ ??93103dy. 6@   Y@ H??9/+3+393333310#5333#dSSyQQjX9X%T@,  ! Y Y  Y?+?9/_^]3+3?+339333333107"&546;33#'26=#"53m|ckz]]yz;>}4,7zaYYZGbjdMJ))'.dyyWd $@  YY?++?39310327#"53'%$","{9/ r q 4@   Y @ Y?++?933331032=#33#"' "VDz<(#6hTWX@Y?+?99310!3!Sx5n[*-Q@,-$$(./&+Y& Y  Y?3?99?+?+?+9333333104&#"#4&#"#'33>323632#"'53258NN\y8NN\ys&eLSaCpd*2%,QlXwvFlX{rFX`#NCFK s i[&#M@' "" %$ #YY ??+3/+?339939333331032653##"&'##"&533265}9MN\yx&eKSa iWpdy9MN\mVzsL=EKBN~mVwv:@  !Y Y ??+?9?+9933333104'33>32#4&#"#"'5325bt,mSzo{BVWg(5"/PB`#PApT{r r i_F:@   YY?+??9?+993333310327#"54&#"#'33>32P+**BUXgzs,mR{ni t >pT{rFX`#PA_.@  ?3?39999333310'3#&'#=tr s.X@s,: K@* Y@H@ HY Y?+?+9/+++99333310!"&5!2267!"!.Jf^s_dc`[is {}\{}w7S@+   Y YY??3+3?+3/+?9333333310%.5%34&'>%D pHLKIoID!d$÷ $N/1S@*, !'0!032.)Y.$&$$$Y$Y?3/+?+3/999+99393322103254.'.54632&#"#"'327#"5bW!=xg\2znSO6APyW4sOS $+"=9v$- 6O8hmXci36(2!6T>lu*per2@  Y Y YY?++?++9333107"'532>54632&#" 1*0 $)efI#+62 q:L7y vKY"I@%  Y Y Y?+?+?3+3?99333333310#"'5326=#"5#53733#327,0%$#* UY$R",( q (9O\\8, !\@0   #" Y @ H Y ??+?39/+933+3339933333333310!33##'##"&=#5326=!WzIIt,nQ{oHHXgBG^Q?~W^GZs>nU81I@$ *!!&//23' Y*$ Y?+?399+3993333333310"&54>54&+53232654.546;#"$*$8TWC5bF?/FAE.qr.EAF/?Fb5CW>[%@   Y?+?3993310"&533253{{ݎ%W)@  Y?+?39933310#"&53324&'3{LW)%!+}ٓ)gh;]LH @    ??39339103#'# 04C< 5@  YY?+3?+3993333105!5!!<Y1>`9b`b.J@'  Y  Y YY?++?+3?+39933333310327#"=!5!5!!&!1$Y1>90q [`9ba%mT@+  !YYY ?3+33?9/++3993993332210>32+'7#5!5!%"32654&$FBRZ^h^%Z0>{BQu40&LyoXHTV:C+Ra8b`ǁ &.M@'  Y Y Y?+3?3/+9/+99333339910!#"&'732654&+5!NYyer{p8 "~‰ une< G@%Y Y Y?+?+9/_^]+99333310#"!2267!"!.=aYXbaXsUAkɺP) @  /2/2/99105375353,Ҿ_6`B%!}) @  /3299//1053%5353_!F%Nf,)/910"54>54.54>54#"'632Z!)!!)!$*$1+/ <   ] /32310#"#"&5332>;]"8``g@mB94Z]iC#Z%-%m9G(0(,Y/+10!5!7,:h:@ Y//]+10!%7!:@:Ԕl,@ Y//]+10'!5!WԀ:@ Y//]+10!'%!:@WTlb@ /332310'%77==Amzzmb@ /22322310''%7v=,=ԀmzzmoWl  /339104'33>3&#"T71$=5W>J0!ZG7t}! /910%5!r``rRV @  /93/391057'5#373窪Rr``rRr``rWR&$@ %+55WWsN&D97Դ71%+55&%%""& ˴ "%+5+5&E ''&+5&%  "%+5&E  % %' %+5&%!!"%+5&E7&&' %+5hNy'&&x& 4]+5Wb'x&Ftg22&4]+5e&'%&%+5+5V&G ##&+5e&' H%+5V&G $$&%+5e&'%+5V&G) %%&%+59e&'%+5V9&G'',%+5We&'%+5VW&G**$%+5+&( @ & %+55+55W&H'C!@0&+5/]q5+&( & %+55+55W&H'tn!@0 &+5/]q5W&(  %+5WWN&HI ! ! %+5W&(! %+5WWN&H6##/ %+5NP&('jx@  &%+5+5WN&H'x*@ &# %+5+5&)%@  & %  %+5+5<&I%@ &K%+5+5g&*I@  &!!"%+5+5VWS&J@ 00&1 12%+5+5 &+%@ &   %+5+5&K~%@ &6%+5+5 &+ k  %+5&K %+5 &+@ & %+55+55&Ki"j@ &'%+55+55N &+xlN&Kxr &+ %+5r&K> $%+5W&, %+5|WI&L %+5M+&, 2"@& %+555+555{&&it#@/o&+55/]q5?&.@ &   %+5+5&N(& q  %+5+5?&. A  %+5&N  Ǵ  %+5?&.´ %+5&N&ߴ %+5/&/    %+5>&O z%+5/&/' 'I  &+5&O' {N &+5/&/i %+5&O %+5W/&/d %+5W&&O %+5&0@  &O%+5+5#&Pt@ //&+}+. %+5+5&0c%@ &%+5+5#&Pc@ --&++- %+5+5&0  %+5#N&P  ++- %+5 &1%& %+5+5&QT@ & %+5+5 &1 q %+5N&Q  %+5 &1 %+5N&Q: %+5W &1 %+5WN&Q:"" %+5a+&2 #@#&##/%+55+55V&R' *@444P444& ,%+55+5/]]5a+&2  @+&++7%+555+555V&R' ]@I4/4?4_44/4?4O4_4o44444/4?4_4o4444 44&332 ,% ,%+5+55+5/]]qr55a+&2 @ ""&##$%+55+55V&R'C.@ 0&%+55+5/]q5a+&2 $&$$#%+55+55V&R't_.@ 0&%+55+5/]q5&3&%+5+5W&Stm@ **&&8&) %+5+5&3%&%+5+5W&Ss@ ((&&&( %+5+5h&5%& %+5+5&U@ & %+5+5h&5 fǴ %+5N&U  %+5h&5'I f@ & %+5+5tS&U' A@ & %+5+5h&5 %+5TN&Ugߴ %+5]&6%@ 11&//1%+5+59&V@ ..&,,.%+5+5]&6 D //1%+59K&V  ,,.%+5]&6 @77&0j06%+55+559&V @44&-7-3%+55+55]+&6 @ 33&55;%+55+559&V @00&228%+55+55]&6'% C@ ..&//1%+5+59&V' @ ..&,,.%+5+5.&7{%@  & %+5+5*&W% &%+5+5.&7   %+5*,&W  8%+5.&7p %+5`,&WN )%+5.W&7q %+5W,&WS )%+5W)&8%+55W:&X:@    %+55W)&8 )%+5W:&X9 $$0 %+5W)&8%+5W:&X&"" %+5)+&8 @&(%+55+55&X'c *@555P555&$$0 %+55+5/]]5)+&8 !@ &%+555+555u&X'iE@2$/$?$O$o$$?$$$$$$&##"% %+5+55+5/]]q55 M&9 a@ &%+5+5&Y&  %+5+5 M&9 @ %+5:&Y   %+5 &:A& %+5+5&ZCH&%+5+5 &:@ &K %+5+5&Zt&@ &]%+5+5 &:@& %+55+55{&Zi@&%+55+55 &:%@ & %+5+5&Z@ &%+5+5 &: _  %+5:&Z | %+5.+&;%@ &   %+5+5&[ &  %+5+5.+&;o@& %+55+55{&[i@ & %+55+55-)&<%@  &  %+5+5W&\@ & %+5+5A&=A@ &  %+5+5S&]&  %+5+5A&=   %+5S:&]   %+5A&=r   %+5S:&]  %+5&K<%+5 8&Wi @ &%+55+55s&Z@ &%+55+55Ws&\@&  %+55+55Ws&D~>&>>;%+5+5&?P%&%+5+5C%Q@*#""" &'##`Y##  _Y  _Y?+??+9/9+3993333910#"'732654&+5.#"#! CwݎkE52VcP%df '{_7A.^(I%R&$ 4%+5WsN&D 2̴24%+5R+&$@  &%+5+5Ws&D4@@&77;%+5+5R+&$ @&f%+55+55Ws&&D E@==&>D>3%+55+55R+&$ @ &%+55+551s&&D E@ ??&5y5:%+55+55R+&$ @((&)=)%+55+55Wsu&D 1@II&JJ:%+55+55R+&$ @11&%%+55+55Ws&D 1@ 99&CʴC4%+55+55R&$'` C@ &%+5+5Ws&D' @ 66&772%+5+5R+&$ @&"%+55+55Ws&D 1@ 11&4̴4:%+55+55R+&$ @&"%+55+55Ws&D 1@ 11&4̴4:%+55+55R+&$ @&%+55+55Ws+&D 1@ 11&4̴4:%+55+55R+&$ @&%%2%+55+55Ws&D 1@ 11&4̴4:%+55+55R&$' v 4$@&% !%+5+5+5Ws&D' $@11&44:%>̴>@%+5+5+5&( \  %+5WN&H    %+5+&(& %+5+5W&HR@ ))& $ %+5+5&( @ &! %+5+5W&H@ #&##/ %+5+5+&( @&f %+55+55WV&&H E@&&&'q' %+55+55+&( @ & %+55+551&&H E@ ((&# %+55+55+&( @##&$)$ %+55+55Wu&H ;@22&3O3# %+55+55+&( @ ,,&  %+55+55W&H 1"&,, %+55+55&('w \$@& % %+5+5+5W&H'  &+5Q+&,:^@N& % 0@9@P`p@P @P`p]qr^]^]+5+5  & 0D@6& %Opqr]qr+5+5|&, %+5=&L z  %+5a&2 %+5VN&R %+5a+&28@ **&! !%%+5+5V &RG&&&!%+5+5a+&2 @''&(d(%+55+55VJ&&R 9@##&$c$%+55+55a+&2 @ ''&"%+55+55%&&R 9@ %%& %+55+55a+&2 @22&3;3$%+55+55Vu&R 1@//&0C0 %+55+55a+&2 @;;&##/%+55+55V&R 1@ &))%+55+55a&2' $@ &""%&&'%+5+5+5V&R' $@&%""#%+5+5+5a&`9++&'δ'*%+5+5V&ate&&&"մ"%%+5+5a&`++&(c(+%+5+5V&aC&&&#;#&%+5+5a+&`855&,,0%+5+5V &aG00&''+%+5+5a&` /&//;%+5+5V&a*&**6%+5+5a&` '')%+5VN&a ""$%+5)&8 n%+5:&X ٴ %+5)+&8##&%+5+5 &XG**&!!% %+5+5&o$$& #%+5+5&pt++&'մ'*%%+5+5&oZ$$&! !$%+5+5&pC++&((+%%+5+5+&o..&%]%)%+5+5 &pG55&,f,0%%+5+5&o (&(i(4%+5+5&p/&/o/;%%+5+5&o j D "%+5:&p 'F')%%+5-)&<" & %+5+5W&\Ci& %+5+5-)&< B  %+5W:&\ -)+&<@ &%+5+5W &\@ &&&! %+5+5-)&< h@ & %+5+5W&\@  &  , %+5+5Ve0&`d,&,״,(%+5+5Ve0&`d--&1´1,%+5+5Ve0&`d2&2˴2(%+55+55Ve0&`d@ 33&77(%+55+55Ve0&`d@2&2 2)%+55+55Ve0&`d@33&7 7)%+55+55Ve,&`F@ EE&0ʴ0=%+55+55Ve"&`<@ FF&0ʴ0=%+55+55R&$?5R&$Ǔ?5*~'$, ?55*~'$, ?55*~'$, ?55*~'$, ?55?~'$,P 4?55?~'$,P 4?55Fj0&dd@ ,&,,( %+5+5Fj0&dd@ --&1 1, %+5+5Fj0&ddd2&2ش2( %+55+55Fj0&ddd@ 33&7ش7( %+55+55Fj0&dd@2&22) %+55+55Fj0&dd@33&77) %+55+55'( ?5'( ?5V'(X ?55V'(X ?55V'(X  ?55V'(X  ?55jX0&fd@ & %+5+5jX0&fd@  &$$ %+5+5jX0&fd%&%% %+55+55jX0&fd@ &&&** %+55+55jX0&f6d@%&%[% %+55+55jX0&f d@&&&*/* %+55+55jX"&f<@88&# #0 %+55+55jX"&f<@99&##0 %+55+55'+ ?5'+ ?5x'+X ?55*x'+X ?55x'+X  ?55x'+X  ?55x'+X /?55x'+X /?550&hd&  %+5+50&hǝd& %+5+50&hd&ʴ  %+55+550&hd@ &ʴ  %+55+55Q0&hd@&  %+55+55Q0&hd@&  %+55+55YJ&hd@ ((&  %+55+55YJ&hd@ ))&  %+55+55D',?5D',?5',X  ?55',X  ?55',X ?55',X ?55',X '?55',X '?55V0&Rd&%+5+5V0&Rd&!!%+5+5V0&Rd"&"۴"%+55+55V0&Rd@ ##&'۴'%+55+55V0&Rd@"&"/"%+55+55V0&Rd@##&'/'%+55+55;&2d?5;&2d%?5'2 +?55'2 +?55g'2 +?55g'2 +?550&td&%+5+50&td& %+5+50&td!&!Ӵ!%+55+550&td@ ""&&Ӵ&%+55+550&t,d@!&!;!%+55+550&t,d@""&&;&%+55+55"&t<@ 44&,%+55+55"&t<@ 55&,%+55+55U'<,?5'<X ?55'< ?55'<X "?55S0&xd0&00,%+5+5S0&xd11&550%+5+5S0&xd6&66,%+55+55S0&xd@ 77&;;,%+55+55S0&xd@6&6&6-%+55+55S0&xd@77&;&;-%+55+55SJ&xd@ II&44A%+55+55SJ&xd@ JJ&44A%+55+55&Xd.?5&Xd.?5'X 4?55'X 4?553'X 4?553'X 4?553'X G?553'X G?55Ve&`,,&)),%+5+5Ve&`6,,&((+%+5+5Fj&d1,,&)), %+5+5Fj&d6@ ,,&("(+ %+5+5jX&f&д %+5+5jX&f6#@ &N %+5+5&hE&  %+5+5&h6@ &  %+5+5V&R&%+5+5V&R6 @ &(%+5+5&t&%+5+5&t6@ &%+5+5S&xo00&--0%+5+5S&x6@ 00&,K,/%+5+5VWe0&`'d,&,״,(%+5+5VWe0&`'d--&1´1,%+5+5VWe0&`'d2&2˴2(%+55+55VWe0&`'d@ 33&77(%+55+55VWe0&`'d@2&2 2)%+55+55VWe0&`'d@33&7 7)%+55+55VWe"&`'<@ EE&0ʴ0=%+55+55VWe"&`'<@ FF&0ʴ0=%+55+55WR&$&?5WR&$&ǝ?5*W~'$,& ?55*W~'$,& ?55*W~'$,& ?55*W~'$,& ?55?W~'$,&P 4?55?W~'$,&P 4?55jW0&f'd@ & %+5+5jW0&f'd@  &$$ %+5+5jW0&f'd%&%% %+55+55jW0&f'd@ &&&** %+55+55jW0&f'6d@%&%[% %+55+55jW0&f'6d@&&&*/* %+55+55jWJ&f'd@88&# #0 %+55+55jWJ&f'd@99&##0 %+55+55W'+' ?5W'+' ?5Wx'+X&< ?55Wx'+X&< ?55Wx'+X&<  ?55Wx'+X&<  ?55Wx'+X&< %?55Wx'+X&< %?55SW0&x'd 0&00,%+5+5SW0&x'd 0&00,%+5+5SW0&x'd 6&66,%+55+55SW0&x'd @ 77&;;,%+55+55SW0&x'd @6&6&6-%+55+55SW0&x'd @77&;&;-%+55+55SW"&x'< @ II&44A%+55+55SW"&x'< @ JJ&44A%+55+55W&Xd'`.?5W&Xd'`.?5W'X& 4?55W'X& 4?55W3'X& 4?55W3'X& 4?55W3'X& G?55W3'X& G?55Ve&`''&**0%+5+5VeS&`((&)Ĵ)*%+5+5VWe&`&~,,&)),%+5+5VWeN&`22-%+5VWe&`'6,,&((+%+5+5Ve&`0&0Ĵ0<%+5+5VWe&`'0&0Ĵ0<%+5+5R&$ v@ &%+5+5R&$hI@ &%+5+5R&$i?5R&$6?5WR&$ .%+5 @  /9/933910#>5#5--.WMWn53L#W @   ?999310327#"=3!,&!p  @  /9/933910#>5#5--.WMWn53L#$@  /2299333310".#"#>323273*TNG76 [ 0Q?,TNEd\d%-%>9fi=%-%wx:@ ! /322/329999399332105353".#"#>323273&LFA30S ]N(LF@[S *Hĸ "("84r"("l_^6jW&f'& %+5+5jWN&fjW&f'6#& %+5+5jX&f@ #&##/ %+5+5jW&f'@ #&##/ %+5+5"*'(,Wr%+5?5B*'(,6u?5"L'+,W?5BL'+,6u?5W &+ * %+5*n2@    /3/2/9/99333910#53!#>5#5nr--.W MWn53L#*x2@    /3/2/9/993393103#5#>5#5rT--.W  MWn53L#{#N@'!##$%% $! @ H ##/]2/3/33/+33/93333933910".#"#>3232673#>5#5*TNG76 [ /R?,UPG62\c--.W$49ac9%58n,MWn53L#0&h & ش  %+5+5S&h & ״  %+5+5&h&i&F@3/Oo?@P`p& %+555+55/]]q_]5&h&i6F@3/Oo?@P`p& %+555+55/]]q_]5wD&h&Ӵ %+5+5,&h!@ &ܴ& %+555+555dP&,j& %+5+5 1&,N@ &%+5+5 ',,U?5W',,6?5*n0@   /3/2/9/9939310#53!##.=nrW.-- #L36nVM*x0@   /3/2/9/99393103#5##.=rXW.--  #L36nVM{#)@ @ H ##/]2/3/33/+33/10".#"#>3232673##.=*TNG76 [ /R?,UPG62\cW.--$49ac9%58n,#L36nVM&t&ݴ%+5+5S&t&%+5+5&t'i\F@3!!/!O!o!!?!!!@!P!`!p!!!&%+555+55/]]q_]5&t'i6F@3!!/!O!o!!?!!!@!P!`!p!!!&%+555+55/]]q_]5W;0&pd$&$$ %+5+5W;0&pd%%&))$ %+5+5&t&+%+5+5&t@&''2%+555+555-)&< r & %+5+5-)&<lI@  &  %+5+5K'< ?5z'<6 ?5'3?5 *@   /339/333333310#53#53#53uк   *@   /339/333333310#53%3#5#53u<кY /991053E %!SW&x'o SWO&x 6+61%+5SW&x'6 @ +&+7+.%+5+5S&x4&44@%+5+5SW&x' 4&44@%+5+5\&2,?5;'62d?5\&X,?5/'6bXd?5WW&X /+/* %+5D/991053 "@  /9/933910##.=W.--̥#L36nVM* /2/10#*T "@   /?933910#'7'77'*T7777Y7887 @  /?9/3310'7##!'77RJ77}m}8L( @   /?9/33]10##'7!(R77J}78}rLrL1@"Y?O/?o@&+H/+]q+99105!rÉL1@"Y?O/?o@&+H/+]q+99105!ÉL1@"Y?O/?o@&+H/+]q+33105!ÉN&BB1@% ?O_o/]]q5/]q5H #@  [[?++933310546733%+y_YaC}H #@ [[?++933310#65#53H&({^Xi@|H "@ [[/++933310%#65#53H&({^X3jA~~G #@ [ Y ?++993310##.=AX^{(&|@gK_ J@&     [  []]?3+3/+39933333310546733!546733$*z^X%+y_Y_C~ÒaC}K_ J@&    [  []]?3+3/+39933333310#65#53#65#53_"-y^X&({^X]I~Ñi@~K_ J@%   [[]]/3+3/+3/9333333310%#65#53#65#53_#,y^X&({^X3_G~ÐjA~HF&v 7@  Y YYY/?++++9333333310#53%s`arxsa@<   Y[ Y [Y[Y[?++++/++++93333333331053%%%%#5hihixxGQ| @ 0  /]]]9910#"&54632|vqptqss .@    [/33+33933310!53!53!53( //310#!*SmOM) /3/105!#MSO/?9/310###!T @  /?39/3310###!!!TuO @   ?3/9/3310!!5!###uTON7'3?K@.%%[(( F=7=[@7 [ 7 ML4CY:4[:IY:+Y"["1Y" Y [YyMiM]MIM9M+MMMMMMM{MfMIM6MM MiMMMMMyMkMIM;MM MMMMMMMyMkM[M9M+MMMMMMMyMkM9M&M M8MMMMMM@RYMFM)MMMMMMMM{MdMKM?MMMMMMMMpM_M@MMM^]]]]]]]_]]]qqqqqqq_qqqqqrrrrrrrrrr^]]]]]]]]]]qqqqqqqqqqqqrrrrrrrrrrr^]]]]]]]]]]]qqqqqqq???+++?+++?+++993+33+3939933+310!#3%2#"&5464&#"3262#"&5464&#"3262#"&5464&#"3260.COTFIOKI.COTFIOKI.COTFIOKI xwy|׷xwy|귲xwy|UzY@ ?9933103U@ĞzUz&V `]5z'O&dzXQ%@ [/o/]+9310%53 PQm?sYR%@ [/o/]+9310%#5 53RQot?G&@ //]55]55T/3310!5!+u`b??3310!#3q~ H@&   Y Y YY?+?+99//++9333333310353535353[Y@   ?33/9/3103#5!#3###TOON @  ?3/9/3310!!!##:QTN/?9310#!*T&n/?9/310##*TG "@   /?39333310#'77'*TT~~~ݵqqp @    ?3/9/3103#5!3###TON3 N@.Y_o ??39/]q33+3993333310#5!533!'jo=岲o-q(_h5(|t@C  YDTd5  Y Y?+?+9/99_^]_]]+993333333_^]_]10#"&'732654&#"#!!>32|w S@GVQK[CF@;АLFSLKHvuQr lIbwvdIl meb@    Y @# H K[@H@H/?/_]]]++]3/+]2+399333104&#"#'33>326FHUw#cJnaZFd^oA:lyO=g ~^6jd;imxs/N6iegl@>   `Y`Y O   `Y`Y?+?3+99//_^]3+3+933333310&#"!!!!!!&432-_U|$ĸՊhy"(.x@<# " /0"@%,._Y)  @ +_Y ?33+23/99?+333/9299333993333332107&5%7373&'$+#7&'&'0=L0!"UH*9G?W SF*}EV@Uqa8B{tvY32&#"$#"$5!2.+pf$%$=#535#5354632.#"!!!!!27PFYVē"oGrphh\M7.yym9@Ks}w)8#@.c@5. ++,##"", /0'PY@- PY+# ?33??+9?+9333333333331054&#"#4'33>323632#4&#"#5}Vps:l{ߞ{*Vp-$oxS*,9OsZbk/x ;#&)@K)(' %$$! & *+%_Y  # _Y'&)(((?3?39///99333+333333+333993333393332223333231033!33#3##!##535#!5!!'##3'󬎎?\oo`"owqq++՛~)g 'N@&CBB( <""/..H<< 44((POH@H4HH4?++2PY/+%PY_Y?FPY9CCC/C C??!PY?@ H_Y@P0P PPPPPPPPPpP`PPPPPPPP0P PPP;PPPPPPPpP`PPP@PPPoP0P PPP^]]]]]]]qqqqqrrrrrr^]]]]]]]]]qqqqqqqqqrrrrr??+99//_^]+]3/3+33/3_^]_]++?+?3+99++99393333333993333310+#!2!#3 #"&5#53733#327%#"&'73254.'.54632.#"+iq@{LQi]ho5n)7=跪cX$Gmh8 VFWrl<L{zŃbNIbxnx=:i* ;W>pwit04U&7<] &5VQ|#'+.14@A.2165+'#_Y40, _Y($ 21.  ?3?3399//9993333+33333333+3333993333339103#3!#!#!53'#533!3!337!37!!'###3 mBBmslpok>@!>CGG/]**֛qq. ]@  !A9: @Y9@Y:?+?+??9/9/33339933102#54.#!#3!2>53#Y1rpToq0[jG5GRh~)-g@-$$,-,./' @ H !@ H*P--?/]3+2299//]+99333399333333310# 46323'5#53533##&5%32654&#"!!#lV╌Vi#xx~\\xPbo]\obQ27I?{?E6\gg\Pd8a]V+@i '')$$  ,-"QY) QY&    @'/H   @_ sYsY?3+?3+9/_^]qr3^]+q2+3+39933333333339310%267#"#73'7#73632.#"!!!!dxۮ(x( ۯyj(c(l~d[NV[d>(&õ?R@)    _Y ?3?39/933+3399333333339103333!!####j=D#-TTsq.M@(     _Y   ??9+3933333333310%%#5%55%!5!GGGG]@ǜ)is:FU_@S[*VM#133'7S;AS '#V`a'G3GaYMV#  XaY>`Y  03@-3**3^aY O`YD`Y?+?+?+?3/399//+9+9+393333333310#"'#>7>32".'#"&546327756%7674&#"32632654&#"32lV8&2 q$~4Dcn>&JX]dQ&V ;[~B2&O0LNyUHL\XGI],H=4F2wvg@I+=9-p6M=9&ĕQ?7ENSQFXnt2$A\)YXLs߸aqt^atxJyy_*{*)11-W!-M@*"+(/.++%`Y `Y/+?3?+99339393210#"'532654' #546324&#">HPSE>@z&~>30@5)7L\N@~"<73B[D쐀r5FC8N~A %*@f'##  &%  ,+%`Y$   @&0%@%P%0 @ P /   %  % *_Y ??+9///_^]]]]33]2233]22+9933333333933333333103##!##535#535!23#'!!627!!&#!Z}3bQ1wY@NtR8ub~{,,bddcg,#%i@8 "'&""_Y_Y@ _Y #_Y?+?3/+?39/9++3933333333310%53.'>75#5!#5$gQ6|K5pIdݯ|Hv 6jl NDf| BnW"p@;    #$_Y _Y  ??99//933+3333+33?9933333393310!3!!3##!##537)!3&/پ}[檥á~ƨ\]WE !&ddvDSne5@C.55 4/*#$$* 76##,',/_Y  _Y4' ' `Y' `Y ?+/+99//3+39/+339/933339233310!3267!"$547#53>?!5!654&#"'>323#!YDY?u'E zo( (pG(Dy~%/)?\1+Ap~xm!--/G*"h,y ^@0  ! _Y @_Y@_Y?+3/3+?33/+39333333310$%53.'$#F |+R|\?>y\Bu}fov7<",! Aa`_: 6@  PYPY??+9/+99339103!5!!5!K$:Ƌ?P{&y's?5"&r's#?5PN&y'3@!/o  @ ` p /A)?555]]]5]555=N''s"3@!/o@`p/\?555]]]5]555]N''(3@!/o@`p/T?555]]]5]555N''f+@/o/B?555]]]5]555;Nb@A  PY p`p o  PY ?+3/_^]?3/^]q+99333104&#"'>32#"&'7326ir٧`"jZẜ lhd^D $@     /3299339910#&'5673!9>HH>9)CI$ICV $@  /299/9333105673&'#CI$ICV9>HH>9#d^D $@     /3299339910&'3#67!59>HH>9#CI$ICV "@    /299933310%67#&'53+CI$ICV9>HH>9d^D<@     /2333993399339910#&'5673!&'3#679>HH>99>HH>9)CI$ICCI$IC6@   /299/299933333105673&'67#&'5CI$ICCI$IC9>HH>99>HH>9H>@   /299/2999333333310!!5673&'67#&'5 CI$ICCI$IChPX9>HH>99>HH>98*Y@3$,+PY QY /o 'PY/,]?+/_^]q9/3++3993333910 #"&54632374&#"7632.#"326Hք~T 5{.$qpmEQWZRN_˴>cTu(#>Xss @| _Y H  /p ?:`@_pP ]]]]]]]]qqrrrrrrr^]]]qqqqqqqrrr?2^]+?+333993933103!7%.' #3 + ^J ojN"@ _Y/2?+993310!#!No3N0 E@$   _Y _Y ]/+9?99+993333105 5!! !{BHNm0,je`H@ Y?+99105!e`~#@Y@&H/+]+9310533bT@l Y   p P 0  o 0   O /  9       p   o O / ]]]]]qqqqqrrr^]]]]qqqqrrrrr/3?9/^]+9933933210##5!3njuNW]!-R@1"( /.%%++"?@HP/]3]+q29]2]29939210#"#"&54632>32%"32654&.#"326]˄DXɀAaFw83wMSmm33wNTihWFxNӰ傓S~qkop~`@ //993103!!^j8^@   ?2/9933104>32#4&#"tтwgĠN@ PY @   PYtfTD6&I9) gv) {k[K;) {k[I9) 7{m_@0 p@'`Pp`/^]]]]]]]]]qqqqq_qqqqqqqrrrrrr_rrrrrrrrrr^]]]]]]]]]]]]]]]]qqqqqqqqqqqqqrrrrrrrr^]]]]]]qqqqqqqq/+/_^]+933310"'53254632&#"$O7<9W,1BSYNwrB8P,,@ *-.'Y#T"@  //999310#4632#"'&'&#"~?K3% &!$ V?0(4 *''#i@  //9993103#"&546323265";N2$! =/'5)%3%Y?+33105! %iH[??+3103#ؑHK&[Y?+?3+310!!#(in&[Y?+?3+3105!# (%%H$[Y??+3+3103!!Hn%H&[Y?+?3+3105!3 %H-[ Y??+?3+33103!!#iHnnH,@ [Y?+??3+33105!3# %K/ @ [Y?+3?3+33105!!# i%n%H/ @ [Y?+3?3+33105!3! %nH ;@   @ [   Y?3+3??3+3333105!3!!# i%nnqj.@  YY?+?+3333105!5! AّH([[?2?3+3+3103#3#ّhHK Kj < @ [ YY?+?+?33+3310!!!!#(iijב" 8 [ [  Y ?3?+33+3+310!###בnn#j D  [ [  Y Y?+?3?+33+3+310!!#!!#htjo"j :  @ [ Y Y?+?+?33+33105!5!5!# i(qב) : [ @ [ Y?+3?33+3+3105!### ܑב%nj D  [ [ Y Y?+?3?+33+3+310#!5#!5!ґttj)F)ޑqH 9 [  YY??+?+33+33103!!!!iH"ב%H 5 [ [ Y?3?3+3+3+3103!!33A$Hn#nqH D [ [   YY?2?+?+33+3+3103!!3!!ّK$hH"qH :  @ [ Y Y?+?+?33+33105!5!5!3 iqב)%H : [ @ [ Y?+3?33+3+310!5!333$ב%nqH D [ [  Y Y?+?3?+33+3+310!5!3!3!5!$KqFH A @ [  YY??+?+?33+333103!!!!#iiH"ב"H ? [ @ [  Y?+?3?33+33+3103!!#3#AHnn KH P   [[ Y @ Y  ?3?3?+?+33+3+33310#3!!#3!!jt " "H ?  @ [ Y Y?+?+??33+333105!5!5!3# iqבKH = [ @ [ Y?+?3?33+33+3105!3#3# 㑑h%K#KH O  [[  Y Y ?3?+?3?+33+3+333103#3!5!#!5!A㑑tHK )ޑj B   [ @ Y Y?+3??+33+333105!!#5! iiq"h @  [ @ [  Y?+33?33+3+33105!!### ב%nnj S @ [[ Y Y ?3?3+3?+33+333+310#!5!3!!#!5jtttAޑ"בqH B  [ @ Y Y?+3??+33+333105!3!5! Aّ"%H @  [ @ [  Y?+33?33+3+33105!333! ב%nnqH R   [[ Y  Y ?3?3+3?+33+3+333103!!3!5!5!AH"oHZ@  @ [ Y Y ?3+3?3+3??33+3333333105!5!5!3!!!!# iiiqב"ב"HV@    [@ [    Y ?3?33+33?33+333+3333103!!###!5!33AבHnnnnH m  @ [  @ [@ Y Y ?3?3+3?3?3+333+33333+333103!!#!5!3!!#3!5!AבttH"ޑ" mH/?3310!!Umm?/3310!!UH??3310!!U H??3910!!* H??3910!!* *g #'+/37;?CGKOSW[_cgkosw{3#%3#%3#3#%3#%3#3#%3#%3#3#%3#%3#3#%3#%3#3#%3#%3#3#%3#%3#3#%3#%3#3#%3#%3#3#%3#%3#3#%3#%3#3#%3#%3#3#3#3#3#3#3#ghhhhgghhhhhhgg`hhbhh hhahhahhhhhhgghhahhahhhhhhgghhhhhhgg`hhbhhhhhhhhhhhhhhhhhhgghhhhhhhhhhhh"bbbbba```````````c```````````c``````aaaaab^^^^^baaaaa``````bbbbb#`````b``aa`T #'+/37;?CGKOSW[_cgkosw{ #'+/37;?CGKO3#73#73#73#73#73#3#73#73#73#73#73#3#73#73#73#73#73#3#73#73#73#73#73#3#73#73#73#73#73#3#%3#73#73#73#%3#3#'3#'3#'3#'3#'3#3#73#73#73#73#73#3#'3#'3#'3#'3#'3#3#73#73#73#73#73#3#73#73#73#73#73#3#73#73#73#73#73#3#3#3#3#3#3#3#3#3#3#3#3#ghhhhhhhhhhhhgggggghhhhggZhhhhhhhhhhhhgggggghhhhggZhhhhhhhhhhhhgggghhhhgggghhhhhhhhhhhhggggggghhhhggghhhhhhhhhhhhggggggghhhhgggggggghhhhggZhhhhhhhhhhhhhhgggghhgggghhgggghhgggghhgggggghh"bbbbbbbbbbba```````````````````````c```````````````````````c````````````aaaaaaaaaaab^^^^^^^^^^^baaaaaaaaaaa````````````bbbbbbbbbbb#```````````ba```c```c``ab^ba``b#`CIMQUY]aeimquy}  !%)-159=AEIMQ!35#35#35#35#35#353353353353353353353#3#3#3#3#3#335335335335#3'#3'#3'#335335335335#373533533535!355#%355##5##5##5#353353353355##5##5##5#35335335335#3'#3'#3'#3#3'#3'#3'#335335#3'#335335#3735355#5##5#353355##5#35335#3'#3#3'#3+jjjjjjjjjjjkjkjkkkkkjkjkkkkkkkkkkkkkkjkjkkkkkkkkjjjjkjkjkkkjjkjkkkkk?kkkkkkkkjkjkkjkjkkkkkkkkjkjkkjkjkkkkkkkkjjjjkkkkkkkkkjkjjjjjkjkkjjkjVkkjkjkkjkjjkjkkjkjjjjjkkkkk"a"a#`!b!b!`````````````b```^`j````````bbbbbbba``````````````````````````aaaaaaaab^^^^^^^^aaaaaaaa`````````bbbbbbb"bbbbbbb````bbba`````````````aaaab^^^^aaaa`````bbb"bbb{uZT//9910!!{!T!@  //993310!!!7L17}1mi{@ P/]/9910!!imi{*@ P/]/q993310!!!iLPbh?9910!!hL@ ?910! XVRZ?9910 7L@ ?910 LRZ?9910Z79e 1@  /3?39933933310!# 3 #R7Rb`15>.)@  ! /9933104>32#".732>54.#"xyzyy{zxVbcbdbbabdzyyyyxxzba`bbbbbV_R'/7?GOW_gow#"5432'#"5432#"5432#"5432#"5432#"5432#"5432#"5432#"5432#"5432#"5432#"5432#"5432%#"5432#"5432'#"5432488448847575$4884766667557R75576666488448844866$48846666\666675576666666,557775666775Z557w557639D557448775666775557848*557# @  /]99102#"54>jnrotjlw)@ //9933103!32>54.#")vwvvvwvu}Avvvuvvw)#*@ %$ //993333103!4>32#".'32>54.#")QbaabbaabMvwvvvwvu}Aabbaabbavvvuvvwscu (@@   //]]993310#".546324&#"326caDpDegGJLfFFfbJM_}kArEgJGgFffFGeiy $0:p@? :6+%%<;("."51h1Y1G11138"_"o"8@ H"8"8  /]99//+^]3]]]]332993993333210"'4! 4'"2#"&54632#"&54632327#"'ybbZڗ20[. -- ., // ,LL>bbHfj24V .. -- .. --# #-d@9$ (./!)-h-Y-K-=--+&_oO&_&&& /99//]^]3]]]]3329999333310"'4! 4&#"326%4&#"326327'#"'bb. -- ., // ,bb>LLHfjz -- .. -- ..ܺ#Fs;*7~@C5  **.&"## 98+** !"1%*"*""*'o/]33/]339///999933/393333333333310373#'#5&''7&'#5367'767"327654&BBc<-VK1$J>5Byd+N P(nqÉ`c;'--qt>}`+*I-d}>_1M =ƈaaP&'\@3$  )(  /   @@%(H/+/]99//]q2329333333310.54632!!#!5!"327654.LkDrvSVjJ#8\9{RW;=9]B LzK~VSzm FF5_9Vy>=T:_4Q,8>@!0,'6!'!9:,*3$$$-  **/^]]]9999339210&'&54763327632".'#"&54632"32654&+!D;X)$  %$ TttzGSY|~WYz|++   =#"&5467> `FWcO|WZYYc`~G`^ %%a\YRw<48@4((56$+/     //99//]92393310)7>5'#".54672&'&5463267632#".'Fw_59YMF]>d& qtET'iDIt8v_=1mr#6xL/xvL~Ms3A(%&ykVb(NLtt1Ri~x5fZy@    //399310./.54632>32b[ZK6eW&"XaXoV{dBkrxwubVB @   //9/3933310&&'6H zDS%Ut}FiGfY;.@  //9/939333103#654&'#"&54632Lm^/9r@k9:}N,.dyxx {6.Mt \@ "! H@ H  /3/]/3339/++3339333310#"&54632#"&5462%%56{I99zN0*ډs9:|O--&DNqT6/Qovu5-Lxgu28h@7  !     ?/9////////////3993993333333333210##57573%377```L`Y=>YYYYG\YY Y /w@G  `Y`Y@H@ /O_  _Y?+?9/_^]3]+2+3+3933333333103#535#533!!!!!||䅔`@7  PYPY@H / ??9/]3]+2+3+39333333333103#535#5333#3#nnnnnnnn "ޅ@G@%   @ H _Y?+?9/+233/393333103'"#>3332673#"'!#'kT&Z`!0/h|Bv/0rr*L@(   _Y`Y _Y?+?99//3+3+9333333103!2#!##%)!!! Qb\@rMمWh P@) "!_Y_Y _Y ?+?+9/+39339922310!!327#"&5!24&#!!26I/4<2F>;͗IJQLվ{PXs)06;@P7#..43 )1=<3*'*PY40:0QY#'::)@' QY 9  PY_ /  ?3/]q3+3?+?39/93+3+39933333333933310&54673&#"'!23327#"&'#+>=4'7P0Myn .dQr*;!DGd[E aU@{l M[XBꨴRZ$,^.PQpip|gl_QYg/wn@I(zXT`@2   PYQY @QY?+?+?+9?99333333333310#537333327#"'#"}5xIJ3?$DY]h6GXЃp0N?80HhG@$  _Y  _Y?+??39/+9933333310!#!#3!33#sThcH@$    QY PY?+?+93??9933333310>323##4.#"#3=:}u*`Ujcro4~= hAR@(      _Y?+??399339933333339910 3###33>͸>hQ@(      QY????+99339933333993310#33 3##„Iga/ma /Ah :@   _Y  _Y?+3?+3933310#!5!5!!OZhV1h: ;@  PYPY ?+3?+399333331035!5!!#18j&a5:@  _Y _Y??+?+?999933310!5# !273%27&#"vrJàvs G[UR}M8gdN0@ SY ??9?3/+39933310!#3?>32.#"ew 8:*zh`j);$*2:@(5Љ}d<':D $7@%& _Y?2+???9?393102&#"#.'#363767>bqBI2<- 5a-&?8 9#kc9E52ongו#CzN"8@ #$ #SY ????9?3+333910!#'#37367>32.#"ѭ4/Ѳ "#.C\TJz5j?+,6#J:'!ĊBXh.FUd-6>@-E#R@+  %$QY !PY ??+?9/93+3933933310 #'67&54632?654&#"lj3F)&l\qcnU$:"i"/:#$rHfxcY4155-U;M"+'a'@ _Y??9/+993310!#3!as):'@ QY??9/+993310!!#B:6:UR9@   PY PY?+3?3?+9333310! 4746324&#">|WP5* ڸ AAj$@ //99//9933105%5%j))J@/9/10533U{s/2/9/10 '53WmdVm_/39/10!5!%53$_ya_ /310!53!}hv @  /9/39310!#!53h[c Uhv @  /9/39310 #5!3!h]U"@ //9/993310#353Si8٘$@ //39/933310#3#58i4, @  //9933310#3#58i4,i8  /32210##5##!8}}Oc8c /23310)335338h}}cWt@ /^]9103#'⪕W㾾~:@  /3/39333105353k^dj@  /3/39933105!5!dH֔dY?9310#535Q3ndP?9310#535Q3evV@, SY PY PY?3?3+3?+?+?9933333333310##5354632&#"3533iK4-#E>ӆIz F\ai:wH@$  PY PY?3?3+3?+?99333333310##5354632&#"33iK4-#E>ӇIz F\aI4wN4@   Y@ HY /]+/++993910!"'53254#"7329!1%+>bQM`W*'//99//10##*TTT'88W'  /2/21053#5!#3WM6MMMW'//10#TxW*'//10#'*T'0}W' //3103!*'O&f& J  ??3]210#"&533265JZNM[㑬M]`J<d&' #)B B)7oPF'=Z'h,@  AY7?+3999310!5!3!'3T3F&- $%+53F&3F&'P*@_****{*T**$%+5]]]]5]53F&'@_{T]]]]5]5B&B&B&9`#0##]]5R& ]5?-&LO$/$$]]5)7& ]5o& ]5f& ]5y& ]5& $$]5Ff& @/]]]]]5'&   ]5P& ]5F&@ ]5]57& @ 0"""d""]5]]5Hy&  ]53&  ""]5X&5q&- &H@ /$]]5]5{H&Td0]]5'& ]53&@_{T]]]]5]5=& ]5fF& R+&P+&q+&BPJ@ A : 996??3?/?93333393310#33673#VÖ 32`F[q> ܺw).2}5  /31032673#"&'aEmzNX*4Cfq5" !%)/AOW_jv@ qe*`kU]]FMJPBX?::<3XPFk*e + x"..+''+&&#++w( ..+nhhG5#53H,(u-1XWk/0V. %@  Y/+2323310 33273T @|E ,@ YP`?]q+993310#65#53E,(u^XWu/dZK 7@"   Y_oP  ?   /]q]q+99331046733#,(u^X%Wu/dZj&@/?_/]]9910%53H&@/?_/]]9910573H 4@  /?_/]3]99993310#'##573ih 0@ /?_/]]9993310#'53373hi-Z$@ Y/3+399331053!53ӥI@*  Y    /   @Y/2+_^]]q+3333310".#"#>323273*TNG76 [ 0Q?,TNEd\d%-%>9fi=%-%wx  -@  /?_/]2]29105733573  &@  /]2323310"&'3326734um[[kuo5<=4rjCjCjCHtHtHt+ /99104&#"'632#5>3*HFZjQ[pE0"c;U 2x+ /99104&#"'632#5>3*HFZjQ[pE0"c;U 2xX + /99104&#"'632#5>b3*HFZjQ[pE0"c;U 2xwu/1053ɬHtHtjCjC++u ?u |u u Zu m!u ^8u u~u u z.u kfu WRu #u :u +<&@ ??931033&++ %@  @ H o/r2232/+]31053!53%!5!%++ U@  k@!H0@Pp/]]]q+q_qr/r3/99//3103#553!53>+ ָ3+ [@   k  @!H0@Pp/]]]q+q_qr2//r399//39103#'5353!53ћ+ a޸++ S@  k  @!H0@Pp/]]]q+q_qr/r399//310#%5353!53h~ }+'@_@ HP/q22/+]q310537!5!W%?+7@$ 0@ o@H/+]3q/339/q3310!5!"'&#"#>3232673%3TU$--[ +L?7SS"0+\ *K&%#(RH(%&&%QJ' '@ ??39/?993310!#!5!3e*\* '@ ??39/?993310!#!5!3e*$E '@ ??39/?993310!#!5!3o ZZ#@ ??39/?99310!#!5!3o DM%@ ??9/3?399310!# 7 3f\>Ha4R '@ ??9/3?993310!#!7!3bG4oaRM'@ ??9/3?993310!#73_J^rM '@ ??9/3?993310!#5 73fS܈kh/iF$@ ??3/9/99310!# 73pZzfjFp'@ ??9/3?993310!#73p^ZHd(5%@ ??9/3?399310!# 7 3RkGHyN!5 1@ ??9/933?993310!# 7 3Rka.K- O &@ ??39/3993310!#!7!3xtdH^- &@ ??39/3993310!# 73`vcFFH @??39/99310!#73wp=Dg-p&@ ??39/3993310!#73pEsHVH!$%@ ??9/3?399310!# 7 3=|GHY2#% 0@ ??39/933993310!# 7 534~X4(5f% 0@ ??39/933993310!# 7 3C{sVH2}q' &@ ??39/3993310!#!7!3cy Q2X/@  ?3?399310!# 73HԈG7%p&@ ??39/3993310!#573p={H\2#"@ ?3?39999310!# 7 36}MH)Q0) *@ ?3?399//993310!# 7 530~YAuO/l6 *@ ?3?399//993310!# 7 3ON,qS-m6 *@ ?3?399//993310!# 7%3O~t8S-{0@ ??39310)733+NS.)p @??39/99310!#73pA>S.)O"@ ??39/9310!#!'!ataoL 0@ ??3399//393310!# ' 3[H5fy4L .@ ??3399//393310!# ' 3UH)hy?L ,@ ??3399//93310!#5' 3SHhy-^(@ ??3399//9310!#' 3Q6fy=Lp @??39/99310!#'3p^iy"@ ??39/399310!#!5!3pT; .@ ??99//33993310!#!5!3a.izT *@ ??99//3993310!#!5!35$&@ ??99//399310!#!5!3?P(@ ??399//39310!# 7 3h`axbVL 6@ ??99//93393310!# 7 3e`;H`GF (@ ??99//3993310!#!7!3fb*]v\^L(@ ??99//3993310!#73^'c{L"@ ??99//99310!# 73e[؈scSc[Lp(@ ??99//3993310!#73pd]?de[/(@ ??399//39310!# 7 3Gu7TaF?9 6@ ??99//93393310!# 7 53Rv8HqGG? 4@ ??99//93393310!# 7 3Nw]sX=U8H? *@ ??99//393310!#!7!3mwo V=2? @ ?3?9/99310!# 73\w߈5:=?p&@ ??99//993310!#73pWw2-B=+6&@ ?3?9/999310!# 7 3O}4H) 0q5 .@ ?3?9/99393310!# 7 53N}<Au 1[l6 .@ ?3?9/99393310!# 7 3ON,q -+m6 .@ ?33?9/9393310!# 7%3O~t8 -6"@ ?3?9/9310)7330O~ -Q5p @??9/999310!#73pM4 -zL"@ ??39/9310!#!'!owKzL 0@ ??3399//393310!# ' 3oH Kz4L 0@ ??3399//393310!# ' 3oH)S@Kz?L .@ ??3399//393310!#5 ' 3oHu^Kz-L&@ ??3399//99310!# ' 3o6RjKz=hp @??39/99310!#'3po~32326733#53TU$--[ +L?7SS"0+\ *K&%#(RH(%&&%QJ'h ?+v @ H@6H @P``p@P/]]]qqqqr3+qq2/39/+39910#5##5"'&#"#>3232673wwX3TU$--[ +L?7SS"0+\ *K+&%#(RH(%&&%QJ'YX @ /]99//10#5353 0K+   @ H/+39910#53#'53373D'hi++ 3@#  P`p@Pp/]q3/9/9310#5!#5!5!+=%+: 2@    PY ??9/3+393333310333###mrrmi/Ve*&`'^6@&0/0O00000000(&(('%+555+5/]]q55Ve*&`'^6@&;/;O;;;;;;;;(&(('%+555+5/]]q55Ve*&`'^6@&;/;O;;;;;;;;(&(('%+555+5/]]q55Ve*&`'^6@&;/;O;;;;;;;;(&(('%+555+5/]]q55Ve*&`'^0@ /E?EOEEEEE''&**2%+555+5/]]55Ve*&`'^0@ /7?7O7777788&;;C%+555+5/]]55Ve*&`'^0@ /7?7O7777788&;;C%+555+5/]]55Ve*&`'^0@ /7?7O7777788&;;C%+555+5/]]55*&h&^8@'/O & %+555+5/]]q55$*&h&^8@'/O & %+555+5/]]q55*&h&^8@'/O & %+555+5/]]q553*&h&^8@'/O & %+555+5/]]q55 *&h'^0@ /?O&&%+555+5/]]55*&h'^0@ /?O&&%+555+5/]]55 *&h'^0@ /?O&&%+555+5/]]55*&h'^0@ /?O&&%+555+5/]]55*&t'^8@'*/*O********& %+555+5/]]q55*&t'^8@'&/&O&&&&&&&&((&))* %+555+5/]]q55*&t'^8@'&/&O&&&&&&&&((&))* %+555+5/]]q55*&t'^8@'&/&O&&&&&&&&((&))* %+555+5/]]q55*&t'^0@ /&?&O&&&&&''&**2%+555+5/]]55*&t'^0@ /&?&O&&&&&''&**2%+555+5/]]55*&t'^0@ /&?&O&&&&&''&**2%+555+5/]]55*&t'^0@ /&?&O&&&&&''&**2%+555+5/]]55+&h&i' X@+;k{ +;[;{/o/?_?_o  _   0 @  @ P ` p & %+5555+qrr55/]qr_]5/]q]qr5+&h&i' @+;k{ +;[;{/o/?_?_o  _   0 @  @ P ` p & %+5555+qrr55/]qr_]5/]q]qr5 +&h&i' X@o""""?""""?"O"""""""/o?/?_ 0@ @P`p &% %+55+55+qrr55/]qr5/]q]qr5 +&h&i' @o""""?""""?"O"""""""/o?/?_ 0@ @P`p &% %+55+55+qrr55/]qr5/]q]qr5+&t''i y@+$;$k${$ $$+$;$[$$$;${$$$$$/o/?_?_o _ 0@ @P`p &%+5555+qrr55/]qr_]5/]q]qr5+&t''i @+$;$k${$ $$+$;$[$$$;${$$$$$/o/?_?_o _ 0@ @P`p &%+5555+qrr55/]qr_]5/]q]qr5+&t'i' @{o....?....?.O.......!/!o!!!!!!?!!!!/!?!!!!_ 0@ @P`p &%+5555+qrr55/]qr5/]q]qr5+&t'i'  @{o....?....?.O.......!/!o!!!!!!?!!!!/!?!!!!_ 0@ @P`p &%+5555+qrr55/]qr5/]q]qr5h+&L ;$@   & Y %+5+]]5W]"9@  $# _Y_Y?+?9?+9333310"&'732654&#"#336$32_;ZjjİwyHWJJsnsheD=atW ;@ _Y?+?39999233310#"'532>=#3&53 }zRA4(-1  AS[aXX`]%I@$ ##'&_Y _Y?2/+??+3/99933333310"$&'33254&#"#336$32 ]İwyHyJhe=Mwj2j '@ Y ) Y/?/]q+/_^]+10#"&546324&#"322LSVMNR¾X}c+@//]qr/]q9107573}Yxy}$jA@%  Y)Y/]qr+3/_^]+3/9910%5>7>54&#"'>32!$zd\EF=:S yTQzU}CF|F@S,6865XkpdEv6QE$nj0j#_@:!Y@ H/Y) YP`/?/]q3/]+/_^]+3/_^]9/++910#"&'732654+732654#"'>320HR?3WM yKgzm^p@;jk/1eb[np^!}Ac A@)Y @ H//]qr/]q9/+933+310#5!5333tfq$ T*q5j1[d@ Y@2 HY?_  YP`/?/]q3/]+/_^]q+9/++3/910# '732654&#"#!!>3211O>LWIP?Q ur#T?z};5SGCR(u#i)j"GY@" H Y )  Y/?O/]q+/_^]3/+9/+9+10#"&54632&#">324&#"326)7^N[`HvFQCHIFENow˙L{}"1{KCJDENN|#\ /@  Y/  O  /]q/]q+310#47!5!#}EFح#oj0j"-E@( !&!&Y!@ H!!Y)+Y/?/]q+/_^]+9/++9910#"&54675.546324#"324&#"3260`PKO~QLQaEEQKIPNJBiopgHf ^>VljY=^ bii69:;@7@i*j$F@*Y @ H Y  / ?    "Y/r+/_^]q3/+9/+9+104632#"&'73265#"&732654&#"؜eN+N[`HvLKCHIFENdwSM)'x}"1}R@LFEJJ+@ @  /329/]103#5#'##538`tih+ C+@ @  /329/]10#'53#'##53`~ihy +#@ @/329/]]99104#"'632##52#'##53T;3(:CC6=Kih#@`,8N?+ /@   @ H  /3]22/33+q2210"'&#"#>3232673#573#3TU$--[ +L?7SS"0+\ *KЛi&%#(RH(%&&%QJ'pC 9+D@( P` @ P `  @  H /+]qr29/r9]103#5"&'332673#݂YkjTThk+ tD78Cx9+D@( P` @ P `  @  H /+]qr29/r9]10#'53"&'332673\ kjTThk tD78Cx9+ X@&@H @P` HH H/+++qr29+9/99910"&'3326734#"'632+52kjTThkc;3(:CJI#KtD78Cx#@`047?+ $K@  P`p@*/Ho@/2/]]+]qr339/33/3310"&'332737".#"#>3232673fUU#DA=Q[ *K@$F@;0+\ *Lj]SSdc#'##53YL=5FYBI[*5ih,Pp0E &^F !5@@H@ H@ @ H /322/+33++22103#'##5"'&#"#>3232673fhi3TU$--[ +L?7SS"0+\ *Kh&%#(RH(%&&%QJ'M /222/10"&'33273573uuIM  /222/10"&'33273%53uuIM+ @  /222/29910"&'332734#"'632#5>uuR]HFZjQ[pE07c;U (nM #)@@ H@ /2]22/33+2210"&'33273"'&#"#>3232673uu 3TU$--[ +L?7SS"0+\ *K|&%#(RH(%&&%QJ'6+/9910'53E6%!6+/9910573E6!%k&&k&'&J'&+P&P&P&FB&9`#0##]]5&i #/;?3@-3'99? !!?>''>>>/3/3/3/2/93/99014632#"&74632#"&4632#"&%4632#"&4632#"&3&. ".." .. ".." .r- #--# -2. ".." .. 0/!",n` .. ".." .. "..".." 00".." ..".0 0..o!@ /3/33/2/99015!%4632#"&4632#"&3G"-# // #-- #--# -nmm@".." .. 00 "...o\d#4@ #"@ "H"/3/+933/2/99015#5!#%4632#"&4632#"&3nGj-# // #-- #//# -nrmmr".." .. 00 "...oV H$7<8ADKSTZh$$7h$9h$:$@>Ah>Dh>H>Kh>O>U>X>]h>^>`F>fh>h>ih>kh>nF>rF>uF>yb>{F?T?ZAAHAOAShAThAUAZhAbAlAvAhCCC@CADCDDCKDChCyXDDHDODSDThDZhHAHDHKHTHZJHJOJUJ[J`JcJeJgJmJnJrJuJxJ{J}KKHKOKShKThKZhOAODOKOTOZQQQQAhQDhQKhRoRsSSSSSS@SAhSDhSHSKhSOSUSXS[S\S_NS`SbNSdSfjShSkjSlSnSrStPSuSvSwjSySzNS{S|NTTTFTTTT@TAhTDhTHTKhTOTUTXT]hT^T`FTbTfhThTihTkhTnFTrFTuFTyyT{FUAUTUZW[W`WcWgWnWrWuWxW{W}XTXZZZ@ZAhZDhZHZKhZOZUZXZ]hZ^Z`FZfhZhZihZkhZnFZrFZuFZybZ{Fcjcocscve[we]e`webecefegeheielenweoerweseuwexwe{we}wgji[i`icieigiminiqiriuixi{i}j[j`jcjmjnjqjrjtjujxj{j|j}m[m`mcmemmmnmqmrmum{njnonsnvo[o`oeonoqorouoxo}pjpopss[s`scsesnsqsrsusxs}ujuousuvv[v`vcvevnvqvrvuvxv{v}xjxoxsxv{j{o{s{v}j}o}s}vlw{w`wD-``-wlw{wwwwwwwwD---}}{ww`-l{`l{w`wwwww--w3``---D33{`w 3 3>>>>>l`>{`>V```nW(Hz!  i  . 5     8 4P    + (   8F \ j * 4 Digitized data copyright (c) 2010 Google Corporation. Copyright (c) 2012 Red Hat, Inc.Digitized data copyright (c) 2010 Google Corporation. Copyright (c) 2012 Red Hat, Inc.Liberation SansLiberation SansRegularRegularAscender - Liberation SansAscender - Liberation SansLiberation SansLiberation SansVersion 2.00.0Version 2.00.0LiberationSansLiberationSansLiberation is a trademark of Red Hat, Inc. registered in U.S. Patent and Trademark Office and certain other jurisdictions.Liberation is a trademark of Red Hat, Inc. registered in U.S. Patent and Trademark Office and certain other jurisdictions.Ascender CorporationAscender CorporationSteve MattesonSteve MattesonBased on Arimo, which was designed by Steve Matteson as an innovative, refreshing sans serif design that is metrically compatible with Arial!". Arimo offers improved on-screen readability characteristics and the pan-European WGL character set and solves the needs of developers looking for width-compatible fonts to address document portability across platforms.Based on Arimo, which was designed by Steve Matteson as an innovative, refreshing sans serif design that is metrically compatible with Arial. Arimo offers improved on-screen readability characteristics and the pan-European WGL character set and solves the needs of developers looking for width-compatible fonts to address document portability across platforms.http://www.ascendercorp.com/http://www.ascendercorp.com/http://www.ascendercorp.com/typedesigners.htmlhttp://www.ascendercorp.com/typedesigners.htmlLicensed under the SIL Open Font License, Version 1.1Licensed under the SIL Open Font License, Version 1.1http://scripts.sil.org/OFLhttp://scripts.sil.org/OFL'   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghjikmlnoqprsutvwxzy{}|~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~                           ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ 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 [ \ ] ^ _ ` 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 { | } ~                      overscoremu1middotAmacronamacronAbreveabreveAogonekaogonek Ccircumflex ccircumflex Cdotaccent cdotaccentDcarondcaronDcroatEmacronemacronEbreveebreve Edotaccent edotaccentEogonekeogonekEcaronecaron Gcircumflex gcircumflex Gdotaccent gdotaccent Gcommaaccent gcommaaccent Hcircumflex hcircumflexHbarhbarItildeitildeImacronimacronIbreveibreveIogonekiogonekIJij Jcircumflex jcircumflex Kcommaaccent kcommaaccent kgreenlandicLacutelacute Lcommaaccent lcommaaccentLcaronlcaronLdotldotNacutenacute Ncommaaccent ncommaaccentNcaronncaron napostropheEngengOmacronomacronObreveobreve Ohungarumlaut ohungarumlautRacuteracute Rcommaaccent rcommaaccentRcaronrcaronSacutesacute Scircumflex scircumflex Tcommaaccent tcommaaccentTcarontcaronTbartbarUtildeutildeUmacronumacronUbreveubreveUringuring Uhungarumlaut uhungarumlautUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexZacutezacute Zdotaccent zdotaccentlongsuni0180uni0181uni0182uni0183uni0184uni0185uni0186uni0187uni0188uni0189uni018Auni018Buni018Cuni018Duni018Euni018Funi0190uni0191uni0193uni0194uni0195uni0196uni0197uni0198uni0199uni019Auni019Buni019Cuni019Duni019Euni019FOhornohornuni01A2uni01A3uni01A4uni01A5uni01A6uni01A7uni01A8uni01A9uni01AAuni01ABuni01ACuni01ADuni01AEUhornuhornuni01B1uni01B2uni01B3uni01B4uni01B5uni01B6uni01B7uni01B8uni01B9uni01BAuni01BBuni01BCuni01BDuni01BEuni01BFuni01C0uni01C1uni01C2uni01C3uni01C4uni01C5uni01C6uni01C7uni01C8uni01C9uni01CAuni01CBuni01CCuni01CDuni01CEuni01CFuni01D0uni01D1uni01D2uni01D3uni01D4uni01D5uni01D6uni01D7uni01D8uni01D9uni01DAuni01DBuni01DCuni01DDuni01DEuni01DFuni01E0uni01E1uni01E2uni01E3uni01E4uni01E5uni01E6uni01E7uni01E8uni01E9uni01EAuni01EBuni01ECuni01EDuni01EEuni01EFuni01F0uni01F1uni01F2uni01F3uni01F4uni01F5uni01F6uni01F7uni01F8uni01F9 Aringacute aringacuteAEacuteaeacute Oslashacute oslashacuteuni0200uni0201uni0202uni0203uni0204uni0205uni0206uni0207uni0208uni0209uni020Auni020Buni020Cuni020Duni020Euni020Funi0210uni0211uni0212uni0213uni0214uni0215uni0216uni0217 Scommaaccent scommaaccentuni021Auni021Buni021Cuni021Duni021Euni021Funi0220uni0221uni0222uni0223uni0224uni0225uni0226uni0227uni0228uni0229uni022Auni022Buni022Cuni022Duni022Euni022Funi0230uni0231uni0232uni0233uni0234uni0235uni0236 j.dotlessuni0238uni0239uni023Auni023Buni023Cuni023Duni023Euni023Funi0240uni0241uni0242uni0243uni0244uni0245uni0246uni0247uni0248uni0249uni024Auni024Buni024Cuni024Duni024Euni024Funi0250uni0251uni0252uni0253uni0254uni0255uni0256uni0257uni0258uni0259uni025Auni025Buni025Cuni025Duni025Euni025Funi0260uni0261uni0262uni0263uni0264uni0265uni0266uni0267uni0268uni0269uni026Auni026Buni026Cuni026Duni026Euni026Funi0270uni0271uni0272uni0273uni0274uni0275uni0276uni0277uni0278uni0279uni027Auni027Buni027Cuni027Duni027Euni027Funi0280uni0281uni0282uni0283uni0284uni0285uni0286uni0287uni0288uni0289uni028Auni028Buni028Cuni028Duni028Euni028Funi0290uni0291uni0292uni0293uni0294uni0295uni0296uni0297uni0298uni0299uni029Auni029Buni029Cuni029Duni029Euni029Funi02A0uni02A1uni02A2uni02A3uni02A4uni02A5uni02A6uni02A7uni02A8uni02A9uni02AAuni02ABuni02ACuni02ADuni02AEuni02AFuni02B0uni02B1uni02B2uni02B3uni02B4uni02B5uni02B6uni02B7uni02B8uni02B9uni02BAuni02BBuni02BCuni02BDuni02BEuni02BFuni02C0uni02C1uni02C2uni02C3uni02C4uni02C5uni02C8uni02CAuni02CBuni02CCuni02CDuni02CEuni02CFuni02D0uni02D1uni02D2uni02D3uni02D4uni02D5uni02D6uni02D7uni02DEuni02DFuni02E0uni02E1uni02E2uni02E3uni02E4uni02E5uni02E6uni02E7uni02E8uni02E9uni02EAuni02EBuni02ECuni02EDuni02EEuni02EFuni02F0uni02F1uni02F2uni02F3uni02F4uni02F5uni02F6uni02F7uni02F8uni02F9uni02FAuni02FBuni02FCuni02FDuni02FEuni02FF gravecomb acutecombuni0302 tildecombuni0304uni0305uni0306uni0307uni0308 hookabovecombuni030Auni030Buni030Cuni030Duni030Euni030Funi0310uni0311uni0312uni0313uni0314uni0315uni0316uni0317uni0318uni0319uni031Auni031Buni031Cuni031Duni031Euni031Funi0320uni0321uni0322 dotbelowcombuni0324uni0325uni0326uni0327uni0328uni0329uni032Auni032Buni032Cuni032Duni032Euni032Funi0330uni0331uni0332uni0333uni0334uni0335uni0336uni0337uni0338uni0339uni033Auni033Buni033Cuni033Duni033Euni033Funi0340uni0341uni0342uni0343uni0344uni0345uni0346uni0347uni0348uni0349uni034Auni034Buni034Cuni034Duni034Euni034Funi0350uni0351uni0352uni0353uni0354uni0355uni0356uni0357uni0358uni0359uni035Auni035Buni035Cuni035Duni035Euni035Funi0360uni0361uni0362uni0363uni0364uni0365uni0366uni0367uni0368uni0369uni036Auni036Buni036Cuni036Duni036Euni036Funi0374uni0375uni037Auni037Buni037Cuni037Dtonos dieresistonos Alphatonos anoteleia EpsilontonosEtatonos Iotatonos Omicrontonos Upsilontonos OmegatonosiotadieresistonosAlphaBetaGammaEpsilonZetaEtaThetaIotaKappaLambdaMuNuXiOmicronPiRhoSigmaTauUpsilonPhiChiPsi IotadieresisUpsilondieresis alphatonos epsilontonosetatonos iotatonosupsilondieresistonosalphabetagammadeltaepsilonzetaetathetaiotakappalambdanuxiomicronrhosigma1sigmatauupsilonphichipsiomega iotadieresisupsilondieresis omicrontonos upsilontonos omegatonosuni03D0uni03D1uni03D2uni03D3uni03D4uni03D5uni03D6uni03D7uni03D8uni03D9uni03DAuni03DBuni03DCuni03DDuni03DEuni03DFuni03E0uni03E1uni03E2uni03E3uni03E4uni03E5uni03E6uni03E7uni03E8uni03E9uni03EAuni03EBuni03ECuni03EDuni03EEuni03EFuni03F0uni03F1uni03F2uni03F3uni03F4uni03F5uni03F6uni03F7uni03F8uni03F9uni03FAuni03FBuni03FCuni03FDuni03FEuni03FFuni0400uni0401uni0402uni0403uni0404uni0405uni0406uni0407uni0408uni0409uni040Auni040Buni040Cuni040Duni040Euni040Funi0410uni0411uni0412uni0413uni0414uni0415uni0416uni0417uni0418uni0419uni041Auni041Buni041Cuni041Duni041Euni041Funi0420uni0421uni0422uni0423uni0424uni0425uni0426uni0427uni0428uni0429uni042Auni042Buni042Cuni042Duni042Euni042Funi0430uni0431uni0432uni0433uni0434uni0435uni0436uni0437uni0438uni0439uni043Auni043Buni043Cuni043Duni043Euni043Funi0440uni0441uni0442uni0443uni0444uni0445uni0446uni0447uni0448uni0449uni044Auni044Buni044Cuni044Duni044Euni044Funi0450uni0451uni0452uni0453uni0454uni0455uni0456uni0457uni0458uni0459uni045Auni045Buni045Cuni045Duni045Euni045Funi0460uni0461uni0462uni0463uni0464uni0465uni0466uni0467uni0468uni0469uni046Auni046Buni046Cuni046Duni046Euni046Funi0470uni0471uni0472uni0473uni0474uni0475uni0476uni0477uni0478uni0479uni047Auni047Buni047Cuni047Duni047Euni047Funi0480uni0481uni0482uni0483uni0484uni0485uni0486uni0487uni0488uni0489uni048Auni048Buni048Cuni048Duni048Euni048Funi0490uni0491uni0492uni0493uni0494uni0495uni0496uni0497uni0498uni0499uni049Auni049Buni049Cuni049Duni049Euni049Funi04A0uni04A1uni04A2uni04A3uni04A4uni04A5uni04A6uni04A7uni04A8uni04A9uni04AAuni04ABuni04ACuni04ADuni04AEuni04AFuni04B0uni04B1uni04B2uni04B3uni04B4uni04B5uni04B6uni04B7uni04B8uni04B9uni04BAuni04BBuni04BCuni04BDuni04BEuni04BFuni04C0uni04C1uni04C2uni04C3uni04C4uni04C5uni04C6uni04C7uni04C8uni04C9uni04CAuni04CBuni04CCuni04CDuni04CEuni04CFuni04D0uni04D1uni04D2uni04D3uni04D4uni04D5uni04D6uni04D7uni04DAuni04DBuni04DCuni04DDuni04DEuni04DFuni04E0uni04E1uni04E2uni04E3uni04E4uni04E5uni04E6uni04E7uni04E8uni04E9uni04EAuni04EBuni04ECuni04EDuni04EEuni04EFuni04F0uni04F1uni04F2uni04F3uni04F4uni04F5uni04F6uni04F7uni04F8uni04F9uni04FAuni04FBuni04FCuni04FDuni04FEuni04FFuni0500uni0501uni0502uni0503uni0504uni0505uni0506uni0507uni0508uni0509uni050Auni050Buni050Cuni050Duni050Euni050Funi0510uni0511uni0512uni0513uni051Auni051Buni051Cuni051Duni0591uni0592uni0593uni0594uni0595uni0596uni0597uni0598uni0599uni059Auni059Buni059Cuni059Duni059Euni059Funi05A0uni05A1uni05A2uni05A3uni05A4uni05A5uni05A6uni05A7uni05A8uni05A9uni05AAuni05ABuni05ACuni05ADuni05AEuni05AFsheva hatafsegol hatafpatah hatafqamatshiriqtseresegolpatahqamatsholamuni05BAqubutsdageshmetegmaqafrafepaseqshindotsindotsofpasuq upper_dotlowerdotuni05C6 qamatsqatanalefbetgimeldalethevavzayinhettetyodfinalkafkaflamedfinalmemmemfinalnunnunsamekhayinfinalpepe finaltsaditsadiqofreshshintavvavvavvavyodyodyodgeresh gershayimuni1D00uni1D01uni1D02uni1D03uni1D04uni1D05uni1D06uni1D07uni1D08uni1D09uni1D0Auni1D0Buni1D0Cuni1D0Duni1D0Euni1D0Funi1D10uni1D11uni1D12uni1D13uni1D14uni1D15uni1D16uni1D17uni1D18uni1D19uni1D1Auni1D1Buni1D1Cuni1D1Duni1D1Euni1D1Funi1D20uni1D21uni1D22uni1D23uni1D24uni1D25uni1D26uni1D27uni1D28uni1D29uni1D2Auni1D2Buni1D2Cuni1D2Duni1D2Euni1D2Funi1D30uni1D31uni1D32uni1D33uni1D34uni1D35uni1D36uni1D37uni1D38uni1D39uni1D3Auni1D3Buni1D3Cuni1D3Duni1D3Euni1D3Funi1D40uni1D41uni1D42uni1D43uni1D44uni1D45uni1D46uni1D47uni1D48uni1D49uni1D4Auni1D4Buni1D4Cuni1D4Duni1D4Euni1D4Funi1D50uni1D51uni1D52uni1D53uni1D54uni1D55uni1D56uni1D57uni1D58uni1D59uni1D5Auni1D5Buni1D5Cuni1D5Duni1D5Euni1D5Funi1D60uni1D61uni1D62uni1D63uni1D64uni1D65uni1D66uni1D67uni1D68uni1D69uni1D6Auni1D6Buni1D6Cuni1D6Duni1D6Euni1D6Funi1D70uni1D71uni1D72uni1D73uni1D74uni1D75uni1D76uni1D77uni1D78uni1D79uni1D7Auni1D7Buni1D7Cuni1D7Duni1D7Euni1D7Funi1D80uni1D81uni1D82uni1D83uni1D84uni1D85uni1D86uni1D87uni1D88uni1D89uni1D8Auni1D8Buni1D8Cuni1D8Duni1D8Euni1D8Funi1D90uni1D91uni1D92uni1D93uni1D94uni1D95uni1D96uni1D97uni1D98uni1D99uni1D9Auni1D9Buni1D9Cuni1D9Duni1D9Euni1D9Funi1DA0uni1DA1uni1DA2uni1DA3uni1DA4uni1DA5uni1DA6uni1DA7uni1DA8uni1DA9uni1DAAuni1DABuni1DACuni1DADuni1DAEuni1DAFuni1DB0uni1DB1uni1DB2uni1DB3uni1DB4uni1DB5uni1DB6uni1DB7uni1DB8uni1DB9uni1DBAuni1DBBuni1DBCuni1DBDuni1DBEuni1DBFuni1DC0uni1DC1uni1DC2uni1DC3uni1DC4uni1DC5uni1DC6uni1DC7uni1DC8uni1DC9uni1DCAuni1DFEuni1DFFuni1E00uni1E01uni1E02uni1E03uni1E04uni1E05uni1E06uni1E07uni1E08uni1E09uni1E0Auni1E0Buni1E0Cuni1E0Duni1E0Euni1E0Funi1E10uni1E11uni1E12uni1E13uni1E14uni1E15uni1E16uni1E17uni1E18uni1E19uni1E1Auni1E1Buni1E1Cuni1E1Duni1E1Euni1E1Funi1E20uni1E21uni1E22uni1E23uni1E24uni1E25uni1E26uni1E27uni1E28uni1E29uni1E2Auni1E2Buni1E2Cuni1E2Duni1E2Euni1E2Funi1E30uni1E31uni1E32uni1E33uni1E34uni1E35uni1E36uni1E37uni1E38uni1E39uni1E3Auni1E3Buni1E3Cuni1E3Duni1E3Euni1E3Funi1E40uni1E41uni1E42uni1E43uni1E44uni1E45uni1E46uni1E47uni1E48uni1E49uni1E4Auni1E4Buni1E4Cuni1E4Duni1E4Euni1E4Funi1E50uni1E51uni1E52uni1E53uni1E54uni1E55uni1E56uni1E57uni1E58uni1E59uni1E5Auni1E5Buni1E5Cuni1E5Duni1E5Euni1E5Funi1E60uni1E61uni1E62uni1E63uni1E64uni1E65uni1E66uni1E67uni1E68uni1E69uni1E6Auni1E6Buni1E6Cuni1E6Duni1E6Euni1E6Funi1E70uni1E71uni1E72uni1E73uni1E74uni1E75uni1E76uni1E77uni1E78uni1E79uni1E7Auni1E7Buni1E7Cuni1E7Duni1E7Euni1E7FWgravewgraveWacutewacute Wdieresis wdieresisuni1E86uni1E87uni1E88uni1E89uni1E8Auni1E8Buni1E8Cuni1E8Duni1E8Euni1E8Funi1E90uni1E91uni1E92uni1E93uni1E94uni1E95uni1E96uni1E97uni1E98uni1E99uni1E9Auni1E9Buni1E9E Adotbelow adotbelow Ahookabove ahookaboveAcircumflexacuteacircumflexacuteAcircumflexgraveacircumflexgraveAcircumflexhookaboveacircumflexhookaboveAcircumflextildeacircumflextildeAcircumflexdotbelowacircumflexdotbelow Abreveacute abreveacute Abrevegrave abrevegraveAbrevehookaboveabrevehookabove Abrevetilde abrevetildeAbrevedotbelowabrevedotbelow Edotbelow edotbelow Ehookabove ehookaboveEtildeetildeEcircumflexacuteecircumflexacuteEcircumflexgraveecircumflexgraveEcircumflexhookaboveecircumflexhookaboveEcircumflextildeecircumflextildeEcircumflexdotbelowecircumflexdotbelow Ihookabove ihookabove Idotbelow idotbelow Odotbelow odotbelow Ohookabove ohookaboveOcircumflexacuteocircumflexacuteOcircumflexgraveocircumflexgraveOcircumflexhookaboveocircumflexhookaboveOcircumflextildeocircumflextildeOcircumflexdotbelowocircumflexdotbelow Ohornacute ohornacute Ohorngrave ohorngraveOhornhookaboveohornhookabove Ohorntilde ohorntilde Ohorndotbelow ohorndotbelow Udotbelow udotbelow Uhookabove uhookabove Uhornacute uhornacute Uhorngrave uhorngraveUhornhookaboveuhornhookabove Uhorntilde uhorntilde Uhorndotbelow uhorndotbelowYgraveygrave Ydotbelow ydotbelow Yhookabove yhookaboveYtildeytildeuni1F00uni1F01uni1F02uni1F03uni1F04uni1F05uni1F06uni1F07uni1F08uni1F09uni1F0Auni1F0Buni1F0Cuni1F0Duni1F0Euni1F0Funi1F10uni1F11uni1F12uni1F13uni1F14uni1F15uni1F18uni1F19uni1F1Auni1F1Buni1F1Cuni1F1Duni1F20uni1F21uni1F22uni1F23uni1F24uni1F25uni1F26uni1F27uni1F28uni1F29uni1F2Auni1F2Buni1F2Cuni1F2Duni1F2Euni1F2Funi1F30uni1F31uni1F32uni1F33uni1F34uni1F35uni1F36uni1F37uni1F38uni1F39uni1F3Auni1F3Buni1F3Cuni1F3Duni1F3Euni1F3Funi1F40uni1F41uni1F42uni1F43uni1F44uni1F45uni1F48uni1F49uni1F4Auni1F4Buni1F4Cuni1F4Duni1F50uni1F51uni1F52uni1F53uni1F54uni1F55uni1F56uni1F57uni1F59uni1F5Buni1F5Duni1F5Funi1F60uni1F61uni1F62uni1F63uni1F64uni1F65uni1F66uni1F67uni1F68uni1F69uni1F6Auni1F6Buni1F6Cuni1F6Duni1F6Euni1F6Funi1F70uni1F71uni1F72uni1F73uni1F74uni1F75uni1F76uni1F77uni1F78uni1F79uni1F7Auni1F7Buni1F7Cuni1F7Duni1F80uni1F81uni1F82uni1F83uni1F84uni1F85uni1F86uni1F87uni1F88uni1F89uni1F8Auni1F8Buni1F8Cuni1F8Duni1F8Euni1F8Funi1F90uni1F91uni1F92uni1F93uni1F94uni1F95uni1F96uni1F97uni1F98uni1F99uni1F9Auni1F9Buni1F9Cuni1F9Duni1F9Euni1F9Funi1FA0uni1FA1uni1FA2uni1FA3uni1FA4uni1FA5uni1FA6uni1FA7uni1FA8uni1FA9uni1FAAuni1FABuni1FACuni1FADuni1FAEuni1FAFuni1FB0uni1FB1uni1FB2uni1FB3uni1FB4uni1FB6uni1FB7uni1FB8uni1FB9uni1FBAuni1FBBuni1FBCuni1FBDuni1FBEuni1FBFuni1FC0uni1FC1uni1FC2uni1FC3uni1FC4uni1FC6uni1FC7uni1FC8uni1FC9uni1FCAuni1FCBuni1FCCuni1FCDuni1FCEuni1FCFuni1FD0uni1FD1uni1FD2uni1FD3uni1FD6uni1FD7uni1FD8uni1FD9uni1FDAuni1FDBuni1FDDuni1FDEuni1FDFuni1FE0uni1FE1uni1FE2uni1FE3uni1FE4uni1FE5uni1FE6uni1FE7uni1FE8uni1FE9uni1FEAuni1FEBuni1FECuni1FEDuni1FEEuni1FEFuni1FF2uni1FF3uni1FF4uni1FF6uni1FF7uni1FF8uni1FF9uni1FFAuni1FFBuni1FFCuni1FFDuni1FFEuni2000uni2001uni2002uni2003uni2004uni2005uni2006uni2007uni2008uni2009uni200Auni200Buni200Cuni200Duni200Euni200Funi2012uni2015 underscoredbl quotereverseduni201Funi202Auni202Buni202Cuni202Duni202Eminuteseconduni2034 exclamdbl radicalexuni205Euni206Auni206Buni206Cuni206Duni206Euni206F foursuperior fivesuperior sevensuperior eightsuperior nsuperioruni2090uni2091uni2092uni2093uni2094uni20A0uni20A1uni20A2lirauni20A5uni20A6pesetauni20A8uni20A9sheqeldongEurouni20ADuni20AEuni20AFuni20B0uni20B1uni20B2uni20B3uni20B4uni20B5uni20F0uni2105uni2113uni2116uni2117Ohm estimateduni214Duni214Eonethird twothirds oneeighth threeeighths fiveeighths seveneighthsuni2184 arrowleftarrowup arrowright arrowdown arrowboth arrowupdn arrowupdnbseuni2206 orthogonal intersection equivalencehouse revlogicalnot integraltp integralbtuni2500uni2502uni250Cuni2510uni2514uni2518uni251Cuni2524uni252Cuni2534uni253Cuni2550uni2551uni2552uni2553uni2554uni2555uni2556uni2557uni2558uni2559uni255Auni255Buni255Cuni255Duni255Euni255Funi2560uni2561uni2562uni2563uni2564uni2565uni2566uni2567uni2568uni2569uni256Auni256Buni256Cupblockdnblockblocklfblockrtblockltshadeshadedkshade filledboxuni25A1uni25AAuni25AB filledrecttriaguptriagrttriagdntriaglfcircleuni25CCuni25CF invbullet invcircle openbullet smileface invsmilefacesunfemalemalespadeclubheartdiamond musicalnotemusicalnotedbluni266Funi2C60uni2C61uni2C62uni2C63uni2C64uni2C65uni2C66uni2C67uni2C68uni2C69uni2C6Auni2C6Buni2C6Cuni2C6Duni2C71uni2C72uni2C73uni2C74uni2C75uni2C76uni2C77uni2E17uniA717uniA718uniA719uniA71AuniA71BuniA71CuniA71DuniA71EuniA71FuniA720uniA721uniA788uniA789uniA78AuniA78BuniA78CundercommaaccentuniF00AuniF00BuniF00CuniF00DuniF00EuniFB1DuniFB1E yodyod_patahalternativeayinalefwide daletwidehewidekafwide lamedwide finalmemwidereshwidetavwide alt_plussign shinshindot shinsindotshindageshshindotshindageshsindot alefpatah alefqamats alefmapiq betdagesh gimeldagesh daletdageshhedagesh vavdagesh zayindagesh tetdagesh yoddageshfinalkafdagesh kafdagesh lameddagesh memdagesh nundagesh samekhdagesh finalpedageshpedagesh tsadidagesh qofdagesh reshdagesh shindagesh tavdageshvavholambetrafekafrafeperafe aleflameduniFE20uniFE21uniFE22uniFE23uniFFFC commaaccent breve.cyrcaroncommaaccentcommaaccentrotategrave.ucacute.uc circumflex.uccaron.uc dieresis.uctilde.uchungarumlaut.ucbreve.uc grave.alt1 grave.alt2 grave.alt3 acute.alt1 acute.alt2 acute.alt3hookabove.alt1hookabove.alt2hookabove.alt3 tilde.alt1 tilde.alt2 breve.alt1circumflex.alt1 dotbelow.alt1 acute.alt4 acute.alt5 grave.alt4 grave.alt5hookabove.alt4hookabove.alt5 tilde.alt3 tilde.alt4 tilde.alt5 tilde.alt6 tilde.alt7 tilde.alt8 dotbelow.alt2 dotbelow.alt3 dotbelow.alt4 dotbelow.alt5 dotbelow.alt6 tilde.alt9 dotbelow.alt7 dotbelow.alt8 dotbelow.alt9dotbelow.alt10dotbelow.alt11dotbelow.alt12dotbelow.alt13dotbelow.alt14dotbelow.alt15 tilde.alt10 tilde.alt11 tilde.alt12 tilde.alt13 dotlessi.alt1uni03080304.capuni03080301.capuni0308030C.capuni03080300.capuni03070304.capuni03030304.capuni02E502E502E6uni02E502E502E7uni02E502E502E8uni02E502E502E9uni02E502E602E5uni02E502E602E6uni02E502E602E7uni02E502E602E8uni02E502E602E9 uni02E502E6uni02E502E702E5uni02E502E702E6uni02E502E702E7uni02E502E702E8uni02E502E702E9 uni02E502E7uni02E502E802E5uni02E502E802E6uni02E502E802E7uni02E502E802E8uni02E502E802E9 uni02E502E8uni02E502E902E5uni02E502E902E6uni02E502E902E7uni02E502E902E8uni02E502E902E9 uni02E502E9uni02E602E502E5uni02E602E502E6uni02E602E502E7uni02E602E502E8uni02E602E502E9 uni02E602E5uni02E602E602E5uni02E602E602E7uni02E602E602E8uni02E602E602E9uni02E602E702E5uni02E602E702E6uni02E602E702E7uni02E602E702E8uni02E602E702E9 uni02E602E7uni02E602E802E5uni02E602E802E6uni02E602E802E7uni02E602E802E8uni02E602E802E9 uni02E602E8uni02E602E902E5uni02E602E902E6uni02E602E902E7uni02E602E902E8uni02E602E902E9 uni02E602E9uni02E702E502E5uni02E702E502E6uni02E702E502E7uni02E702E502E8uni02E702E502E9 uni02E702E5uni02E702E602E5uni02E702E602E6uni02E702E602E7uni02E702E602E8uni02E702E602E9 uni02E702E6uni02E702E702E5uni02E702E702E6uni02E702E702E8uni02E702E702E9uni02E702E802E5uni02E702E802E6uni02E702E802E7uni02E702E802E8uni02E702E802E9 uni02E702E8uni02E702E902E5uni02E702E902E6uni02E702E902E7uni02E702E902E8uni02E702E902E9 uni02E702E9uni02E802E502E5uni02E802E502E6uni02E802E502E7uni02E802E502E8uni02E802E502E9 uni02E802E5uni02E802E602E5uni02E802E602E6uni02E802E602E7uni02E802E602E8uni02E802E602E9 uni02E802E6uni02E802E702E5uni02E802E702E6uni02E802E702E7uni02E802E702E8uni02E802E702E9 uni02E802E7uni02E802E802E5uni02E802E802E6uni02E802E802E7uni02E802E802E9uni02E802E902E5uni02E802E902E6uni02E802E902E7uni02E802E902E8uni02E802E902E9 uni02E802E9uni02E902E502E5uni02E902E502E6uni02E902E502E7uni02E902E502E8uni02E902E502E9 uni02E902E5uni02E902E602E5uni02E902E602E6uni02E902E602E7uni02E902E602E8uni02E902E602E9 uni02E902E6uni02E902E702E5uni02E902E702E6uni02E902E702E7uni02E902E702E8uni02E902E702E9 uni02E902E7uni02E902E802E5uni02E902E802E6uni02E902E802E7uni02E902E802E8uni02E902E802E9 uni02E902E8uni02E902E902E5uni02E902E902E6uni02E902E902E7uni02E902E902E8cyrillic_otmarkuni03040300.capuni03040301.capuni03030301.capuni03030308.capuni03010307.capuni030C0307.capuni03040308.cap bari.dotlessuni03B1030403130300uni03B1030403130301uni03B1030403140300uni03B1030403140301uni03B1030603130300uni03B1030603130301uni03B1030603140300uni03B1030603140301uni03B9030403130300uni03B9030403130301uni03B9030403140300uni03B9030403140301uni03B9030603130300uni03B9030603130301uni03B9030603140300uni03B9030603140301uni03C5030403130300uni03C5030403130301uni03C5030403140300uni03C5030403140301uni03C5030603130300uni03C5030603130301uni03C5030603140300uni03C5030603140301uni03B9030803040300uni03B9030803040301uni03B9030803060300uni03B9030803060301uni03C5030803040300uni03C5030803040301uni03C5030803060300uni03C5030803060301 dottediacuteEng.alt1Eng.alt2Eng.alt3zero.altone.alttwo.alt three.altfour.altfive.altsix.alt seven.alt eight.altnine.altcircumflexacutecircumflexgravecircumflexhookcircumflextilde breveacute brevegrave brevehook brevetildecircumflexacute.lccircumflexgrave.lccircumflexhook.lccircumflextilde.lc breveacute.lc brevegrave.lc brevehook.lc brevetilde.lc uni1FEF.short tonos.shortlamedholamdagesh lamedholamfinalkafqamats finalkafshevaaleflamedhatafsegolaleflamedsegolaleflamedtserealternativelamed alefdagesh uni05B105BD uni05B205BD uni05B305BDrz        T|cyrlgrek$hebr0latn>ccmpccmpdlig" $,(848BLV`jt~ (2<FP           (06<     ",j"4FX:BJRZbjrz Q P O N M K J I H G E D C B A ? > = < ; : 9 8 7 L R @ F:BJRZbjrz m l k j i g f e d c a ` _ ^ ] \ [ Z Y W V U T S n b X h:BJRZbjrz           ~ } | { y x w v u s r q p o   t z:BJRZbjrz                            :BJRZbjrz                            J",6@  Vcyrlgrek&hebr2latn@kernkernmark  6>FNV^fn|&.6>     jx|8  #j&&&'8''(F( () )<)l)))*,*\***++,+Z+~;;>pB0ElI,I4IP1lll~.6llL.llll....llll..lll  ))    ))        ,        ))    -          1       n L $*06<BHNTZ`flrx~ &,28>DJPV\<<<<<<<~<<<<<<<<PPd<<<~<<<<<<<<<<~<<<<< ( H" X &,28>DJPV\bhntz x  XX&|vll   L28>DJPV\bhntz "(.4:@FLRX^djpv| $*06<BHNTZ`flrx~ &,28>DJPV\bhntzFFhFhFXFXFFFFFFFXFXF F F@F@FXFXXFXXFXFF0F0FFFFFFXFXFFFXFXFXFXFFFFFFFFFFFhFhFXFXFFFFFFXFX F @F@FXFXXFXF0F0FFF00XFXXFXFF ( HFLRX^djpv|FFFFFFFFFFFFFn. L28>DJPV\bhntz "(.4:@FLRX^djpv| $*06<BHNTZ`flrx~ &,28>DJPV\bhntz00>>,,hhXX00\l4XX>04hh00>0,,ThhXXXX\l400XXTT ( H   jpv|-22<2 !< !J`    J`      J`    !   J`    ! 4<4J4< !4J !Jl      Jb    Jl       !Jb     !n L $*06<BHNTZ`flrx~ &,28>DJPV\FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFdFFFFLFLFFF ( HFFFn L $*06<BHNTZ`flrx~ &,28>DJPV\8FFFFFhFFFFhF F FpFFFhFFFFFFFFF\FFLF F F FF F8FFF F FF\FLFFFFF8F8F8FFFFFhFFFhF F F FFFFFFFF\FFLFFF FF F F F F ( H FFn L $*06<BHNTZ`flrx~ &,28>DJPV\$HD88\ X88$888888$$$HD$ X8$H ( H ( >     $*  $*  $*  $*  $*  $*  "  $*$*$*$*$*$*$*$*$*$*$*$*$*"( "( pi 2@^p4r|&Tv.8,:dR>TZ`6  . < b 0 H j  @ R  , > l .p(FLZ $7<8ADKSTZh 7h9h:?ACDHJKOQRSTUWXZcegijmnopsuvx{} >  n L $*06<BHNTZ`flrx~ &,28>DJPV\`88ppp8LL8\Ppppp`pp\PP```pppLL8\PLpppp ( H n L $*06<BHNTZ`flrx~ &,28>DJPV\&0,ThXXXlhhhXh000,ThXXl0XTT ( H   flrx~888888888n L $*06<BHNTZ`flrx~ &,28>DJPV\FFhFFXFFFFFFFFFF FF@FFXFXFXFFF0FFFFFFFXFFF0FFFFFFFF FF FFFFFhFFXFFFFFFFF F@FFXFXFF0FFFFFhF,FFFFFF ( H:@FLRX^djpv|FF,FFF,FhF,FFFFFFnn L $*06<BHNTZ`flrx~ &,28>DJPV\0h,|hXX,XX0h,|hXXXh0X ( H   flrx~h@,,x|,|@p 8ɉo1@1flare-engine-0.19/mods/default/images/000077500000000000000000000000001224717101500176325ustar00rootroot00000000000000flare-engine-0.19/mods/default/images/logo/000077500000000000000000000000001224717101500205725ustar00rootroot00000000000000flare-engine-0.19/mods/default/images/logo/icon.png000066400000000000000000000021011224717101500222220ustar00rootroot00000000000000PNG  IHDR szzIDATxݖNWE% &lDMD4wHU۹+a*EIH1Ć 6p0Us4TW<w$R(c׷_:S)f]O;*| <8$j9pհ/'g09Lt3C\;0{ 8rG+űpȹg@@Kp{E~I0O fiuk{ J E? Nfd\n`I='o+(QRd  ˒!5lo 660Y%Y YuVAژHQD /v/smKZ)(YwJd}KD;o+7dD!y=kÜYe Je'n)r_nga-2kxtcN֭|*qJ-yeoneDƐ]JD#v&.TnJ#~= Ik.H b>@] ؂  5`mJV\d X`3x۱*Wc0^C [6끃*^ߪې4슴w (LpR׫h$،jX VQ [[NGE WlѦяnEb119`/97O;*kA#u ؎؈X܀ȐzMO'mU3NnDS^`ߍȨ>KJ4`,xz 6(限ݛtp8 k@ڰ7"#ΠBJ@27b$\,CHa[EED>o220) "ƚp&1or$BѣۑPa*IENDB`flare-engine-0.19/mods/default/images/menus/000077500000000000000000000000001224717101500207615ustar00rootroot00000000000000flare-engine-0.19/mods/default/images/menus/buttons/000077500000000000000000000000001224717101500224575ustar00rootroot00000000000000flare-engine-0.19/mods/default/images/menus/buttons/button_default.png000066400000000000000000000004471224717101500262110ustar00rootroot00000000000000PNG  IHDRp:KUR$PLTE333UUUfff333UUUfff"PjtRNSnIDATXױ AEXv`&osm`;LPELMp_'L*-=z;4cgQ MF&t겭;>{4`{~Wn88888;Ows z&IENDB`flare-engine-0.19/mods/default/images/menus/buttons/button_x.png000066400000000000000000000003631224717101500250310ustar00rootroot00000000000000PNG  IHDR`0BfPLTE333DDDUUUffftRNS@fIDATHA D]P%^5Wb7/ [Ǝ[ӡ1:7ט4@:en^2n?G}uVaJk*%pOWJv\ͮ(p{/B -IENDB`flare-engine-0.19/mods/default/images/menus/buttons/checkbox_default.png000066400000000000000000000002501224717101500264540ustar00rootroot00000000000000PNG  IHDR,epPLTEDDD+tRNSv8FIDAT(c` 0@âÃ9C9.JJ.0C9*.@ ..J9(ʐ @1RCG67 IENDB`flare-engine-0.19/mods/default/images/menus/buttons/down.png000066400000000000000000000003451224717101500241360ustar00rootroot00000000000000PNG  IHDR`(gPLTE333DDDUUUffftRNS@f{IDAT8cdK`_,q&&$@cCdL&pC289PdXW٬, t ġn,pOܳphzC7ȚYF)pc @Z8uF]IENDB`flare-engine-0.19/mods/default/images/menus/buttons/left.png000066400000000000000000000003421224717101500241160ustar00rootroot00000000000000PNG  IHDR`0BfPLTE333DDDUUUffftRNS@fxIDATH C;ţ@VDZ OTs@y0VItӴ4/+Xn䒂$އ0|D_UpuϕBD;\?{\ \5F&J3W De*`IENDB`flare-engine-0.19/mods/default/images/menus/buttons/listbox_default.png000066400000000000000000000002221224717101500263510ustar00rootroot00000000000000PNG  IHDRT= PLTEuk/tRNSv83IDATHco` _ JlTըQUFUU5jTըQU#N=cH%IENDB`flare-engine-0.19/mods/default/images/menus/buttons/right.png000066400000000000000000000003441224717101500243030ustar00rootroot00000000000000PNG  IHDR`0BfPLTE333DDDUUUffftRNS@fzIDATH C;śaSO) VtF)g7N<-:-=Ǫ6J8'՛5JRHkWՠ L޹jT'u*.IENDB`flare-engine-0.19/mods/default/images/menus/buttons/scrollbar_default.png000066400000000000000000000003321224717101500266520ustar00rootroot00000000000000PNG  IHDRK-PLTE333UUUffftRNS@fyIDATx͒ C,Rd`@Q49xʸ2 v9F 8>0 rиLȗWa~W#_|}?{ C%PIENDB`flare-engine-0.19/mods/default/images/menus/buttons/slider_default.png000066400000000000000000000003241224717101500261520ustar00rootroot00000000000000PNG  IHDRH} WPLTEfffDDDUUUfffϮtRNSvhIDATX 0mWM K^Em*\ k``IH$gZ"Ir)IQ;{2Z+sU1QDiJzGre L#*IENDB`flare-engine-0.19/mods/default/images/menus/buttons/up.png000066400000000000000000000003451224717101500236130ustar00rootroot00000000000000PNG  IHDR`0BfPLTE333DDDUUUffftRNS@f{IDATHK 0DGqP&J]" BCtR3`muEV%[(Dt?}@1$^]@>D_2q>rADL?ž}pLg?\=sUL[c*IENDB`flare-engine-0.19/mods/default/images/menus/config.png000066400000000000000000000003161224717101500227340ustar00rootroot00000000000000PNG  IHDR`ZPLTE333IDATx10 yw&r̥kvP( BP( BP( BP( BP( BP( BP( BP( BP( BP( BP( BP( BP( BP(  %b..IENDB`flare-engine-0.19/mods/default/images/menus/confirm_bg.png000066400000000000000000000001541224717101500235740ustar00rootroot00000000000000PNG  IHDR@vPLTEDDDS9Y!IDAT8Ocπ064`I V@}SIENDB`flare-engine-0.19/mods/default/images/menus/logo.png000066400000000000000000000134071224717101500224340ustar00rootroot00000000000000PNG  IHDRd#IDATxtTպd&L&eB@@AQ.RE.FPOQR.wmXpEA{A3LLr q~{%LalsvxK(.[%JxP .[%B&V(/  \\D)!©^j{ \\+,h%^L -V\*pq,m-Q%*X(ORvdV^_%^Fj|#z%ftSeZץZTj-5.YX;Ez\ #-OT\\rW<=4L=3<ЦYMIG)ʣs 8H̀ph9mCкSKͯCqyk؂V2pθz)QiP?dFkF8B'jGZ8g\DU\癒_8pe$5`6DԜ%"7kH 4*m!դ_>mh} ^OmaAB; d ;( @۪I[, |Nqц(\jZ]-hP[9gQABڎJްT6/ě+`6 5P{sY=hIN|?[#qf0ڷoO46yQF344T[fygNСÐ!C̝;~e𻉉j:(a: +ԾwjPJVw-ЦVVx3X fDulj鼠R48=l{2_=h-"%'x7|c}ũyѣGE.\<ؠAv}E|={v۶mSQ N̠BWE9ue]p(ʹ)+h&V hMYqZ =Y]Cg:+g?-Ћ/hZoI T^8tl3@FP[?F(_YBK9mE֖8b[pZLM")jaWKӓUp]/2ZL" K-9oQ^^oJǎKHH'IKK efftΟ?_hb 61g ܀bW2Nwvz4ifƜK˪jB`lwm'"Vuhneй8cU'pFRJŭ@9aRY.8p@F{=UӦM q]r8\ҫkZ-&|̠ƤV!KůhQ3^g\aLѠ\vJEΠ^7WU|򉌜$š9YYәC _0XL4“3TZrzx"٢?Ƚ{tҥ>}T)St{|12VZiGbr%M(3Ib'pJH#Bv'{g;#jn@ݡpֻRka;'ZFܩg>Ιw:ߏ'X%\`U^؁ /hPbә $ Uc,+#m39%g3Hdo݅)NK$Π`Ssk :4 JhT>͙dꫯW]reĈr6sfYjp&3T\m~TA46Fyr&vX@& :8XLgֆ4DBm՞ 84x{r\,ss,^HE]ݻl C'e7%r4j3A ̀^9`#rª (4]8rk.UHnؓB}ӚڜBv3& h~vuotaz#rFf8c#Nr#9(I g0^ XazTGF:dp tdSD 06J8m"g$_aΟ?*""9c~9IA=uB܀s<8+́7QLNs \ڑzϠX=7XχvCOF8JX( t tv>8{\ G,3$#g (|\ރ@g9#eV 6 j\[a+;mɊMRkT%qVk5(09~94 6VuKlws q]>| RSDf&0.։85Y&м mFjՊv rsi™ (B;#g>ӛ?{<@Ǚp]YT2?cAbgt8)6]ޚʸlP6H鉆Iv7i)5d_TfPPSxFsl6 TVmJ<TA⺔$Ȣϩ g m3)9Kg%gHJN疸"' 4Æq+"SOZ;ЯuN_[kUnnnSr]\UpR˵z}un,Ue(9ݜֆR%u;*Yu.`?67ξ;U,6>|)9^r>}W^;w㏱W-\:6CL+ElmH/rdwGgE؜ ę%e폦 .qC3MƧhZIhe3:z%Nzoza1* tsDku7P5,e˖ndTIry3DS4RrJ)Zf !}A9z55 OCtpЕ;Pc-cj[5: lSr&]۷OKZ3h)-931EC'pƪNݠSOUk=Cdlm\1S)ed6 @ a GfޫI+}3vA=W웞3,A I,l&DTrSΤ]^F*@ mK~ݒx8J K6q,DE~Pq@&f21}3G{ڢ],, fp=::9cr{UO K#)z^rritE>-h+A VdT%\?o'mmto.lx'4fɅ{x8ڗӵ=TO }g:}GTSn`Ω{D(??Uuꗠ`)Z>8c]aN>el DYĔfl$QiX?H#4 aÆ͢*A/`gP7MI2D@pi'j@E-#0wM0z=,A;άTtfr}(OSAnU'kz4PCb=~es7դH@u9w@З-etY2GMA̙9Vosw.u.ӡLwΚ wDmsL[:N}0j0eB2D c234@"?™Zĺ9uiŒKcuK[pViۧcJ4*{~* G@j3C: W \n=.-ˀ@XD, 2013. msgid "" msgstr "" "Project-Id-Version: flare-engine data\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+\n" "PO-Revision-Date: 2013-11-29 07:40+0100\n" "Last-Translator: GunChleoc \n" "Language-Team: Fòram na Gàidhlig http://www.foramnagaidhlig.net\n" "Language: gd\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : " "(n > 2 && n < 20) ? 2 : 3;\n" "X-Generator: Virtaal 0.7.1\n" #: ../cutscenes/credits.txt:6 msgid "Flare Engine Credits" msgstr "Cliù airson an einnsein flare" #: ../cutscenes/credits.txt:8 msgid "" "Lead Programmers - Clint Bellanger, Henrik Andersson, Igor Paliychuk, Justin " "Jacobs, Stefan Beller, and Thane Brimhall" msgstr "" "Prìomh-phrògramairean - Clint Bellanger, Henrik Andersson, Igor Paliychuk, " "Justin Jacobs, Stefan Beller agus Thane Brimhall" #: ../cutscenes/credits.txt:10 msgid "" "Programmers - Anton Golov, Artur Rojek, Bonbadil, Chris Oelmueller, David " "Bariod, Daniel Santos, Gallaecio, Joseph Bleu, Juan PabloTamayo, Kitano, " "Kyle Belanger, LongerDev, Manuel A. Fernandez Montecelo, Matthew Krohn, " "Nojan, Pavel Kirpichyov, and runtime-x86" msgstr "" "Prògramairean - Anton Golov, Artur Rojek, Bonbadil, Chris Oelmueller, David " "Bariod, Daniel Santos, Gallaecio, Joseph Bleu, Juan PabloTamayo, Kitano, " "Kyle Belanger, LongerDev, Manuel A. Fernandez Montecelo, Matthew Krohn, " "Nojan, Pavel Kirpichyov agus runtime-x86" #: ../cutscenes/credits.txt:12 msgid "Default Art - Clint Bellanger" msgstr "Ealan tùsail - Clint Bellanger" #: ../cutscenes/credits.txt:14 msgid "" "Translators - Adrian Chaves Fernandez, Andrea Ranaldi, Andreas Berheim " "Brudin, Bas Doodeman, Bonbadil, Carlos Sanchez, Chris Oelmueller, Christoph " "J. Thompson, Evgen Pavlov, Giovanni Dalla Torre, Hans Joachim Desserud, Igor " "Paliychuk, Juan Pablo Tamayo, Mikhail Karalevich, Miro Jánošík, Morgan " "Strauss, Nikita Vanku, Paul Wortmann, Pawel Puszczynski, Quentin Stievenart, " "Sergey Basalaev, Stefan Beller, Thomas Glamsch, Timo Sievänen, and Yannis " "Anthymidis" msgstr "" "Eadar-theangadairean - Adrian Chaves Fernandez, Andrea Ranaldi, Andreas " "Berheim Brudin, Bas Doodeman, Bonbadil, Carlos Sanchez, Chris Oelmueller, " "Christoph J. Thompson, Evgen Pavlov, Giovanni Dalla Torre, Hans Joachim " "Desserud, Igor Paliychuk, Juan Pablo Tamayo, Mikhail Karalevich, Miro " "Jánošík, Morgan Strauss, Nikita Vanku, Paul Wortmann, Pawel Puszczynski, " "Quentin Stievenart, Sergey Basalaev, Stefan Beller, Thomas Glamsch, Timo " "Sievänen agus Yannis Anthymidis" #: ../cutscenes/credits.txt:16 msgid "" "Distributors - Ablu, Feillyne, Jan-Hendrik Peters, Manuel A. Fernandez " "Montecelo, miffe" msgstr "" "Sgaoileadairean - Ablu, Feillyne, Jan-Hendrik Peters, Manuel A. Fernandez " "Montecelo, miffe" #: ../cutscenes/credits.txt:18 msgid "" "Special Thanks - Bart Kelsey and the community at OpenGameArt, for giving " "constant feedback and testing. Thorbjørn Lindeijer, Stefan Beller, and Ranie " "Jade Ramiso for Tiled and the Flare map exporter." msgstr "" "Taing shònraichte Thanks - Bart Kelsey is a' choimhearsnachd aig OpenGameArt " "airson beachdan is deuchainnean gun sgur. Thorbjørn Lindeijer, Stefan Beller " "is Ranie Jade Ramiso airson leacan is an t-às-phortachadh aig mapaichean " "Flare." #: ../cutscenes/intro_example.txt:6 msgid "Flare, the..." msgstr "Flare, an..." #: ../cutscenes/intro_example.txt:9 msgid "Free Libre Action Roleplaying Engine" msgstr "Einnsean saor airson cluich ghnìomhan mas fhìor" flare-engine-0.19/mods/default/languages/data.pot000066400000000000000000000042471224717101500217770ustar00rootroot00000000000000# Copyright (C) 2011 Clint Bellanger # This file is distributed under the same license as the FLARE package. # # FIRST AUTHOR , YEAR. msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../cutscenes/credits.txt:6 msgid "Flare Engine Credits" msgstr "" #: ../cutscenes/credits.txt:8 msgid "Lead Programmers - Clint Bellanger, Henrik Andersson, Igor Paliychuk, Justin Jacobs, Stefan Beller, and Thane Brimhall" msgstr "" #: ../cutscenes/credits.txt:10 msgid "Programmers - Anton Golov, Artur Rojek, Bonbadil, Chris Oelmueller, David Bariod, Daniel Santos, Gallaecio, Joseph Bleu, Juan PabloTamayo, Kitano, Kyle Belanger, LongerDev, Manuel A. Fernandez Montecelo, Matthew Krohn, Nojan, Pavel Kirpichyov, and runtime-x86" msgstr "" #: ../cutscenes/credits.txt:12 msgid "Default Art - Clint Bellanger" msgstr "" #: ../cutscenes/credits.txt:14 msgid "Translators - Adrian Chaves Fernandez, Andrea Ranaldi, Andreas Berheim Brudin, Bas Doodeman, Bonbadil, Carlos Sanchez, Chris Oelmueller, Christoph J. Thompson, Evgen Pavlov, Giovanni Dalla Torre, Hans Joachim Desserud, Igor Paliychuk, Juan Pablo Tamayo, Mikhail Karalevich, Miro Jánošík, Morgan Strauss, Nikita Vanku, Paul Wortmann, Pawel Puszczynski, Quentin Stievenart, Sergey Basalaev, Stefan Beller, Thomas Glamsch, Timo Sievänen, and Yannis Anthymidis" msgstr "" #: ../cutscenes/credits.txt:16 msgid "Distributors - Ablu, Feillyne, Jan-Hendrik Peters, Manuel A. Fernandez Montecelo, miffe" msgstr "" #: ../cutscenes/credits.txt:18 msgid "Special Thanks - Bart Kelsey and the community at OpenGameArt, for giving constant feedback and testing. Thorbjørn Lindeijer, Stefan Beller, and Ranie Jade Ramiso for Tiled and the Flare map exporter." msgstr "" #: ../cutscenes/intro_example.txt:6 msgid "Flare, the..." msgstr "" #: ../cutscenes/intro_example.txt:9 msgid "Free Libre Action Roleplaying Engine" msgstr "" flare-engine-0.19/mods/default/languages/data.uk.po000066400000000000000000000070571224717101500222330ustar00rootroot00000000000000# Copyright (C) 2011 Clint Bellanger # This file is distributed under the same license as the FLARE package. # # Igor Paliychuk , 2013. msgid "" msgstr "" "Project-Id-Version: 0.19\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+\n" "PO-Revision-Date: 2013-10-12 16:38+0200\n" "Last-Translator: Igor Paliychuk \n" "Language-Team: Ukrainian \n" "Language: Ukrainian\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.5.5\n" #: ../cutscenes/credits.txt:6 msgid "Flare Engine Credits" msgstr "Автори Flare Engine" #: ../cutscenes/credits.txt:8 msgid "Lead Programmers - Clint Bellanger, Henrik Andersson, Igor Paliychuk, Justin Jacobs, Stefan Beller, and Thane Brimhall" msgstr "Основні програмісти - Clint Bellanger, Henrik Andersson, Igor Paliychuk, Justin Jacobs, Stefan Beller та Thane Brimhall" #: ../cutscenes/credits.txt:10 msgid "Programmers - Anton Golov, Artur Rojek, Bonbadil, Chris Oelmueller, David Bariod, Daniel Santos, Gallaecio, Joseph Bleu, Juan PabloTamayo, Kitano, Kyle Belanger, LongerDev, Manuel A. Fernandez Montecelo, Matthew Krohn, Nojan, Pavel Kirpichyov, and runtime-x86" msgstr "Програмісти - Anton Golov, Artur Rojek, Bonbadil, Chris Oelmueller, David Bariod, Daniel Santos, Gallaecio, Joseph Bleu, Juan PabloTamayo, Kitano, Kyle Belanger, LongerDev, Manuel A. Fernandez Montecelo, Matthew Krohn, Nojan, Pavel Kirpichyov та runtime-x86" #: ../cutscenes/credits.txt:12 msgid "Default Art - Clint Bellanger" msgstr "Типова графіка - Clint Bellanger" #: ../cutscenes/credits.txt:14 msgid "Translators - Adrian Chaves Fernandez, Andrea Ranaldi, Andreas Berheim Brudin, Bas Doodeman, Bonbadil, Carlos Sanchez, Chris Oelmueller, Christoph J. Thompson, Evgen Pavlov, Giovanni Dalla Torre, Hans Joachim Desserud, Igor Paliychuk, Juan Pablo Tamayo, Mikhail Karalevich, Miro Jánošík, Morgan Strauss, Nikita Vanku, Paul Wortmann, Pawel Puszczynski, Quentin Stievenart, Sergey Basalaev, Stefan Beller, Thomas Glamsch, Timo Sievänen, and Yannis Anthymidis" msgstr "Перекладачі - Adrian Chaves Fernandez, Andrea Ranaldi, Andreas Berheim Brudin, Bas Doodeman, Bonbadil, Carlos Sanchez, Chris Oelmueller, Christoph J. Thompson, Evgen Pavlov, Giovanni Dalla Torre, Hans Joachim Desserud, Igor Paliychuk, Juan Pablo Tamayo, Mikhail Karalevich, Miro Jánošík, Morgan Strauss, Nikita Vanku, Paul Wortmann, Pawel Puszczynski, Quentin Stievenart, Sergey Basalaev, Stefan Beller, Thomas Glamsch, Timo Sievänen та Yannis Anthymidis" #: ../cutscenes/credits.txt:16 msgid "Distributors - Ablu, Feillyne, Jan-Hendrik Peters, Manuel A. Fernandez Montecelo, miffe" msgstr "Розповсюджувачі - Ablu, Feillyne, Jan-Hendrik Peters, Manuel A. Fernandez Montecelo, miffe" #: ../cutscenes/credits.txt:18 msgid "Special Thanks - Bart Kelsey and the community at OpenGameArt, for giving constant feedback and testing. Thorbjørn Lindeijer, Stefan Beller, and Ranie Jade Ramiso for Tiled and the Flare map exporter." msgstr "Окрема вдячність - Bart Kelsey та спільноті OpenGameArt, за постійні відгуки та тестування. Thorbjørn Lindeijer, Stefan Beller та Ranie Jade Ramiso за Tiled і експортер карт Flare." #: ../cutscenes/intro_example.txt:6 msgid "Flare, the..." msgstr "Flare" #: ../cutscenes/intro_example.txt:9 msgid "Free Libre Action Roleplaying Engine" msgstr "Вільний двигун рольових ігор" flare-engine-0.19/mods/default/languages/engine.be.po000066400000000000000000000701341224717101500225320ustar00rootroot00000000000000# Belarussian translation of Flare engine. v0.18 # (Я толькі вучуся. Выбачайце.) # Copyright (C) 2013 Clint Bellanger # This file is distributed under the same license as the PACKAGE package. # Mikhail Karalevich , 2013. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: flare-engine 0.18\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2013-03-29 01:00+0300\n" "Last-Translator: Mikhail Karalevich \n" "Language-Team: Belarussian \n" "Language: be\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "Віншуем, вы дасягнулі %d ўзроўня!" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "Вы можаце павялічыць адзін атрыбут у меню персанажа." #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "Вас забілі. Канец гульні! Націсніце Enter, каб выйсці ў меню." #: ../../../src/Avatar.cpp:634 #, fuzzy msgid "You are defeated. Press Enter to continue." msgstr "Вас забілі. Вы губляеце палову вашага %s. Націсніце Enter, каб працягнуць." #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "%d %s перанесена." #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "%s перанесена." #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "Вы атрымліваеце %s." #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "Вы атрымліваеце %s x%d." #: ../../../src/CampaignManager.cpp:168 #, c-format msgid "You receive %d %s." msgstr "Вы атрымліваеце %d %s." #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "Вы атрымліваеце %d XP." #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "HP адноўлена." #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "MP адноўлена." #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "HP і MP адноўлены." #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "Негатыўныя эфекты прыбраны." #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "HP і MP адноўлены, негатыўныя эфекты прыбраны." #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "промах" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "+%d HP" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "+%d MP" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "Невядомы накірунак" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "Добра" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "Па змаўчэнню" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "Скасаваць" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "Відэа" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "Аўдыа" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "Інтэрфэйс" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "Увод" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "Клавішы" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "Моды" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "Назначыць: " #: ../../../src/GameStateConfig.cpp:165 msgid "Reset ALL settings?" msgstr "Зкінуць УСЕ налады?" #: ../../../src/GameStateConfig.cpp:166 msgid "Use this resolution?" msgstr "Выкарыстоўваць гэтую распазнавальнасць?" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "Поўнаэкранны рэжым" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "Рухаць героем мышкай" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "Паказваць текст бою" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "Апаратныя паверхні" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "Двайны бафырынг" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "Вкарыстоўваць джосцік" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "Тэкстуры вылікай якасці" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "Дазволіць змену гамы" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "Анімацыйныя тайлы" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "Цэліцца мышкай" #: ../../../src/GameStateConfig.cpp:318 #, fuzzy msgid "Do not use mouse" msgstr "Рухаць героем мышкай" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "Паказваць FPS" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "Паказаць гарачыя клавішы" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "Рэжым дальтанізма" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "Гучнасць музыкі" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "Гучнасць гука" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "Гама" #: ../../../src/GameStateConfig.cpp:377 #, fuzzy msgid "Joystick Deadzone" msgstr "Джосцік" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "Распазнавальнасць" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "Актыўныя моды" #: ../../../src/GameStateConfig.cpp:412 msgid "Available Mods" msgstr "Наяўныя моды" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "Джосцік" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "Мова" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 msgid "Disable for performance" msgstr "Прыбярыце, калі гульня тармозіць" #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "Эксперыментальна" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "Для мабільных прылад" #: ../../../src/GameStateConfig.cpp:527 msgid "<< Disable" msgstr "<< Прыбраць" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr "Дадаць >>" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "Выдаліць гульню" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "Выдаліць захаваную гульню?" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "Выхад у меню" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "Выбярыце слот" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "Новая гульня" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "Дадайце сюжэтны мод, каб працягнуць" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "Загрузіць гульню" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "Уваход у гульнявы сусвет..." #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "Загрузка захаванай гульні..." #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "Узровень %d %s" #: ../../../src/GameStateLoad.cpp:579 #, fuzzy msgid "Permadeath" msgstr "Смертны?" #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "Пусты слот" #: ../../../src/GameStateNew.cpp:62 msgid "Create" msgstr "Стварыць" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "Выбярыце партрэт" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "Выбярыце імя" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "Смертны?" #: ../../../src/GameStateNew.cpp:179 msgid "Choose a Class" msgstr "Выбярыце клас" #: ../../../src/GameStatePlay.cpp:99 msgid "Loading..." msgstr "Загрузка..." #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "Інвентар поўны." #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "Гуляць" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "Дадайце базавы мод, каб працягнуць" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "Канфігурацыя" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "Стваральнікі" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "Выхад" #: ../../../src/GameStateTitle.cpp:67 #, fuzzy msgid "Flare Alpha v0.19" msgstr "Flare Alpha v0.19" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "Прыняць" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "Уверх" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "Уніз" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "Налева" #: ../../../src/InputState.cpp:627 msgid "Right" msgstr "Направа" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "Меню1" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "Меню2" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "Меню3" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "Меню4" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "Меню5" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "Меню6" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "Меню7" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "Меню8" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "Меню9" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "Меню0" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "Персанаж" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "Інвентар" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "Моцы" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "Нататнік" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "Галоўнае1" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "Галоўнае2" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "Ctrl" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "Shift" #: ../../../src/InputState.cpp:646 msgid "Delete" msgstr "Delete" #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "МенюДзей Прыняць" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "МенюДзей Лева" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "МенюДзей Права" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "МенюДзей Выкарыстаць" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "лкм" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "скм" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "пкм" #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "кола ўверх" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "кола ўніз" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "mbx1" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "mbx2" #: ../../../src/ItemManager.cpp:488 #, fuzzy msgid "Low" msgstr "Нізкі" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "Нармальны" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "Высокі" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "Эпічны" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "Узровень %d" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "Урон бліжняга бою: %d-%d" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "Урон бліжняга бою: %d" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "Урон дальняга боя: %d-%d" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "Урон дальняга боя: %d" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "Урон магіі: %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "Урон магіі: %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "Паглынае: %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "Паглынае: %d" #: ../../../src/ItemManager.cpp:554 #, fuzzy, c-format msgid "%d% Speed" msgstr "%d\\% Хуткасць" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "Павялічвае %s на %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "Памяншае %s на %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "Патрабуе сілы %d" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "Патрабуе магію %d" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "Патрабуе спрытнасць %d" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "Патрабуе абарону %d" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "Якасць: %s" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, c-format msgid "Buy Price: %d %s" msgstr "Кошт пакупкі: %d %s" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, c-format msgid "Buy Price: %d %s each" msgstr "Кошт пакупкі: %d %s за кожны" #: ../../../src/ItemManager.cpp:643 #, c-format msgid "Sell Price: %d %s" msgstr "Кошт продажу: %d %s" #: ../../../src/ItemManager.cpp:645 #, c-format msgid "Sell Price: %d %s each" msgstr "Кошт продажу: %d %s за кожны" #: ../../../src/ItemManager.cpp:655 msgid "Set: " msgstr "Усталяваць: " #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "%d прадметаў: " #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "Імя" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "Узровень" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "Сіла" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "Магія" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "Спрытнасць" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "Абарона" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "ачкоў засталося" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "Макс HP:" #: ../../../src/MenuCharacter.cpp:340 msgid "HP Regen:" msgstr "Аднаўленне HP:" #: ../../../src/MenuCharacter.cpp:341 msgid "Ticks of HP regen per minute. " msgstr "Аднаўленне HP за хвіліну. " #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "Макс MP:" #: ../../../src/MenuCharacter.cpp:352 msgid "MP Regen:" msgstr "Аднаўлен МР:" #: ../../../src/MenuCharacter.cpp:353 msgid "Ticks of MP regen per minute. " msgstr "Аднаўленне MP за хвіліну. " #: ../../../src/MenuCharacter.cpp:358 msgid "Accuracy:" msgstr "Точнасць:" #: ../../../src/MenuCharacter.cpp:364 msgid "Avoidance:" msgstr "Ухіленне:" #: ../../../src/MenuCharacter.cpp:370 msgid "Melee Damage:" msgstr "Бліжні ўрон:" #: ../../../src/MenuCharacter.cpp:380 msgid "Ranged Damage:" msgstr "Дальні ўрон" #: ../../../src/MenuCharacter.cpp:390 msgid "Mental Damage:" msgstr "Магічны ўрон:" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "Крыт:" #: ../../../src/MenuCharacter.cpp:406 msgid "Absorb:" msgstr "Паглынае:" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "Супраціў яду: " #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "Зніжае ваш шанец натыкнуцца пры ўдары" #: ../../../src/MenuCharacter.cpp:422 #, fuzzy msgid "Bonus XP: " msgstr "Бонус XP: " #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "Павялічвае XP за кожнае забойства" #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "Бонус" #: ../../../src/MenuCharacter.cpp:429 #, c-format msgid "Increases the %s found per drop" msgstr "Павялічвае колькасць знойдзеннага %s " #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "Бонус да пошука прадметаў: " #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "Павялічвае шанец, што вораг выране які-небудзь прадмет калі памрэ" #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "Патаемнасць" #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "Павялічвае магчымасць рухацца незаўажна" #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "XP: %d" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "Наступны: %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "Сіла (P) павялічвае урон бліжняга боя і HP." #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "базавае (%d), бонус (%d)" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "Магія (M) павялічвае урон магіі і MP." #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "Спрытнасць (O) павялічвае урон дальняга бою і точнасць." #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "Абарона (D) павялічвае шчыт і ухіленне." #: ../../../src/MenuCharacter.cpp:498 #, c-format msgid "Each level grants %d. " msgstr "Кожны ўзровень дае %d. " #: ../../../src/MenuCharacter.cpp:500 #, fuzzy, c-format msgid "Each point of Physical grants %d. " msgstr "Кожны пункт сілы дае +%d HP. Кожны ўзровень павялічвае +%d HP" #: ../../../src/MenuCharacter.cpp:502 #, fuzzy, c-format msgid "Each point of Mental grants %d. " msgstr "Кожны пункт магіі дае +%d MP. Кожны ўзровень павялічвае +%d MP" #: ../../../src/MenuCharacter.cpp:504 #, fuzzy, c-format msgid "Each point of Offense grants %d. " msgstr "Кожны пункт магіі дае +%d MP. Кожны ўзровень павялічвае +%d MP" #: ../../../src/MenuCharacter.cpp:506 #, fuzzy, c-format msgid "Each point of Defense grants %d. " msgstr "Кожны пункт магіі дае +%d MP. Кожны ўзровень павялічвае +%d MP" #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "Забіты" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "%s узровеь %d" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "Выхад" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "Захаваць і выйсці ў меню?" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "Загублена %d%% з %s. " #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "Загублена %d%% з усяго XP. " #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "Загублена %d%% з бягучага ўзроўня XP. " #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "Загублена %s." #: ../../../src/MenuInventory.cpp:228 #, c-format msgid "%d %s" msgstr "%d %s" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "Карыстайцеся SHIFT, каб перадвінуць толькі адзін прадмет." #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "CTRL+націск лкм, каб прадаць прадмет. " #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "Гэты прадмет можа быць выкарастан толькі з меню дзей." #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "Запісы" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "Заданні" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "XP: %d/%d" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, fuzzy, c-format msgid "Not enough %s." msgstr "Недастаткова %s." #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "Гандляваць" #: ../../../src/MenuPowers.cpp:463 msgid "Unspent skill points:" msgstr "Не патрачана навыкаў" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" "\n" "Наступны ўзровень:" #: ../../../src/MenuPowers.cpp:525 #, fuzzy, c-format msgid "Requires a %s" msgstr "Патрабуе магію %d" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "Патрабуе фізічную спрытнасць %d" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "Патрабуе фізічную абарону %d" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "Патабуе магічную спрытнасць %d" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "Патрабуе магічную абарону %d" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, c-format msgid "Requires Level %d" msgstr "Патрабуе %d ўзровень" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, c-format msgid "Requires %d Skill Point" msgstr "Патрабуе %d навыка" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "Націсніце, каб разблакаваць" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, c-format msgid "Requires Power: %s" msgstr "Патрабуе: %s" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "Каштуе %d MP" #: ../../../src/MenuPowers.cpp:625 #, c-format msgid "Costs %d HP" msgstr "Каштуе %d HP" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "Аднаўлене: %d секунд" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "Агульныя запасы" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "Выкуп" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "Гандляр" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "+%d Шчыт" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "Вы ўжо трансфарміраваны, растрансфарміруўцеся сперва." #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "Шукальнік прыгод" #: ../../../src/Utils.cpp:519 msgid "k" msgstr "k" #~ msgid "Character Menu (C)" #~ msgstr "Персанаж (C)" #~ msgid "Inventory Menu (I)" #~ msgstr "Інвентар (I)" #~ msgid "Power Menu (P)" #~ msgstr "Моцы (P)" #~ msgid "Log Menu (L)" #~ msgstr "Нататнік (L)" #~ msgid "Ticks of HP regen per minute. Each point of Physical grants +%d HP regen. Each level grants +%d HP regen" #~ msgstr "Колькасць аднаўлення HP у хвіліну. Кожны пункт сілы павялічвае +%d HP. Кожны ўзровень павялічвае +%d HP" #~ msgid "Ticks of MP regen per minute. Each point of Mental grants +%d MP regen. Each level grants +%d MP regen" #~ msgstr "Колькасць аднаўлення MP у хвіліну. Кожны пункт магіі павялічвае +%d MP. Кожны ўзровень павялічвае +%d MP" #~ msgid "Each point of Offense grants +%d accuracy. Each level grants +%d accuracy" #~ msgstr "Кожны пункт спрытнасці павялічвае +%d точнасць. Кожны ўзровень павялічвае +%d точнасць" #~ msgid "Each point of Defense grants +%d avoidance. Each level grants +%d avoidance" #~ msgstr "Кожны пункт абароны павялічвае +%d ухіленне. Кожны ўзровень павялічвае +%d ухіленне" #~ msgid "Requires a physical weapon" #~ msgstr "Патрабуе фізічную зброю" #~ msgid "Requires a mental weapon" #~ msgstr "Патрабуе магічную зброю" #~ msgid "Requires an offense weapon" #~ msgstr "Патрабуе спрытную зброю" flare-engine-0.19/mods/default/languages/engine.cs.po000066400000000000000000000605771224717101500225630ustar00rootroot00000000000000# Copyright (C) 2011 Clint Bellanger # This file is distributed under the same license as Flare package. # Nikita Vaňků , 2013. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: 0.18\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2013-03-25 10:03+ZONE\n" "Last-Translator: Nikita Vaňků \n" "Language-Team:\n" "Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "Dosáhl jsi levelu %d!" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "Můžete zvýšit jeden atribtu v Menu Postavy" #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "Jsi poražen. Game over! Stiskni Enter pro odchod do Menu." #: ../../../src/Avatar.cpp:634 #, fuzzy msgid "You are defeated. Press Enter to continue." msgstr "Jsi poražen. Ztrácíš polovinu tvých %s. Pro pokračování stiskni Enter." #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "" #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "" #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "Dostáváš %s." #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "Dostáváš %s x%d." #: ../../../src/CampaignManager.cpp:168 #, c-format msgid "You receive %d %s." msgstr "Dostáváš %d %s." #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "Dostáváš %d XP." #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "HP obnoveno." #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "MP obnoveno." #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "HP a MP obnoveno." #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "Negativní účinky odstraněny." #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "HP a MP obnoveno, negativní účtinky odstraněny" #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "minout" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "%d MP" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "Neznámá lokace" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "Původní" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "Zrušit" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "Vstup" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "Nastavení kláves" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "Mody" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "Přiřadit: " #: ../../../src/GameStateConfig.cpp:165 msgid "Reset ALL settings?" msgstr "Vrátit původní nastavení?" #: ../../../src/GameStateConfig.cpp:166 msgid "Use this resolution?" msgstr "Použít toto rozlišení?" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "Mod plné obrazovky" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "Chůze pomocí myši" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "Zobraz bojový text" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "Hardwarové povrchy" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "Dvojitý buffering" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "Použít joystick" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "Textury Vysoké kvality" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "Povolit změnu gammy" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "Animované dlaždice" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "Míření myší" #: ../../../src/GameStateConfig.cpp:318 #, fuzzy msgid "Do not use mouse" msgstr "Chůze pomocí myši" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "Zobraz FPS" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "Hlasitost Hudby" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "Hlasitost Zvuku" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "" #: ../../../src/GameStateConfig.cpp:377 msgid "Joystick Deadzone" msgstr "" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "Rozlišení" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "Aktivní mody" #: ../../../src/GameStateConfig.cpp:412 msgid "Available Mods" msgstr "Mody k dispozici" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "Jazyk" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 msgid "Disable for performance" msgstr "Zakážte pro rychlejší vykreslování" #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "Experimentální" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "" #: ../../../src/GameStateConfig.cpp:527 msgid "<< Disable" msgstr "<< Zakázat" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr "Povolit >>" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "Vymazat uložené pozice" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "Vymazat tuto pozici?" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "Ukončit do menu" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "Vyber si pozici" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "Nová Hra" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "Pro pokračování povol příběhový mod" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "Nahrát Hru" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "Vstupuji do herního světa..." #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "Nahrávám uloženou pozici..." #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "" #: ../../../src/GameStateLoad.cpp:579 #, fuzzy msgid "Permadeath" msgstr "Pernamentní smrt?" #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "Volná pozice" #: ../../../src/GameStateNew.cpp:62 msgid "Create" msgstr "Vytvořit" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "Zvol si Portrét" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "Zvol své Jméno" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "Pernamentní smrt?" #: ../../../src/GameStateNew.cpp:179 msgid "Choose a Class" msgstr "Zvol své povolání" #: ../../../src/GameStatePlay.cpp:99 msgid "Loading..." msgstr "Nahrávám..." #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "Inventář je plný." #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "Hrát Hru" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "Pro pokračování povol mod jádra" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "Nastavení" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "Ukončit Hru" #: ../../../src/GameStateTitle.cpp:67 msgid "Flare Alpha v0.19" msgstr "" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "Příjmout" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "Nahoru" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "Dolů" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "Doleva" #: ../../../src/InputState.cpp:627 msgid "Right" msgstr "Doprava" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "Postava" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "Inventář" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "Schopnosti" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "Deník" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "" #: ../../../src/InputState.cpp:646 msgid "Delete" msgstr "" #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "L. tl. myši" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "Pros. tl. myši" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "P. tl. myši." #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "kolečko nahoru" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "kolečko dolů" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "" #: ../../../src/ItemManager.cpp:488 #, fuzzy msgid "Low" msgstr "Deník" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "Poškození zblízka: %d-%d" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "Poškození zblízka: %d-%d" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "Střelné poškození: %d-%d" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "Střelné poškození: %d" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "Psychické poškození: %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "Psychické poškození: %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "Absorbuje: %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "Absorbuje: %d" #: ../../../src/ItemManager.cpp:554 #, fuzzy, c-format msgid "%d% Speed" msgstr "%d\\% Rychlost" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "Zvyšuje %s o %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "Snižuje %s o %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "Potřebuje Fyzickou sílu %d" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "Potřebuje Mentální sílu %d" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "Potřebuje Útok %d" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "Potřebuje Obranu %d" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, c-format msgid "Buy Price: %d %s" msgstr "Nákupní Cena: %d %s" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, c-format msgid "Buy Price: %d %s each" msgstr "Nákupní Cena: %d %s každý" #: ../../../src/ItemManager.cpp:643 #, c-format msgid "Sell Price: %d %s" msgstr "Prodejní Cena: %d %s" #: ../../../src/ItemManager.cpp:645 #, c-format msgid "Sell Price: %d %s each" msgstr "Prodejní Cena: %d %s každý" #: ../../../src/ItemManager.cpp:655 msgid "Set: " msgstr "Nastavit: " #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "%d předměty: " #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "Jméno" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "Fyzická Sílá" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "Mentální Síla" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "Útok" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "Obrana" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "zbývající body" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "" #: ../../../src/MenuCharacter.cpp:340 msgid "HP Regen:" msgstr "HP Regenerace" #: ../../../src/MenuCharacter.cpp:341 msgid "Ticks of HP regen per minute. " msgstr "" #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "" #: ../../../src/MenuCharacter.cpp:352 msgid "MP Regen:" msgstr "MP Regenerace:" #: ../../../src/MenuCharacter.cpp:353 msgid "Ticks of MP regen per minute. " msgstr "" #: ../../../src/MenuCharacter.cpp:358 msgid "Accuracy:" msgstr "Přesnost:" #: ../../../src/MenuCharacter.cpp:364 msgid "Avoidance:" msgstr "Vyhýbání se:" #: ../../../src/MenuCharacter.cpp:370 msgid "Melee Damage:" msgstr "Poškození chladnými zbraněmi:" #: ../../../src/MenuCharacter.cpp:380 msgid "Ranged Damage:" msgstr "Poškození střelnými zbraněmi:" #: ../../../src/MenuCharacter.cpp:390 msgid "Mental Damage:" msgstr "Mentální poškození:" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "" #: ../../../src/MenuCharacter.cpp:406 msgid "Absorb:" msgstr "Absorbovat:" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "" #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "Snižuje tvou šanci ochromení při zásahu" #: ../../../src/MenuCharacter.cpp:422 msgid "Bonus XP: " msgstr "" #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "Zvyšuje XP získane zabitím" #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "" #: ../../../src/MenuCharacter.cpp:429 #, c-format msgid "Increases the %s found per drop" msgstr "Zvyšuje šanci nalezení %s" #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "" #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "Zvyšuje šanci, že nepřítel bude po smrti u sebe mít předmět" #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "" #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "Zvyšuje schopnost pohybovat se nepozorovaně." #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "Další: %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "Fyzická Síla (P) zvyšuje účinnost chladných zbraní a maximální HP." #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "základní (%d), bonus (%d)" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "Mentální síla (M) zvyšuje účinnost mentální zbraní a maximální MP." #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "Útok (O) zvyšuje účinnost a přesnost střelných zbrnaí." #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "Obrana (D) zvyšuje účinnost zbroje a šanci úniku." #: ../../../src/MenuCharacter.cpp:498 #, c-format msgid "Each level grants %d. " msgstr "" #: ../../../src/MenuCharacter.cpp:500 #, fuzzy, c-format msgid "Each point of Physical grants %d. " msgstr "Každý bod Fyzické Síly přidá +%d HP. Každý level se zvýší +%d HP" #: ../../../src/MenuCharacter.cpp:502 #, fuzzy, c-format msgid "Each point of Mental grants %d. " msgstr "Každý bod Mentální síly přidá +%d MP. Každý level se zvýší +%d MP" #: ../../../src/MenuCharacter.cpp:504 #, fuzzy, c-format msgid "Each point of Offense grants %d. " msgstr "Každý bod Mentální síly přidá +%d MP. Každý level se zvýší +%d MP" #: ../../../src/MenuCharacter.cpp:506 #, fuzzy, c-format msgid "Each point of Defense grants %d. " msgstr "Každý bod Mentální síly přidá +%d MP. Každý level se zvýší +%d MP" #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "Mrtvý" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "Konec" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "Uložit a ukončit do menu?" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "" #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "" #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "" #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "" #: ../../../src/MenuInventory.cpp:228 #, c-format msgid "%d %s" msgstr "" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "Použíjte SHIFT k přesunu pouze jediné věci" #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "CTRL-kliknutí na předmět v inventáři k jeho prodání." #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "Tento předmět může být použit pouze z akčního menu" #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "Poznámky" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "Úkoly" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, fuzzy, c-format msgid "Not enough %s." msgstr "Nedostatek peněz." #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "Obchodovat" #: ../../../src/MenuPowers.cpp:463 msgid "Unspent skill points:" msgstr "Zbývající body schopnosti" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" #: ../../../src/MenuPowers.cpp:525 #, fuzzy, c-format msgid "Requires a %s" msgstr "Potřebuje Mentální sílu %d" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, c-format msgid "Requires Level %d" msgstr "Potřebuje Level %d" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, c-format msgid "Requires %d Skill Point" msgstr "Potřebuje %d Bodu Schopnosti" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "Kliknutím odemknete" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, c-format msgid "Requires Power: %s" msgstr "Potřebuje Schopnost: %s" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "Stojí %d MP" #: ../../../src/MenuPowers.cpp:625 #, c-format msgid "Costs %d HP" msgstr "Stojí %d HP" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "Obnovení: %d sekund" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "Sdílená Skrýš" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "Koupit Zpět" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "Obchodník" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "%d Štít" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "Už jsi transformovaný, nejdřív se transformuj zpět." #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "Dobrodruh" #: ../../../src/Utils.cpp:519 msgid "k" msgstr "" #~ msgid "Character Menu (C)" #~ msgstr "Postava (C)" #~ msgid "Inventory Menu (I)" #~ msgstr "Inventář (I)" #~ msgid "Power Menu (P)" #~ msgstr "Schopnosti (P)" #~ msgid "Log Menu (L)" #~ msgstr "Deník (L)" #~ msgid "Ticks of HP regen per minute. Each point of Physical grants +%d HP regen. Each level grants +%d HP regen" #~ msgstr "Regenerace HP za minutu. Každý bod Fyzické síly zvýší +%d HP regeneraci. Každý level se zvýší +%d HP regenerace." #~ msgid "Ticks of MP regen per minute. Each point of Mental grants +%d MP regen. Each level grants +%d MP regen" #~ msgstr "Regenerace MP za minutu. Každý bod Mentální síly zvýší +%d HP regeneraci. Každý level se zvýši +%d MP regenerace." #~ msgid "Each point of Offense grants +%d accuracy. Each level grants +%d accuracy" #~ msgstr "Každý bod Útoku přidá +%d k přesnosti. Každý level zvýší +%d přesnosti" #~ msgid "Each point of Defense grants +%d avoidance. Each level grants +%d avoidance" #~ msgstr "Každý bod Obrany zvýší schopnost vyhýbání se +%d. Každý level zvýší schopnost vyhýbání se +%d." #~ msgid "Requires a physical weapon" #~ msgstr "Potřebuje fyzickou zbraň" #~ msgid "Requires a mental weapon" #~ msgstr "Potřebuje psychickou zbraň" #~ msgid "Requires an offense weapon" #~ msgstr "Potřebuješ střelnou zbraň" flare-engine-0.19/mods/default/languages/engine.de.po000066400000000000000000000727631224717101500225460ustar00rootroot00000000000000# Copyright (C) 2011 Thomas Glamsch # This file is distributed under the same license as the Flare package. # Thomas 'CruzR' Glamsch , 2011. # Chris Oelmueller , 2012. # Stefan Beller , 2013 msgid "" msgstr "" "Project-Id-Version: 0.18\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2013-11-28 01:17+0100\n" "Last-Translator: Wuzzy \n" "Language-Team: \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 1.5.7\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "Glückwunsch, du hast Stufe %d erreicht!" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "Du kannst ein Attribut im Charaktermenü erhöhen." #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "" "Du wurdest besiegt. Game over! Drücke Enter, um zum Hauptmenü zurückzukehren." #: ../../../src/Avatar.cpp:634 msgid "You are defeated. Press Enter to continue." msgstr "Du wurdest besiegt. Drücke Eingabe zum fortfahren" #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "%d × %s entfernt." #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "%s entfernt." #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "Du erhältst %s." #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "Du erhältst %s ×%d." #: ../../../src/CampaignManager.cpp:168 #, c-format msgid "You receive %d %s." msgstr "Du erhältst %d %s." #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "Du erhältst %d EP." #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "TP wiederhergestellt." #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "MP wiederhergestellt." #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "TP und MP wiederhergestellt." #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "Negativwirkungen entfernt." #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "TP und MP wiederhergestellt, Negativwirkungen entfernt." #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "verfehlt" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "+%d TP" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "+%d MP" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "Unbekanntes Ziel" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "OK" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "Standard" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "Abbrechen" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "Grafik" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "Ton" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "Interface" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "Eingabe" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "Tastenbelegung" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "Mods" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "Zuweisen: " #: ../../../src/GameStateConfig.cpp:165 msgid "Reset ALL settings?" msgstr "ALLE Einstellungen zurücksetzen?" #: ../../../src/GameStateConfig.cpp:166 msgid "Use this resolution?" msgstr "Diese Auflösung verwenden?" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "Vollbildmodus" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "Maussteuerung" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "Schwebender Kampftext" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "Hardwareoberflächen" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "Doppel-Buffering" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "Joystick benutzen" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "Hochauflösende Texturen" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "Änderbarer Gamma-Wert" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "Animierter Untergrund" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "Zielen mit Maus" #: ../../../src/GameStateConfig.cpp:318 msgid "Do not use mouse" msgstr "Maus nicht benutzen" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "Framerate anzeigen" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "Schnelltasten anzeigen" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "Modus für Farbblinde" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "Musiklautstärke" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "Soundlautstärke" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "Gamma-Wert" #: ../../../src/GameStateConfig.cpp:377 msgid "Joystick Deadzone" msgstr "Joystick-Todeszone" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "Auflösung" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "Aktive Mods" #: ../../../src/GameStateConfig.cpp:412 msgid "Available Mods" msgstr "Verfügbare Mods" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "Joystick" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "Sprache" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 msgid "Disable for performance" msgstr "Für mehr Leistung deaktivieren" #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "Experimentell" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "Für tragbare Geräte" #: ../../../src/GameStateConfig.cpp:527 msgid "<< Disable" msgstr "<< Deaktivieren" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr "Aktivieren >>" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "Spielstand löschen" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "Diesen Spielstand löschen?" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "Zurück zum Menü" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "Speicherplatz wählen" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "Neues Spiel" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "Aktiviere einen »story mod«, um fortzufahren" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "Spiel laden" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "Spielwelt wird betreten …" #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "Gespeichertes Spiel wird geladen …" #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "Stufe %d %s" #: ../../../src/GameStateLoad.cpp:579 msgid "Permadeath" msgstr "Dauerhafter Tod?" #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "Leerer Speicherplatz" #: ../../../src/GameStateNew.cpp:62 msgid "Create" msgstr "Erstellen" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "Wähle dein Porträt" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "Wähle deinen Namen" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "Dauerhafter Tod?" #: ../../../src/GameStateNew.cpp:179 msgid "Choose a Class" msgstr "Wähle eine Klasse" #: ../../../src/GameStatePlay.cpp:99 msgid "Loading..." msgstr "Laden …" #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "Inventar ist voll." #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "Spiel starten" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "Aktiviere einen »core mod« zum Fortfahren" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "Einstellungen" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "Mitwirkende" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "Beenden" #: ../../../src/GameStateTitle.cpp:67 msgid "Flare Alpha v0.19" msgstr "Flare Alpha v0.19" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "Bestätigen" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "Hoch" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "Runter" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "Links" #: ../../../src/InputState.cpp:627 msgid "Right" msgstr "Rechts" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "Aktionsleiste 1" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "Aktionsleiste 2" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "Aktionsleiste 3" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "Aktionsleiste 4" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "Aktionsleiste 5" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "Aktionsleiste 6" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "Aktionsleiste 7" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "Aktionsleiste 8" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "Aktionsleiste 9" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "Aktionsleiste 0" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "Charakter" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "Inventar" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "Fähigkeiten" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "Protokoll" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "Haupt-Aktionstaste 1" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "Haupt-Aktionstaste 2" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "Strg" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "Umschalt" #: ../../../src/InputState.cpp:646 msgid "Delete" msgstr "Entf" #: ../../../src/InputState.cpp:647 #, fuzzy msgid "ActionBar Accept" msgstr "ActionBar annehmen" #: ../../../src/InputState.cpp:648 #, fuzzy msgid "ActionBar Left" msgstr "ActionBar links" #: ../../../src/InputState.cpp:649 #, fuzzy msgid "ActionBar Right" msgstr "ActionBar rechts" #: ../../../src/InputState.cpp:650 #, fuzzy msgid "ActionBar Use" msgstr "ActionBar benutzen" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "lMt" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "mMt" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "rMt" #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "Mausrad auf" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "Mausrad ab" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "Maus-Zusatztaste 1" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "Maus-Zusatztaste 2" #: ../../../src/ItemManager.cpp:488 msgid "Low" msgstr "Niedrig" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "Normal" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "Hoch" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "Monumental" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "Stufe %d" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "Nahkampfschaden: %d-%d" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "Nahkampfschaden: %d" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "Fernkampfschaden: %d-%d" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "Fernkampfschaden: %d" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "Magieschaden: %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "Magieschaden: %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "Absorbieren: %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "Absorbieren: %d" #: ../../../src/ItemManager.cpp:554 #, c-format msgid "%d% Speed" msgstr "%d% Geschwindigkeit" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "Erhöht %s um %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "Verringert %s um %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "Benötigt %d Kraft" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "Benötigt %d Geist" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "Benötigt %d Angriff" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "Benötigt %d Verteidigung" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "Qualität: %s" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, c-format msgid "Buy Price: %d %s" msgstr "Kaufpreis: %d %s" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, c-format msgid "Buy Price: %d %s each" msgstr "Kaufpreis: je %d %s" #: ../../../src/ItemManager.cpp:643 #, c-format msgid "Sell Price: %d %s" msgstr "Verkaufspreis: %d %s" #: ../../../src/ItemManager.cpp:645 #, c-format msgid "Sell Price: %d %s each" msgstr "Verkaufspreis: je %d %s" #: ../../../src/ItemManager.cpp:655 msgid "Set: " msgstr "Set: " #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "%d Gegenstände: " #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "Name" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "Stufe" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "Kraft" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "Geist" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "Angriff" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "Verteidigung" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "verbleibende Punkte" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "Max. TP:" #: ../../../src/MenuCharacter.cpp:340 msgid "HP Regen:" msgstr "TP-Regeneration:" #: ../../../src/MenuCharacter.cpp:341 #, fuzzy msgid "Ticks of HP regen per minute. " msgstr "TP-Regenerierung pro Minute" #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "Max. MP:" #: ../../../src/MenuCharacter.cpp:352 msgid "MP Regen:" msgstr "MP-Regeneration:" #: ../../../src/MenuCharacter.cpp:353 #, fuzzy msgid "Ticks of MP regen per minute. " msgstr "MP-Regenerierung pro Minute" #: ../../../src/MenuCharacter.cpp:358 msgid "Accuracy:" msgstr "Genauigkeit:" #: ../../../src/MenuCharacter.cpp:364 msgid "Avoidance:" msgstr "Ausweichen:" #: ../../../src/MenuCharacter.cpp:370 msgid "Melee Damage:" msgstr "Nahkampfschaden:" #: ../../../src/MenuCharacter.cpp:380 msgid "Ranged Damage:" msgstr "Fernkampfschaden:" #: ../../../src/MenuCharacter.cpp:390 msgid "Mental Damage:" msgstr "Magieschaden:" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "Krit. Trefferchance:" #: ../../../src/MenuCharacter.cpp:406 msgid "Absorb:" msgstr "Absorbieren:" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "Gleichgewicht: " #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "" "Reduziert die Wahrscheinlichkeit, bei einem Treffer ins Taumeln zu geraten" #: ../../../src/MenuCharacter.cpp:422 msgid "Bonus XP: " msgstr "Bonus-EP: " #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "Erhöht die erhaltenen EP pro getötetem Gegner" #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "Bonus" #: ../../../src/MenuCharacter.cpp:429 #, c-format msgid "Increases the %s found per drop" msgstr "Erhöhte Chance auf %s" #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "Zusatzchance für Gegenstände: " #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "Finde mehr Gegenstände bei getöteten Gegnern." #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "Verborgenheit: " #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "Erhöht die Fähigkeit, sich unbemerkt zu bewegen" #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "EP: %d" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "Nächstes: %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "Kraft (K) erhöht Nahkampffertigkeiten und maximale TP." #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "Basis (%d), Bonus (%d)" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "Geist (G) erhöht die Fertigkeit für magische Waffen und maximale MP." #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "Angriff (A) erhöht die Fertigkeit für Fernkampfwaffen und Genauigkeit." #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "Verteidigung (V) erhöht die Rüstungskenntnis und Ausweichen." #: ../../../src/MenuCharacter.cpp:498 #, c-format msgid "Each level grants %d. " msgstr "Jedes Level gewährt %d." #: ../../../src/MenuCharacter.cpp:500 #, c-format msgid "Each point of Physical grants %d. " msgstr "Jeder Punkt in Körper gewährt %d." #: ../../../src/MenuCharacter.cpp:502 #, c-format msgid "Each point of Mental grants %d. " msgstr "Jeder Punkt in Geist gewährt %d." #: ../../../src/MenuCharacter.cpp:504 #, c-format msgid "Each point of Offense grants %d. " msgstr "Jeder Punkt in Angriff gewährt %d." #: ../../../src/MenuCharacter.cpp:506 #, c-format msgid "Each point of Defense grants %d. " msgstr "Jeder Punkt in Verteidigung gewährt %d." #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "Tot" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "%s Stufe %d" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "Beenden" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "Speichern und zum Hauptmenü?" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "%d%% an %s verloren." #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "%d%% an den gesamten EP verloren." #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "%d%% der EP der aktuellen Stufe verloren." #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "Verloren: %s." #: ../../../src/MenuInventory.cpp:228 #, c-format msgid "%d %s" msgstr "%d %s" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "Halte Umschalt gedrückt, um nur einen Gegenstand zu nehmen." #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "" "Halte Umschalt gedrückt und klicke auf einen deiner Gegenstände, um ihn zu " "verkaufen." #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "Dieser Gegenstand kann nur von der Aktionsleiste aus benutzt werden." #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "Aufzeichnungen" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "Aufgaben" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "EP: %d/%d" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, c-format msgid "Not enough %s." msgstr "Nicht genug %s." #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "Handeln" #: ../../../src/MenuPowers.cpp:463 msgid "Unspent skill points:" msgstr "Verfügbare Fertigkeitspunkte:" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" "\n" "Nächste Stufe:" #: ../../../src/MenuPowers.cpp:525 #, c-format msgid "Requires a %s" msgstr "Benötigt: %s" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "Benötigt %d Körper-Angriff" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "Benötigt %d Körper-Verteidigung" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "Benötigt %d Geist-Angriff" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "Benötigt %d Geist-Verteidigung" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, c-format msgid "Requires Level %d" msgstr "Benötigt Stufe %d" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, c-format msgid "Requires %d Skill Point" msgstr "Benötigt %d Fertigkeitspunkt" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "Zum Freischalten klicken" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, c-format msgid "Requires Power: %s" msgstr "Benötigt Fähigkeit: %s" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "Kostet %d MP" #: ../../../src/MenuPowers.cpp:625 #, c-format msgid "Costs %d HP" msgstr "Kostet %d TP" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "Abklingzeit: %d Sekunden" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "Gemeinsame Truhe" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "Rückkauf" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "Verkäufer" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "+%d Schild" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "Du bist bereits verwandelt, beende die Verwandlung zunächst." #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "Abenteurer" #: ../../../src/Utils.cpp:519 msgid "k" msgstr "k" #~ msgid "Character Menu (C)" #~ msgstr "Charakter (C)" #~ msgid "Inventory Menu (I)" #~ msgstr "Inventar (I)" #~ msgid "Power Menu (P)" #~ msgstr "Fähigkeiten (P)" #~ msgid "Log Menu (L)" #~ msgstr "Log (L)" #~ msgid "Each point of Physical grants +%d HP. Each level grants +%d HP" #~ msgstr "Jeder Punkt in Kraft erhöht TP um %d, jedes Level um weitere %d." #~ msgid "" #~ "Ticks of HP regen per minute. Each point of Physical grants +%d HP regen. " #~ "Each level grants +%d HP regen" #~ msgstr "" #~ "Pro Minute regenerierte TP. Jeder Punkt in Kraft erhöht TP-Regeneration " #~ "um %d, jede Stufe um weitere %d." #~ msgid "Each point of Mental grants +%d MP. Each level grants +%d MP" #~ msgstr "Jeder Punkt in Geist erhöht MP um %d, jede Stufe um weitere %d." #~ msgid "" #~ "Ticks of MP regen per minute. Each point of Mental grants +%d MP regen. " #~ "Each level grants +%d MP regen" #~ msgstr "" #~ "Pro Minute regenerierte MP. Jeder Punkt in Geist erhöht MP-Regeneration " #~ "um %d, jede Stufe um weitere %d." #~ msgid "" #~ "Each point of Offense grants +%d accuracy. Each level grants +%d accuracy" #~ msgstr "" #~ "Jeder Punkt in Angriff erhöht Genauigkeit um %d, jede Stufe um weitere %d." #~ msgid "" #~ "Each point of Defense grants +%d avoidance. Each level grants +%d " #~ "avoidance" #~ msgstr "" #~ "Jeder Punkt in Verteidigung erhöht Ausweichen um %d, jede Stufe um " #~ "weitere %d." #~ msgid "Requires a physical weapon" #~ msgstr "Benötigt eine physische Waffe" #~ msgid "Requires a mental weapon" #~ msgstr "Benötigt eine magische Waffe" #~ msgid "Requires an offense weapon" #~ msgstr "Benötigt eine Fernwaffe" #~ msgid "Flare" #~ msgstr "Flare" #~ msgid "Accuracy (vs lvl 5):" #~ msgstr "Genauigkeit (gegen V 5):" #~ msgid "Avoidance (vs lvl 5):" #~ msgstr "Ausweichen (gegen A 5):" #~ msgid "Unspent attribute points" #~ msgstr "Ungenutzte Attributpunkte" #~ msgid "Stats" #~ msgstr "Statistik" #~ msgid "Grand Master" #~ msgstr "Großmeister" #~ msgid "Master" #~ msgstr "Meister" #~ msgid "Warrior" #~ msgstr "Krieger" #~ msgid "Wizard" #~ msgstr "Zauberer" #~ msgid "Ranger" #~ msgstr "Waldläufer" #~ msgid "Paladin" #~ msgstr "Paladin" #~ msgid "Rogue" #~ msgstr "Schurke" #~ msgid "Knight" #~ msgstr "Ritter" #~ msgid "Shaman" #~ msgstr "Schamane" #~ msgid "Cleric" #~ msgstr "Priester" #~ msgid "Battle Mage" #~ msgstr "Kampfmagier" #~ msgid "Heavy Archer" #~ msgstr "Schwerer Bogenschütze" #~ msgid "You receive %d gold." #~ msgstr "Du erhältst %d Gold." #~ msgid "Press a key to assign: " #~ msgstr "Eine Taste zum Zuweisen drücken: " #~ msgid "Activate >>" #~ msgstr "Aktivieren >>" #~ msgid "Create Character" #~ msgstr "Charakter erstellen" #~ msgid "Main Hand" #~ msgstr "Waffenhand" #~ msgid "Body" #~ msgstr "Körper" #~ msgid "Off Hand" #~ msgstr "Schildhand" #~ msgid "Artifact" #~ msgstr "Artefakt" #~ msgid "Consumable" #~ msgstr "Verbrauchbar" #~ msgid "Gem" #~ msgstr "Edelstein" #~ msgid "Quest Item" #~ msgstr "Questgegenstand" #~ msgid "%d Gold" #~ msgstr "%d Gold" #~ msgid "Total HP" #~ msgstr "Gesamte TP" #~ msgid "Total MP" #~ msgstr "Gesamte MP" #~ msgid "vs. Def 5" #~ msgstr "ggn. V 5" #~ msgid "vs. Off 5" #~ msgstr "ggn. A 5" #~ msgid "Main Weapon" #~ msgstr "Hauptwaffe" #~ msgid "Ranged Weapon" #~ msgstr "Fernwaffe" #~ msgid "Crit Chance" #~ msgstr "Krit. Trefferchance" #~ msgid "Fire Resist" #~ msgstr "Feuerwiderst." #~ msgid "Ice Resist" #~ msgstr "Eiswiderst." #~ msgid "Each level grants +1 HP regen" #~ msgstr "Jedes Level erhöht TP-Regenerierung um 1" #~ msgid "Each level grants +2 MP" #~ msgstr "Jedes Level erhöht MP um 2" #~ msgid "Each level grants +1 MP regen" #~ msgstr "Jedes Level erhöht MP-Regenerierung um 1" #~ msgid "Each level grants +1 accuracy" #~ msgstr "Jedes Level erhöht Genauigkeit um 1" #~ msgid "Each level grants +1 avoidance" #~ msgstr "Jedes Level erhöht Ausweichen um 1" #~ msgid "Dagger Proficiency" #~ msgstr "Fertigkeit: Dolch" #~ msgid "Shortsword Proficiency" #~ msgstr "Fertigkeit: Kurzschwert" #~ msgid "Longsword Proficiency" #~ msgstr "Fertigkeit: Langschwert" #~ msgid "Greatsword Proficiency" #~ msgstr "Fertigkeit: Breitschwert" #~ msgid "Wand Proficiency" #~ msgstr "Fertigkeit: Zauberstab" #~ msgid "Rod Proficiency" #~ msgstr "Fertigkeit: Zauberrute" #~ msgid "Staff Proficiency" #~ msgstr "Fertigkeit: Stab" #~ msgid "Greatstaff Proficiency" #~ msgstr "Fertigkeit: Langstab" #~ msgid "Slingshot Proficiency" #~ msgstr "Fertigkeit: Schleuder" #~ msgid "Shortbow Proficiency" #~ msgstr "Fertigkeit: Kurzbogen" #~ msgid "Longbow Proficiency" #~ msgstr "Fertigkeit: Langbogen" #~ msgid "Greatbow Proficiency" #~ msgstr "Fertigkeit: Kompositbogen" #~ msgid "Light Armor Proficiency" #~ msgstr "Fertigkeit: Leichte Rüstung" #~ msgid "Light Shield Proficiency" #~ msgstr "Fertigkeit: Leichter Schild" #~ msgid "Heavy Armor Proficiency" #~ msgstr "Fertigkeit: Schwere Rüstung" #~ msgid "Heavy Shield Proficiency" #~ msgstr "Fertigkeit: Schwerer Schild" #~ msgid "Messages" #~ msgstr "Nachrichten" #~ msgid "Physical + Offense grants melee and ranged attacks" #~ msgstr "Physisch + Angriff erlaubt Nah- und Fernkampfattacken" #~ msgid "Physical + Defense grants melee protection" #~ msgstr "Physisch + Verteidigung bietet Nahkampfschutz" #~ msgid "Mental + Offense grants elemental spell attacks" #~ msgstr "Mental + Angriff erlaubt offensive Elementarzauber" #~ msgid "Mental + Defense grants healing and magical protection" #~ msgstr "Mental + Verteidigung erlaubt Heilen und magischen Schutz" flare-engine-0.19/mods/default/languages/engine.el.po000066400000000000000000000731641224717101500225520ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Γιάννης , 2012. # Μιχάλης Παπαγεωργίου , 2013. msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2013-11-25 13:11+0300\n" "Last-Translator: Μιχάλης Παπαγεωργίου \n" "Language-Team: Μιχάλης Παπαγεωργίου\n" "Language: el\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Virtaal 0.7.1\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "Συγχαρητήρια, έφτασες στο επίπεδο %d!" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "Μπορείς να αυξήσεις μία ικανότητα μέσω του Μενού Χαρακτήρα." #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "" "Ηττήθηκες. Τέλος παιχνιδιού! Πάτησε Enter για να επιστρέψεις στον Τίτλο." #: ../../../src/Avatar.cpp:634 msgid "You are defeated. Press Enter to continue." msgstr "Ηττήθηκες. Πάτησε Enter για να συνεχίσεις." #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "%d %s αφαιρέθηκαν." #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "Αφαιρέθηκε: %s" #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "Λαμβάνεις %s." #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "Λαμβάνεις %s x%d." #: ../../../src/CampaignManager.cpp:168 #, c-format msgid "You receive %d %s." msgstr "Λαμβάνεις %d %s." #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "Λαμβάνεις %d XP." #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "HP αναζωογονήθηκαν." #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "MP αναζωογονήθηκαν." #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "HP και MP αναζωογονήθηκαν." #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "Αρνητικές επιδράσεις αφαιρέθηκαν." #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "HP και MP αναζωογονήθηκαν, αρνητικές επιδράσεις αφαιρέθηκαν." #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "αστοχία" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "+%d HP" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "+%d MP" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "Άγνωστος προορισμός" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "Εντάξει" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "Προκαθορισμένα" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "Ακύρωση" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "Εικόνα" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "Ήχος" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "Περιβάλλον" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "Εισαγωγή" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "Πλήκτρα" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "Πρόσθετα" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "Ανάθεση: " #: ../../../src/GameStateConfig.cpp:165 msgid "Reset ALL settings?" msgstr "Επαναφορά ΌΛΩΝ των ρυθμίσεων;" #: ../../../src/GameStateConfig.cpp:166 msgid "Use this resolution?" msgstr "Χρήση αυτής της ανάλυσης;" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "Λειτουργία πλήρους οθόνης" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "Κίνηση ήρωα με ποντίκι" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "Προβολή κειμένου μάχης" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "Χρήση κάρτας γραφικών για επιφάνειες" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "Διπλή ενδιάμεση μνήμη" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "Χρήση χειριστηρίου" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "Υφές Υψηλής Ποιότητας" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "Επιτρέπετε η αλλαγή Φωτεινότητας" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "Κινούμενα πλακίδια" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "Σκόπευση με το ποντίκι" #: ../../../src/GameStateConfig.cpp:318 msgid "Do not use mouse" msgstr "Απενεργοποίηση του ποντικιού" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "Εμφάνιση καρέ ανά δευτερόλεπτο" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "Εμφάνιση Ετικετών Πλήκτρων" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "Ρύθμιση Δυσχρωματοψίας" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "Ένταση Μουσικής" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "Ένταση Ήχου" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "Φωτεινότητα" #: ../../../src/GameStateConfig.cpp:377 msgid "Joystick Deadzone" msgstr "Νεκρή Ζώνη Χειριστηρίου" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "Ανάλυση" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "Ενεργά Πρόσθετα" #: ../../../src/GameStateConfig.cpp:412 msgid "Available Mods" msgstr "Διαθέσιμα Πρόσθετα" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "Χειριστήριο" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "Γλώσσα" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 msgid "Disable for performance" msgstr "Απενεργοποίηση για καλύτερες επιδόσεις" #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "Πειραματικό" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "Για φορητές συσκευές" #: ../../../src/GameStateConfig.cpp:527 msgid "<< Disable" msgstr "<< Απενεργοποίηση" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr "Ενεργοποίηση >>" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "Διαγραφή" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "Διαγραφή παιχνιδιού;" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "Έξοδος προς Τίτλο" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "Επέλεξε μία Θέση" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "Νέο Παιχνίδι" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "Ενεργοποίησε ένα πρόσθετο με σενάριο για να συνεχίσεις" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "Φόρτωση Παιχνιδιού" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "Είσοδος στο παιχνίδι..." #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "Φόρτωση αποθηκευμένου παιχνιδιού..." #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "Επίπεδο %d %s" #: ../../../src/GameStateLoad.cpp:579 msgid "Permadeath" msgstr "Μόνιμος θάνατος" #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "Κενή Θέση" #: ../../../src/GameStateNew.cpp:62 msgid "Create" msgstr "Δημιουργία" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "Επιλογή Πορτραίτου" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "Επιλογή Ονόματος" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "Μόνιμος θάνατος;" #: ../../../src/GameStateNew.cpp:179 msgid "Choose a Class" msgstr "Επιλογή Κλάσης" #: ../../../src/GameStatePlay.cpp:99 msgid "Loading..." msgstr "Φόρτωση..." #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "Έχεις παραφορτωθεί." #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "Έναρξη Παιχνιδιού" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "Ενεργοποίησε ένα πρόσθετο πυρήνα για να συνεχίσεις" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "Ρυθμίσεις" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "Μνεία" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "Έξοδος" #: ../../../src/GameStateTitle.cpp:67 msgid "Flare Alpha v0.19" msgstr "" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "Αποδοχή" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "Πάνω" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "Κάτω" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "Αριστερά" #: ../../../src/InputState.cpp:627 msgid "Right" msgstr "Δεξιά" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "Μπάρα 1" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "Μπάρα 2" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "Μπάρα 3" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "Μπάρα 4" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "Μπάρα 5" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "Μπάρα 6" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "Μπάρα 7" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "Μπάρα 8" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "Μπάρα 9" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "Μπάρα 0" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "Χαρακτήρας" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "Εξοπλισμός" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "Δυνάμεις" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "Ημερολόγιο" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "Κύρια Ενέργεια 1" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "Κύρια Ενέργεια 2" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "Ctrl" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "Shift" #: ../../../src/InputState.cpp:646 msgid "Delete" msgstr "Διαγραφή" #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "Μπάρα Ενεργειών Αποδοχή" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "Μπάρα Ενεργειών Αριστερά" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "Μπάρα Ενεργειών Δεξιά" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "Μπάρα Ενεργειών Χρήση" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "ακπ" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "μκπ" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "δκπ" #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "Ροδέλα προς τα πάνω" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "Ροδέλα προς τα κάτω" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "εκπ1" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "εκπ2" #: ../../../src/ItemManager.cpp:488 msgid "Low" msgstr "Χαμηλή" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "Κανονική" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "Υψηλή" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "Επική" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "Επίπεδο %d" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "Ζημιά εξ επαφής: %d-%d" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "Ζημιά εξ επαφής: %d" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "Ζημιά από απόσταση: %d-%d" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "Ζημιά από απόσταση: %d" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "Πνευματική ζημιά: %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "Πνευματική ζημιά: %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "Απορρόφηση: %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "Απορρόφηση: %d" #: ../../../src/ItemManager.cpp:554 #, c-format msgid "%d% Speed" msgstr "%d% Ταχύτητα" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "Αυξάνει %s κατά %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "Μειώνει %s κατά %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "Χρειάζεται %d Πυγμή" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "Χρειάζεται %d Πνεύμα" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "Χρειάζεται %d Επιδεξιότητα" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "Χρειάζεται %d Άμυνα" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "Ποιότητα: %s" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, c-format msgid "Buy Price: %d %s" msgstr "Τιμή Αγοράς: %d %s" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, c-format msgid "Buy Price: %d %s each" msgstr "Τιμή Αγοράς: %d %s έκαστο" #: ../../../src/ItemManager.cpp:643 #, c-format msgid "Sell Price: %d %s" msgstr "Τιμή Πώλησης: %d %s" #: ../../../src/ItemManager.cpp:645 #, c-format msgid "Sell Price: %d %s each" msgstr "Τιμή Πώλησης: %d %s έκαστο" #: ../../../src/ItemManager.cpp:655 msgid "Set: " msgstr "Σύνολο: " #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "%d αντικείμενα: " #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "Όνομα" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "Επίπεδο" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "Πυγμή" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "Πνεύμα" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "Επιδεξιότητα" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "Άμυνα" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "εναπομείναντες πόντοι" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "Μέγιστα ΗΡ (πόντοι ζωής):" #: ../../../src/MenuCharacter.cpp:340 msgid "HP Regen:" msgstr "Αναγέννηση ΗΡ:" #: ../../../src/MenuCharacter.cpp:341 msgid "Ticks of HP regen per minute. " msgstr "Επαναλήψεις αναγέννησης ΗΡ ανά λεπτό. " #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "Μέγιστα ΜΡ (πόντοι μαγείας):" #: ../../../src/MenuCharacter.cpp:352 msgid "MP Regen:" msgstr "Αναγέννηση ΜΡ:" #: ../../../src/MenuCharacter.cpp:353 msgid "Ticks of MP regen per minute. " msgstr "Επαναλήψεις αναγέννησης ΜΡ ανά λεπτό. " #: ../../../src/MenuCharacter.cpp:358 msgid "Accuracy:" msgstr "Σημάδι:" #: ../../../src/MenuCharacter.cpp:364 msgid "Avoidance:" msgstr "Αποφυγή:" #: ../../../src/MenuCharacter.cpp:370 msgid "Melee Damage:" msgstr "Ζημιά εξ επαφής:" #: ../../../src/MenuCharacter.cpp:380 msgid "Ranged Damage:" msgstr "Ζημιά από απόσταση:" #: ../../../src/MenuCharacter.cpp:390 msgid "Mental Damage:" msgstr "Πνευματική ζημιά:" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "Πιθανότητα Κρίσιμου Χτυπήματος:" #: ../../../src/MenuCharacter.cpp:406 msgid "Absorb:" msgstr "Απορρόφηση:" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "Ισορροπία: " #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "Μειώνει το ενδεχόμενο να παραπατήσεις όταν χτυπηθείς" #: ../../../src/MenuCharacter.cpp:422 msgid "Bonus XP: " msgstr "Μπόνους ΧΡ: " #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "Αυξάνει τα ΧΡ που αποκτάς ανά σκοτωμό" #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "Μπόνους" #: ../../../src/MenuCharacter.cpp:429 #, c-format msgid "Increases the %s found per drop" msgstr "Αυξάνει τα %s που βρίσκεις στα πτώματα" #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "Μπόνους Εύρεσης Αντικειμένων: " #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "Αυξάνει το ενδεχόμενο να ρίξει ένα αντικείμενο ο εχθρός όταν σκοτωθεί" #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "Δολιότητα: " #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "Αυξάνει την ικανότητά σου να περνάς απαρατήρητος" #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "XP (Πόντοι Εμπειρίας): %d" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "Επόμενο: %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "Η Πυγμή (Π) αυξάνει την εξοικείωση με κοντινά όπλα και τα συνολικά ΗΡ." #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "βάση (%d), μπόνους (%d)" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "" "Το Πνεύμα (Μ) αυξάνει την εξοικείωση με τα πνευματικά όπλα και τα συνολικά " "ΜΡ." #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "" "Η Επιδεξιότητα (Ε) αυξάνει την εξοικείωση με μακρινά όπλα και το σημάδι." #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "Η Άμυνα (Α) αυξάνει την εξοικείωση με πανοπλίες και την αποφυγή." #: ../../../src/MenuCharacter.cpp:498 #, c-format msgid "Each level grants %d. " msgstr "Κάθε επίπεδο παρέχει %d. " #: ../../../src/MenuCharacter.cpp:500 #, c-format msgid "Each point of Physical grants %d. " msgstr "Κάθε πόντος Πυγμής παρέχει %d. " #: ../../../src/MenuCharacter.cpp:502 #, c-format msgid "Each point of Mental grants %d. " msgstr "Κάθε πόντος Πνεύματος παρέχει %d. " #: ../../../src/MenuCharacter.cpp:504 #, c-format msgid "Each point of Offense grants %d. " msgstr "Κάθε πόντος Επιδεξιότητας παρέχει %d. " #: ../../../src/MenuCharacter.cpp:506 #, c-format msgid "Each point of Defense grants %d. " msgstr "Κάθε πόντος Άμυνας παρέχει %d. " #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "Νεκρός" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "%s επιπέδου %d" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "Έξοδος" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "Αποθήκευση και έξοδος;" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "Έχασες %d%% από τα %s. " #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "Έχασες %d%% του συνολικού XP. " #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "Έχασες %d%% του XP αυτού του επιπέδου. " #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "Έχασες %s." #: ../../../src/MenuInventory.cpp:228 #, c-format msgid "%d %s" msgstr "%d %s" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "Πάτα το SHIFT για να μετακινήσεις μόνο ένα αντικείμενο." #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "" "CTRL-κλικ ποντικιού σε ένα αντικείμενο που κουβαλάς για να το πουλήσεις." #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "" "Αυτό το αντικείμενο μπορεί να χρησιμοποιηθεί μόνο από την μπάρα ενεργειών." #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "Σημειώσεις" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "Αποστολές" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "XP: %d/%d" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, c-format msgid "Not enough %s." msgstr "Έλλειψη από %s." #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "Εμπόριο" #: ../../../src/MenuPowers.cpp:463 msgid "Unspent skill points:" msgstr "Εναπομείναντες πόντοι ικανότητας:" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" "\n" "Επόμενο Επίπεδο:" #: ../../../src/MenuPowers.cpp:525 #, c-format msgid "Requires a %s" msgstr "Χρειάζεται ένα %s" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "Χρειάζεται %d Υλική Επίθεση" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "Χρειάζεται %d Υλική Άμυνα" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "Χρειάζεται %d Πνευματική Επίθεση" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "Χρειάζεται %d Πνευματική Άμυνα" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, c-format msgid "Requires Level %d" msgstr "Χρειάζεται Επίπεδο %d" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, c-format msgid "Requires %d Skill Point" msgstr "Χρειάζεται %d Πόντο Ικανότητας" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "Κάντε κλικ για Ξεκλείδωμα" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, c-format msgid "Requires Power: %s" msgstr "Χρειάζεται Δύναμη: %s" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "Κοστίζει %d MP" #: ../../../src/MenuPowers.cpp:625 #, c-format msgid "Costs %d HP" msgstr "Κοστίζει %d ΗP" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "Επανάκτηση: %d δευτερόλεπτα" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "Κοινόχρηστη Αποθήκη" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "Επαναγορά" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "Πωλητής" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "+%d Άμυνα" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "Έχεις ήδη μεταμορφωθεί, απομεταμορφώσου πρώτα." #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "Τυχοδιώκτης" #: ../../../src/Utils.cpp:519 msgid "k" msgstr "κ" #~ msgid "Character Menu (C)" #~ msgstr "Μενού Χαρακτήρα (C)" #~ msgid "Power Menu (P)" #~ msgstr "Μενού Δυνάμεων (P)" #~ msgid "Log Menu (L)" #~ msgstr "Μενού Ημερολογίου (L)" #, fuzzy #~ msgid "Stats" #~ msgstr "Στατιστικά" #~ msgid "Warrior" #~ msgstr "Πολεμιστής" #~ msgid "Wizard" #~ msgstr "Μάγος" #~ msgid "Knight" #~ msgstr "Ιππότης" #~ msgid "Shaman" #~ msgstr "Σαμάνος" #~ msgid "Cleric" #~ msgstr "Κληρικός" #~ msgid "Battle Mage" #~ msgstr "Μαχόμενος Μάγος" #~ msgid "Heavy Archer" #~ msgstr "Βαριά Οπλισμένος Τοξότης" #~ msgid "You receive %d gold." #~ msgstr "Λαμβάνετε %d χρυσάφι." #~ msgid "Press a key to assign: " #~ msgstr "Πατήστε ένα πλήκτρο για ανάθεση:" #~ msgid "Activate >>" #~ msgstr "Ενεργοποίηση >>" #~ msgid "Create Character" #~ msgstr "Δημιουργία Χαρακτήρα" #~ msgid "Main Hand" #~ msgstr "Κύριο Χέρι" #~ msgid "Body" #~ msgstr "Σώμα" #~ msgid "Off Hand" #~ msgstr "Εκτός Χεριού" #~ msgid "Quest Item" #~ msgstr "Αντικείμενο Αποστολής" #~ msgid "%d Gold" #~ msgstr "%d Χρυσάφι" #, fuzzy #~ msgid "Total HP" #~ msgstr "Συνολική Ζωη" #, fuzzy #~ msgid "Total MP" #~ msgstr "Συνολική Ζωη" #~ msgid "Main Weapon" #~ msgstr "Κύριο Όπλο" #~ msgid "Wand Proficiency" #~ msgstr "Ικανότητα Ράβδου" #~ msgid "Slingshot Proficiency" #~ msgstr "Ικανότητα Σφεντόνας" #~ msgid "Light Armor Proficiency" #~ msgstr "Ικανότητα Ελαφριάς Πανοπλίας" #~ msgid "Light Shield Proficiency" #~ msgstr "Ικανότητα Ελαφριάς Ασπίδας" #~ msgid "Heavy Armor Proficiency" #~ msgstr "Ικανότητα Βαρεάς Πανοπλίας" #~ msgid "Heavy Shield Proficiency" #~ msgstr "Ικανότητα Βαρεάς Ασπίδας" #~ msgid "Messages" #~ msgstr "Μηνύματα" flare-engine-0.19/mods/default/languages/engine.es.po000066400000000000000000000615361224717101500225610ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: Flare v0.18\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2013-03-17 20:57+0100\n" "Last-Translator: \n" "Language-Team: \n" "Language: Español\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.5.4\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "Felicidades, has alcanzado el nivel %d!" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "Usted puede aumentar un atributo a través del Menú de Personaje." #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "Usted está derrotado. Se acabó el juego! Pulse Enter para salir al Título." #: ../../../src/Avatar.cpp:634 #, fuzzy msgid "You are defeated. Press Enter to continue." msgstr "Usted está derrotado. Pierde la mitad de su %s. Pulse Intro para continuar." #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "" #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "" #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "Recibe %s." #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "Recibe %s x%d." #: ../../../src/CampaignManager.cpp:168 #, c-format msgid "You receive %d %s." msgstr "Recibe %d %s." #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "Recibe %d XP." #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "Restaurado PV" #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "Restaurado PM" #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "Restaurados PV y PM" #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "Efectos negativos removidos." #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "Restaurados PV y PM, efectos negativos removidos" #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "Falla" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "+%d PV" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "+%d PM" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "Destino desconocido" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "ACEPTAR" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "Por defecto" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "Cancelar" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "Vídeo" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "Audio" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "Interfaz" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "Entrada" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "Teclas" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "Mods" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "Asignar:" #: ../../../src/GameStateConfig.cpp:165 msgid "Reset ALL settings?" msgstr "¿Restablecer TODOS los ajustes?" #: ../../../src/GameStateConfig.cpp:166 msgid "Use this resolution?" msgstr "¿Usar esta resolución?" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "Modo Pantalla Completa" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "Mover héroe a través del ratón" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "Mostrar texto de combate" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "Superficies de hardware" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "Buffering doble" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "Usar control de mando" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "Texturas de Alta Calidad" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "Permitir cambiar gama" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "Cuadros animados" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "Ratón para apuntar" #: ../../../src/GameStateConfig.cpp:318 #, fuzzy msgid "Do not use mouse" msgstr "Mover héroe a través del ratón" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "Mostrar FPS" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "Volumen de Música" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "Volumen de Sonido" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "Gama" #: ../../../src/GameStateConfig.cpp:377 #, fuzzy msgid "Joystick Deadzone" msgstr "Control de mando" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "Resolución" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "Mods Activos" #: ../../../src/GameStateConfig.cpp:412 msgid "Available Mods" msgstr "Mods Disponibles" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "Control de mando" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "Idioma" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 msgid "Disable for performance" msgstr "Desactivar para rendimiento" #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "Experimental" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "" #: ../../../src/GameStateConfig.cpp:527 msgid "<< Disable" msgstr "<< Inhabilitar" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr "Habilitar >>" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "Eliminar" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "¿Eliminar este guardado?" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "Salir al Título" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "Elija una ranura" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "Nuevo Juego" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "Habilitar un mod historia para continuar" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "Cargar Juego" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "Entrando en mundo del juego..." #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "Cargando partida guardada..." #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "Nivel %d %s" #: ../../../src/GameStateLoad.cpp:579 #, fuzzy msgid "Permadeath" msgstr "¿Muerte permanente?" #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "Ranura vacía" #: ../../../src/GameStateNew.cpp:62 msgid "Create" msgstr "Crear" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "Elija un Retrato" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "Elija un Nombre" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "¿Muerte permanente?" #: ../../../src/GameStateNew.cpp:179 msgid "Choose a Class" msgstr "Elija una Clase" #: ../../../src/GameStatePlay.cpp:99 msgid "Loading..." msgstr "Cargando..." #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "El inventario esta completo." #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "Jugar" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "Habilitar un mod núcleo para continuar" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "Configuración" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "Salir del juego" #: ../../../src/GameStateTitle.cpp:67 #, fuzzy msgid "Flare Alpha v0.19" msgstr "Flare v0.18" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "Aceptar" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "Arriba" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "Abajo" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "Izquierda" #: ../../../src/InputState.cpp:627 msgid "Right" msgstr "Derecha" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "Bar1" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "Bar2" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "Bar3" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "Bar4" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "Bar5" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "Bar6" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "Bar7" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "Bar8" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "Bar9" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "Bar0" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "Personaje" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "Inventario" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "Poderes" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "Registro" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "Principal1" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "Principal2" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "Ctrl" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "Shift" #: ../../../src/InputState.cpp:646 msgid "Delete" msgstr "Borrar" #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "lmb" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "mmb" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "rmb" #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "Rueda arriba" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "Rueda abajo" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "mbx1" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "mbx2" #: ../../../src/ItemManager.cpp:488 #, fuzzy msgid "Low" msgstr "Registro" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "Nivel %d" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "Daño cuerpo a cuerpo: %d-%d" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "Melee damage: %d" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "Daño a distancia: %d-%d" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "Daño a distancia: %d" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "Daño mental: %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "Daño mental: %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "Absorber: %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "Absorber: %d" #: ../../../src/ItemManager.cpp:554 #, fuzzy, c-format msgid "%d% Speed" msgstr "%d\\% Velocidad" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "Aumenta %s por %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "Disminuye %s por %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "Requiere físico %d" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "Requiere Mental %d" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "Requiere Ofensiva %d" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "Requiere Defensa %d" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, c-format msgid "Buy Price: %d %s" msgstr "Precio de Compra: %d %s" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, c-format msgid "Buy Price: %d %s each" msgstr "Precio de Compra: %d %s cada" #: ../../../src/ItemManager.cpp:643 #, c-format msgid "Sell Price: %d %s" msgstr "Precio de Venta: %d %s" #: ../../../src/ItemManager.cpp:645 #, c-format msgid "Sell Price: %d %s each" msgstr "Precio de Venta: %d %s cada" #: ../../../src/ItemManager.cpp:655 msgid "Set: " msgstr "Conjunto:" #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "%d artículos: " #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "Nombre" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "Nivel" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "Físico" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "Mental" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "Ofensa" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "Defensa" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "puntos restantes" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "PV Máximo:" #: ../../../src/MenuCharacter.cpp:340 msgid "HP Regen:" msgstr "Regeneración de PV:" #: ../../../src/MenuCharacter.cpp:341 msgid "Ticks of HP regen per minute. " msgstr "" #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "PM Máximo:" #: ../../../src/MenuCharacter.cpp:352 msgid "MP Regen:" msgstr "Regeneración de PM:" #: ../../../src/MenuCharacter.cpp:353 msgid "Ticks of MP regen per minute. " msgstr "" #: ../../../src/MenuCharacter.cpp:358 msgid "Accuracy:" msgstr "Precisión:" #: ../../../src/MenuCharacter.cpp:364 msgid "Avoidance:" msgstr "Evitación:" #: ../../../src/MenuCharacter.cpp:370 msgid "Melee Damage:" msgstr "Daño Cuerpo a Cuerpo :" #: ../../../src/MenuCharacter.cpp:380 msgid "Ranged Damage:" msgstr "Daño a Distancia:" #: ../../../src/MenuCharacter.cpp:390 msgid "Mental Damage:" msgstr "Daño Mental:" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "Crítico:" #: ../../../src/MenuCharacter.cpp:406 msgid "Absorb:" msgstr "Absorber:" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "Equilibrio: " #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "Reduce la probabilidad de tropezar cuando es golpeado" #: ../../../src/MenuCharacter.cpp:422 #, fuzzy msgid "Bonus XP: " msgstr "Bonus" #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "Aumenta la experiencia ganada por matar" #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "Bonus" #: ../../../src/MenuCharacter.cpp:429 #, c-format msgid "Increases the %s found per drop" msgstr "Aumenta el %s encontrado por gota" #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "Punto Bonus Buscar: " #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "Aumenta la probabilidad de que un enemigo suelte un objeto cuando muera" #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "Sigilo: " #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "Aumenta la capacidad de moverse sin ser detectado" #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "Experiencia: %d" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "Siguiente: %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "Física (P) aumenta la habilidad cuerpo a cuerpo arma y PV total." #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "base (%d), bonus (%d)" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "Mental (M) aumenta la capacidad de arma mental y PM total." #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "Ofensa (O) aumenta la capacidad del rango de arma largo alcance y su precisión." #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "Defensa (D) aumenta la capacidad de armadura y la elusión." #: ../../../src/MenuCharacter.cpp:498 #, c-format msgid "Each level grants %d. " msgstr "" #: ../../../src/MenuCharacter.cpp:500 #, fuzzy, c-format msgid "Each point of Physical grants %d. " msgstr "Cada punto de subvenciones físicas +%d PV. Cada nivel de subvenciones +%d PV" #: ../../../src/MenuCharacter.cpp:502 #, fuzzy, c-format msgid "Each point of Mental grants %d. " msgstr "Cada punto de subvenciones Mental +%d PM. Cada nivel de subvenciones +%d PM" #: ../../../src/MenuCharacter.cpp:504 #, fuzzy, c-format msgid "Each point of Offense grants %d. " msgstr "Cada punto de subvenciones Mental +%d PM. Cada nivel de subvenciones +%d PM" #: ../../../src/MenuCharacter.cpp:506 #, fuzzy, c-format msgid "Each point of Defense grants %d. " msgstr "Cada punto de subvenciones Mental +%d PM. Cada nivel de subvenciones +%d PM" #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "Muerto" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "%s nivel%d" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "Salir" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "¿Guardar y salir al título?" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "" #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "" #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "" #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "" #: ../../../src/MenuInventory.cpp:228 #, c-format msgid "%d %s" msgstr "%d %s" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "Usar SHIFT para mover un solo artículo." #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "CTRL-clic en un bulto que se lleve para venderlo." #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "Este elemento sólo se puede utilizar en la barra de acción." #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "Notas" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "Misiones" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "Experiencia: %d/%d" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, fuzzy, c-format msgid "Not enough %s." msgstr "No hay suficiente dinero." #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "" #: ../../../src/MenuPowers.cpp:463 msgid "Unspent skill points:" msgstr "Puntos de habilidad no utilizados:" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" #: ../../../src/MenuPowers.cpp:525 #, fuzzy, c-format msgid "Requires a %s" msgstr "Requiere Mental %d" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "Requiere Ofensa Física %d" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "Requiere Defensa Física %d" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "Requiere Ofensiva Mental %d" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "Requiere Defensa Mental %d" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, c-format msgid "Requires Level %d" msgstr "Necesitas ser de Nivel %d" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, c-format msgid "Requires %d Skill Point" msgstr "Requiere %d Punto de Habilidad" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "Clic para desbloquear" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, c-format msgid "Requires Power: %s" msgstr "Requiere Poder: %s" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "Costos %d PM" #: ../../../src/MenuPowers.cpp:625 #, c-format msgid "Costs %d HP" msgstr "Costos %d HP" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "Reutilización: %d seconds" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "Esconder compartido" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "Recompra" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "Vendedor" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "+%d Escudo" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "Usted ya está transformado, destransformase primero." #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "Aventurero" #: ../../../src/Utils.cpp:519 #, fuzzy msgid "k" msgstr "Aceptar" #~ msgid "Character Menu (C)" #~ msgstr "Menú de Personaje (C)" #~ msgid "Inventory Menu (I)" #~ msgstr "Menu de Inventario (I)" #~ msgid "Power Menu (P)" #~ msgstr "Menú de Poder (P)" #~ msgid "Log Menu (L)" #~ msgstr "Menú de Registro (L)" #~ msgid "Ticks of HP regen per minute. Each point of Physical grants +%d HP regen. Each level grants +%d HP regen" #~ msgstr "Ticks de regeneración de PV por minuto. Cada punto de subvenciones físicas +%d PV de regeneración. Cada nivel de subvenciones +%d PV de regeneración" #~ msgid "Ticks of MP regen per minute. Each point of Mental grants +%d MP regen. Each level grants +%d MP regen" #~ msgstr "Ticks de regeneración de PM por minuto. Cada punto de subvenciones Mental +%d PM de regeneración. Cada nivel de subvenciones +%d PM de regeneración" #~ msgid "Each point of Offense grants +%d accuracy. Each level grants +%d accuracy" #~ msgstr "Cada punto de subvenciones Ofensa +%d precisión. Cada nivel de subvenciones+%d precisión" #~ msgid "Each point of Defense grants +%d avoidance. Each level grants +%d avoidance" #~ msgstr "Cada punto de subvenciones Defensa +%d evitación. Cada nivel de subvenciones +%d evitación" #~ msgid "Requires a physical weapon" #~ msgstr "Requiere un arma física" #~ msgid "Requires a mental weapon" #~ msgstr "Requiere un arma mental" #~ msgid "Requires an offense weapon" #~ msgstr "Requiere un arma ofensiva" flare-engine-0.19/mods/default/languages/engine.fi.po000066400000000000000000000612231224717101500225410ustar00rootroot00000000000000# FLARE (Free/Libre Action RPG Engine) # Copyright (C) 2013 Clint Bellanger # This file is distributed under the same license as the FLARE package. # Timo Sievänen , 2012. msgid "" msgstr "" "Project-Id-Version: 0.18\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2013-03-25 22:07+0200\n" "Last-Translator: Timo Sievänen \n" "Language-Team: \n" "Language: Finnish\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "Onnittelut, olet päässyt tasolle %d!" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "Voit nostaa yhtä kyvyistäsi hahmovalikossa." #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "Sinut on nujerrettu, peli päättyi. Paina Enter poistuaksesi päävalikkoon." #: ../../../src/Avatar.cpp:634 #, fuzzy msgid "You are defeated. Press Enter to continue." msgstr "Kärsit tappion. Menetät puolet kullasta. Paina Enter jatkaaksesi." #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "" #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "" #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "Hallussasi on nyt %s." #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "Saat %s x%d" #: ../../../src/CampaignManager.cpp:168 #, c-format msgid "You receive %d %s." msgstr "Saat %d %s" #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "Saat %d kokemusta." #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "Osumapisteet palautuneet." #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "Mentaalipisteet palautuneet." #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "OP ja MP palautuneet." #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "Haitalliset vaikutukset poistuneet." #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "OP ja MP palautuneet ja haitalliset vaikutukset poistuneet." #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "ohi" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "+%d OP" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "+%d MP" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "Tuntematon määränpää" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "OK" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "Oletukset" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "Peru" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "Video" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "Audio" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "Käyttöliittymä" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "Ohjaus" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "Näppäimet" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "Modit" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "Valinta: " #: ../../../src/GameStateConfig.cpp:165 msgid "Reset ALL settings?" msgstr "Palauta KAIKKI asetukset?" #: ../../../src/GameStateConfig.cpp:166 msgid "Use this resolution?" msgstr "Käytä tätä kuvakokoa?" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "Täysi ruutu" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "Liikuta sankaria hiirellä" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "Näytä taisteluteksti" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "Hardware surfaces" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "Kaksoispuskurointi" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "Käytä peliohjainta" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "Korkeatasoiset tekstuurit" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "Salli gamma-muutokset" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "Animoidut tiilet" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "Hiiritähtäys" #: ../../../src/GameStateConfig.cpp:318 #, fuzzy msgid "Do not use mouse" msgstr "Liikuta sankaria hiirellä" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "Näytä päivitystaso (FPS)" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "Musiikin voimakkuus" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "äänenvoimakkuus" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "Gamma" #: ../../../src/GameStateConfig.cpp:377 #, fuzzy msgid "Joystick Deadzone" msgstr "Peliohjain" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "Kuvakoko" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "Käytössäolevat modit" #: ../../../src/GameStateConfig.cpp:412 msgid "Available Mods" msgstr "Saatavilla olevat modit" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "Peliohjain" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "Kieli" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 msgid "Disable for performance" msgstr "Poiskytkeminen nopeuttaa peliä" #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "Kokeellinen" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "" #: ../../../src/GameStateConfig.cpp:527 msgid "<< Disable" msgstr "<< Poista käytöstä" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr "Ota käyttöön >>" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "Poista tallennus" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "Poistetaanko tallennus?" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "Palaa päävalikkoon" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "Valitse ura" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "Uusi peli" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "Salli tarinamodin jatkaa" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "Lataa peli" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "Saavutaan pelimaailmaan..." #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "Ladataan tallennettu peli..." #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "Taso %d %s" #: ../../../src/GameStateLoad.cpp:579 #, fuzzy msgid "Permadeath" msgstr "Lopullinen kuolema?" #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "Tyhjä ura" #: ../../../src/GameStateNew.cpp:62 msgid "Create" msgstr "Aloita" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "Valitse muotokuva" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "Valitse nimi" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "Lopullinen kuolema?" #: ../../../src/GameStateNew.cpp:179 msgid "Choose a Class" msgstr "Valitse luokka" #: ../../../src/GameStatePlay.cpp:99 msgid "Loading..." msgstr "Ladataan..." #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "Tavaraluettelo on täynnä." #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "Pelaa" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "Salli ydinmodin jatkaa" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "Asetukset" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "Lopeta peli" #: ../../../src/GameStateTitle.cpp:67 #, fuzzy msgid "Flare Alpha v0.19" msgstr "Flare Alpha v0.18" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "Hyväksy" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "Ylös" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "Alas" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "Vasen" #: ../../../src/InputState.cpp:627 msgid "Right" msgstr "Oikea" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "Hahmo" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "Tavaraluettelo" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "Voimat" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "Loki" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "Vaihto" #: ../../../src/InputState.cpp:646 msgid "Delete" msgstr "" #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "H-vasen" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "H-keski" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "H-oikea" #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "Pyörä ylös" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "Pyörä alas" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "" #: ../../../src/ItemManager.cpp:488 #, fuzzy msgid "Low" msgstr "Loki" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "Taso %d" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "Lähitaisteluvahinko: %d-%d" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "Lähitaisteluvahinko: %d" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "Etävahinko: %d-%d" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "Etävahinko: %d" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "Mentaalinen vahinko: %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "Mentaalinen vahinko: %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "Vaimennus: %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "Vaimennus: %d" #: ../../../src/ItemManager.cpp:554 #, fuzzy, c-format msgid "%d% Speed" msgstr "%d%% nopeus" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "%s nousee %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "%s laskee %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "Vaatii fyysisen kyvyn %d" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "Vaatii mentaalisen kyvyn %d" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "Vaatii hyökkäyskyvyn %d" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "Vaatii puolustuskyvyn %d" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, c-format msgid "Buy Price: %d %s" msgstr "Ostohinta: %d kultaa" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, c-format msgid "Buy Price: %d %s each" msgstr "Ostohinta: á %d kultaa" #: ../../../src/ItemManager.cpp:643 #, c-format msgid "Sell Price: %d %s" msgstr "Myyntihinta: %d kultaa" #: ../../../src/ItemManager.cpp:645 #, c-format msgid "Sell Price: %d %s each" msgstr "Myyntihinta: á %d kultaa" #: ../../../src/ItemManager.cpp:655 msgid "Set: " msgstr "" #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "%d esinettä: " #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "Nimi" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "Taso" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "Fyysinen" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "Mentaalinen" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "Hyökkäys" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "Puolustus" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "pistettä jäljellä" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "Maksimi OP:" #: ../../../src/MenuCharacter.cpp:340 msgid "HP Regen:" msgstr "Osumapisteiden uusiutuminen:" #: ../../../src/MenuCharacter.cpp:341 msgid "Ticks of HP regen per minute. " msgstr "" #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "Maksimi MP:" #: ../../../src/MenuCharacter.cpp:352 msgid "MP Regen:" msgstr "Mentaalipisteiden uusiutuminen:" #: ../../../src/MenuCharacter.cpp:353 msgid "Ticks of MP regen per minute. " msgstr "" #: ../../../src/MenuCharacter.cpp:358 msgid "Accuracy:" msgstr "Tarkkuus:" #: ../../../src/MenuCharacter.cpp:364 msgid "Avoidance:" msgstr "Välttely" #: ../../../src/MenuCharacter.cpp:370 msgid "Melee Damage:" msgstr "Lähitaisteluvahinko:" #: ../../../src/MenuCharacter.cpp:380 msgid "Ranged Damage:" msgstr "Etävahinko:" #: ../../../src/MenuCharacter.cpp:390 msgid "Mental Damage:" msgstr "Mentaalinen vahinko:" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "Kuritus:" #: ../../../src/MenuCharacter.cpp:406 msgid "Absorb:" msgstr "Vaimennus:" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "Tasapaino:" #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "Vähentää horjahduksen mahdollisuutta iskuja vastaanottaessa" #: ../../../src/MenuCharacter.cpp:422 msgid "Bonus XP: " msgstr "Lisäkokemus: " #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "Lisää kokemusta tapoista" #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "Lisä" #: ../../../src/MenuCharacter.cpp:429 #, c-format msgid "Increases the %s found per drop" msgstr "Voitetuista lisää %s" #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "Löytölisä: " #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "Lisää mahdollisuutta saada esine tapetulta viholliselta" #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "Häive: " #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "Parantaa kykyäsi liikkua huomaamatta" #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "Kokemus: %d" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "Seuraava: %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "Fyysinen (P) lisää lähitaisteluasekykyä ja kokonaisosumapisteitä." #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "perus (%d), lisä (%d)" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "Mentaalinen (M) lisää mentaaliasetaitoa ja MP:n kokonaismäärää." #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "Hyökkäys (O) lisää etäasetaitoa ja tarkkuutta." #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "Puolustus (D) lisää haarniskataitoa ja välttelymahdollisuuksia." #: ../../../src/MenuCharacter.cpp:498 #, c-format msgid "Each level grants %d. " msgstr "" #: ../../../src/MenuCharacter.cpp:500 #, fuzzy, c-format msgid "Each point of Physical grants %d. " msgstr "Jokainen fyysinen piste lisää +%d OP. Jokainen taso lisää +%d OP" #: ../../../src/MenuCharacter.cpp:502 #, fuzzy, c-format msgid "Each point of Mental grants %d. " msgstr "Jokainen mentaalipiste lisää +%d MP. Jokainen taso lisää +%d MP" #: ../../../src/MenuCharacter.cpp:504 #, fuzzy, c-format msgid "Each point of Offense grants %d. " msgstr "Jokainen mentaalipiste lisää +%d MP. Jokainen taso lisää +%d MP" #: ../../../src/MenuCharacter.cpp:506 #, fuzzy, c-format msgid "Each point of Defense grants %d. " msgstr "Jokainen mentaalipiste lisää +%d MP. Jokainen taso lisää +%d MP" #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "Kuollut" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "%s taso %d" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "Poistu" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "Tallenna ja poistu päävalikkoon?" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "" #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "" #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "" #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "" #: ../../../src/MenuInventory.cpp:228 #, c-format msgid "%d %s" msgstr "" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "Vaihtonäppäimellä siirrät vain yhden tavaran." #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "CTRL-napsauttamalla myyt kannetun tavaran." #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "Tätä tavaraa voit käyttää vain toimintapalkista." #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "Muistiinpanot" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "Etsinnät" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "Kokemus: %d/%d" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, fuzzy, c-format msgid "Not enough %s." msgstr "Rahat eivät riitä." #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "Tee kaupat" #: ../../../src/MenuPowers.cpp:463 msgid "Unspent skill points:" msgstr "Käyttämättömät kykypisteet" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" #: ../../../src/MenuPowers.cpp:525 #, fuzzy, c-format msgid "Requires a %s" msgstr "Vaatii mentaalisen kyvyn %d" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "Vaatii fyysisen hyökkäyskyvyn %d" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "Vaatii fyysisen puolustuskyvyn %d" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "Vaatii mentaalisen hyökkäyskyvyn %d" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "Vaatii mentaalisen puolustuskyvyn %d" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, c-format msgid "Requires Level %d" msgstr "Vaatii tason %d" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, c-format msgid "Requires %d Skill Point" msgstr "Vaatii %d taitopisteitä" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "Napsauta avataksesi" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, c-format msgid "Requires Power: %s" msgstr "Vaatii voiman: %s" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "Kustannus %d MP" #: ../../../src/MenuPowers.cpp:625 #, c-format msgid "Costs %d HP" msgstr "Kustannus %d OP" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "Jäähtyminen: %d sekuntia" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "Jaettu kätkö" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "Takaisinosto" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "Kauppias" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "+%d kilpi" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "Olet jo muuntunut, palaa ensin entisellesi." #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "Seikkailija" #: ../../../src/Utils.cpp:519 #, fuzzy msgid "k" msgstr "Ok" #~ msgid "Character Menu (C)" #~ msgstr "Hahmovalikko (C)" #~ msgid "Inventory Menu (I)" #~ msgstr "Tavaraluettelo (I)" #~ msgid "Power Menu (P)" #~ msgstr "Voimavalikko (P)" #~ msgid "Log Menu (L)" #~ msgstr "Lokivalikko (L)" #~ msgid "Ticks of HP regen per minute. Each point of Physical grants +%d HP regen. Each level grants +%d HP regen" #~ msgstr "Osumapisteiden lisäys minuuttia kohden. Jokainen fyysinen piste lisää uusiutumiseen +%d OP. Jokainen taso lisää uusiutumiseen +%d OP" #~ msgid "Ticks of MP regen per minute. Each point of Mental grants +%d MP regen. Each level grants +%d MP regen" #~ msgstr "MP:n lisäys minuuttia kohden. Jokainen mentaalipiste lisää uusiutumiseen +%d MP. Jokainen taso lisää uusiutumiseen +%d MP" #~ msgid "Each point of Offense grants +%d accuracy. Each level grants +%d accuracy" #~ msgstr "Jokainen hyökkäyspiste lisää +%d tarkkuuteen. Jokainen taso lisää +%d tarkkuuteen" #~ msgid "Each point of Defense grants +%d avoidance. Each level grants +%d avoidance" #~ msgstr "Jokainen puolustuspiste lisää +%d välttelyyn. Jokainen taso lisää +%d välttelyyn" #~ msgid "Requires a physical weapon" #~ msgstr "Vaatii fyysisen aseen" #~ msgid "Requires a mental weapon" #~ msgstr "Vaatii mentaalisen aseen" #~ msgid "Requires an offense weapon" #~ msgstr "Vaatii hyökkäysaseen" flare-engine-0.19/mods/default/languages/engine.fr.po000066400000000000000000000635251224717101500225610ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) 2011 Clint Bellanger # This file is distributed under the same license as the FLARE package. # Christoph J. Thompson , 2013 # Quentin 'acieroid' Stievenart , 2011 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2012-10-15 HO:MI+ZONE\n" "Last-Translator: Nubux\n" "Language-Team:\n" "Language:French \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "Félicitations, vous avez atteint le niveau %d !" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "Vous pouvez améliorer un attribut via le menu Personnage." #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "Vous êtes vaincu. Votre personnage est mort ! Pressez Entrée pour revenir au menu." #: ../../../src/Avatar.cpp:634 #, fuzzy msgid "You are defeated. Press Enter to continue." msgstr "Vous êtes vaincu. Vous perdez la moitié de votre %s. Appuyez sur Entrée pour continuer." #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "" #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "" #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "Vous recevez %s." #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "Vous recevez %s x%d." #: ../../../src/CampaignManager.cpp:168 #, c-format msgid "You receive %d %s." msgstr "Vous recevez %d %s." #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "Vous recevez %d points d'expérience." #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "PV restaurés." #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "PM restaurés." #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "PV et PM restaurés." #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "Effet négatif supprimé" #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "PV et PM restaurés, effet négatif supprimé" #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "manqué" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "+%d PV" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "+%d PM" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "Destination inconnue" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "OK" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "Par défaut" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "Annuler" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "Vidéo" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "Audio" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "Interface" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "Entrée" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "Commandes" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "Mods" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "Assigner" #: ../../../src/GameStateConfig.cpp:165 msgid "Reset ALL settings?" msgstr "Réinitaliser TOUS les réglages ?" #: ../../../src/GameStateConfig.cpp:166 msgid "Use this resolution?" msgstr "Utiliser cette résolution ?" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "Mode plein écran" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "Déplacement du héro à la souris" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "Afficher le texte des combats" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "Hardware surfaces" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "Double buffering" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "Utiliser une manette" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "Textures haute qualité" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "Régler le gamma" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "Décors animés" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "Visée à la souris" #: ../../../src/GameStateConfig.cpp:318 #, fuzzy msgid "Do not use mouse" msgstr "Déplacement du héro à la souris" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "Afficher les FPS" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "Volume de la musique" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "Volume des sons" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "Gamma" #: ../../../src/GameStateConfig.cpp:377 #, fuzzy msgid "Joystick Deadzone" msgstr "Manette" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "Résolution" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "Mods actifs" #: ../../../src/GameStateConfig.cpp:412 msgid "Available Mods" msgstr "Mods disponibles" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "Manette" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "Langues" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 msgid "Disable for performance" msgstr "Désactiver = meilleures perf." #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "Expérimental" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "" #: ../../../src/GameStateConfig.cpp:527 msgid "<< Disable" msgstr "<< Désactiver" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr "Activer >>" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "Suppr. sauvegarde" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "Supprimer cette sauvegarde ?" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "Retour au menu" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "Choisir une partie" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "Nouvelle partie" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "Activez un mod scenario pour continuer" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "Charger" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "Entrée dans le monde du jeu..." #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "Chargement d'une partie..." #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "Niveau %d %s" #: ../../../src/GameStateLoad.cpp:579 #, fuzzy msgid "Permadeath" msgstr "Mort permanente (permadeath) ? " #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "Pas de partie" #: ../../../src/GameStateNew.cpp:62 msgid "Create" msgstr "Créer" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "Choisissez un portrait" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "Choisissez un nom" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "Mort permanente (permadeath) ? " #: ../../../src/GameStateNew.cpp:179 msgid "Choose a Class" msgstr "Choisir une classe" #: ../../../src/GameStatePlay.cpp:99 msgid "Loading..." msgstr "Chargement..." #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "L'inventaire est complet." #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "Jouer" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "Activez un mod de base pour continuer" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "Configuration" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "Quitter" #: ../../../src/GameStateTitle.cpp:67 #, fuzzy msgid "Flare Alpha v0.19" msgstr "Flare Alpha v0.18" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "Accepter" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "Haut" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "Bas" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "Gauche" #: ../../../src/InputState.cpp:627 msgid "Right" msgstr "Droite" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "Emplacement 1" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "Emplacement 2" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "Emplacement 3" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "Emplacement 4" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "Emplacement 5" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "Emplacement 6" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "Emplacement 7" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "Emplacement 8" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "Emplacement 9" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "Emplacement 0" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "Personnage" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "Inventaire" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "Pouvoirs" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "Journal" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "1ere Main" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "2eme Main" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "Ctrl" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "Maj" #: ../../../src/InputState.cpp:646 msgid "Delete" msgstr "Suppr." #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "bgs" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "bms" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "bds" #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "Roulette haut" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "Roulette bas" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "" #: ../../../src/ItemManager.cpp:488 #, fuzzy msgid "Low" msgstr "Journal" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "Niveau %d" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "Dégâts en corps à corps : %d-%d" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "Dégâts en corps à corps : %d" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "Dégâts à distance : %d-%d" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "Dégâts à distance : %d" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "Dégâts mentaux : %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "Dégâts mentaux : %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "Absorbe : %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "Absorbe : %d" #: ../../../src/ItemManager.cpp:554 #, fuzzy, c-format msgid "%d% Speed" msgstr "%d%% Vitesse" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "Augmente %s de %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "Diminue %s de %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "Nécéssite %d de Physique" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "Nécessite %d de Mental" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "Nécessite %d d'Attaque" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "Nécessite %d de Défense" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, c-format msgid "Buy Price: %d %s" msgstr "Prix d'achat : %d %s" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, c-format msgid "Buy Price: %d %s each" msgstr "Prix d'achat : %d %s par pièce" #: ../../../src/ItemManager.cpp:643 #, c-format msgid "Sell Price: %d %s" msgstr "Prix de vente : %d %s" #: ../../../src/ItemManager.cpp:645 #, c-format msgid "Sell Price: %d %s each" msgstr "Prix de vente : %d %s par pièce" #: ../../../src/ItemManager.cpp:655 msgid "Set: " msgstr "État : " #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "%d items :" #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "Nom" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "Niveau" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "Physique" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "Mental" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "Attaque" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "Défense" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "Points restants" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "PV max :" #: ../../../src/MenuCharacter.cpp:340 msgid "HP Regen:" msgstr "Régén. PV :" #: ../../../src/MenuCharacter.cpp:341 msgid "Ticks of HP regen per minute. " msgstr "" #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "PM max :" #: ../../../src/MenuCharacter.cpp:352 msgid "MP Regen:" msgstr "Régén. PM :" #: ../../../src/MenuCharacter.cpp:353 msgid "Ticks of MP regen per minute. " msgstr "" #: ../../../src/MenuCharacter.cpp:358 msgid "Accuracy:" msgstr "Précision :" #: ../../../src/MenuCharacter.cpp:364 msgid "Avoidance:" msgstr "Esquive :" #: ../../../src/MenuCharacter.cpp:370 msgid "Melee Damage:" msgstr "Dégâts en corps à corps :" #: ../../../src/MenuCharacter.cpp:380 msgid "Ranged Damage:" msgstr "Dégâts à distance :" #: ../../../src/MenuCharacter.cpp:390 msgid "Mental Damage:" msgstr "Dégâts mentaux :" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "Crit :" #: ../../../src/MenuCharacter.cpp:406 msgid "Absorb:" msgstr "Absorbe :" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "Aplomb : " #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "Réduit vos chances de trébucher quand vous êtes touché" #: ../../../src/MenuCharacter.cpp:422 msgid "Bonus XP: " msgstr "Bonus XP : " #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "Augmente l'XP recupérée par ennemi abattu" #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "Bonus" #: ../../../src/MenuCharacter.cpp:429 #, c-format msgid "Increases the %s found per drop" msgstr "Augmente les %s trouvés par cession" #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "Bonus de découverte d'objets: " #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "Augmente les chances qu'un enemi abattu cedera un objet" #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "Furtivité: " #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "Augmente votre aptitude au déplacement sans détection" #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "XP : %d" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "Prochain : %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "Le Physique (P) augmente la compétence avec des armes de corps à corps ainsi que les points de vie totaux." #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "base (%d), bonus (%d)" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "Le Mental (M) augmente la compétence avec des armes mentales ainsi que les points de magie totaux." #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "L'Attaque (O) augmente la compétence avec des armes de jet ainsi que la précision." #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "La Défense (D) augmente la compétence avec des armures et l'esquive." #: ../../../src/MenuCharacter.cpp:498 #, c-format msgid "Each level grants %d. " msgstr "" #: ../../../src/MenuCharacter.cpp:500 #, fuzzy, c-format msgid "Each point of Physical grants %d. " msgstr "Chaque point de Physique donne +%d PV. Chaque niveau donne +%d PV" #: ../../../src/MenuCharacter.cpp:502 #, fuzzy, c-format msgid "Each point of Mental grants %d. " msgstr "Chaque point de Mental donne +%d PM. Chaque niveau donne +%d PM" #: ../../../src/MenuCharacter.cpp:504 #, fuzzy, c-format msgid "Each point of Offense grants %d. " msgstr "Chaque point de Mental donne +%d PM. Chaque niveau donne +%d PM" #: ../../../src/MenuCharacter.cpp:506 #, fuzzy, c-format msgid "Each point of Defense grants %d. " msgstr "Chaque point de Mental donne +%d PM. Chaque niveau donne +%d PM" #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "Mort" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "%s niveau %d" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "Quitter" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "Sauver et quitter ?" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "" #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "" #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "" #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "" #: ../../../src/MenuInventory.cpp:228 #, c-format msgid "%d %s" msgstr "%d %s" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "Utilisez SHIFT pour déplacer un seul objet." #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "Cliquez sur un objet de l'inventaire avec CTRL enfoncé pour le vendre." #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "Cet objet ne peut être utilisé que depuis la barre d'action." #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "Notes" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "Quêtes" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "XP: %d/%d" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, fuzzy, c-format msgid "Not enough %s." msgstr "Pas assez d'argent." #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "Commercer" #: ../../../src/MenuPowers.cpp:463 msgid "Unspent skill points:" msgstr "Pts de compétence non dépensés:" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" #: ../../../src/MenuPowers.cpp:525 #, fuzzy, c-format msgid "Requires a %s" msgstr "Nécessite %d de Mental" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "Nécessite Attaque Physique %d" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "Nécessite Défense Physique %d" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "Nécessite Attaque Mentale %d" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "Nécessite Défense Mentale %d" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, c-format msgid "Requires Level %d" msgstr "Nécessite le niveau %d" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, c-format msgid "Requires %d Skill Point" msgstr "Nécessite %d points de compétence" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "Cliquer pour débloquer" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, c-format msgid "Requires Power: %s" msgstr "Nécessite le pouvoir: %s" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "Consomme %d PM" #: ../../../src/MenuPowers.cpp:625 #, c-format msgid "Costs %d HP" msgstr "Consomme %d PV" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "Récupération : %d secondes" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "Coffre commun" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "Racheter" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "Vendeur" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "+%d Bouclier" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "Vous êtes deja transformé, reprenez forme humaine avant." #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "Aventurier" #: ../../../src/Utils.cpp:519 #, fuzzy msgid "k" msgstr "Ok" #~ msgid "Character Menu (C)" #~ msgstr "Menu Personnage (C)" #~ msgid "Inventory Menu (I)" #~ msgstr "Menu Inventaire (I)" #~ msgid "Power Menu (P)" #~ msgstr "Menu Pouvoirs (P)" #~ msgid "Log Menu (L)" #~ msgstr "Menu Journal (L)" #~ msgid "Ticks of HP regen per minute. Each point of Physical grants +%d HP regen. Each level grants +%d HP regen" #~ msgstr "Augmente la régénération de PV par minute. Chaque point de Physique régénère +%d PV. Chaque niveau régénère +%d PV" #~ msgid "Ticks of MP regen per minute. Each point of Mental grants +%d MP regen. Each level grants +%d MP regen" #~ msgstr "Augmente la régénération de PM par minute. Chaque point de Mental régénère +%d PM. Chaque niveau régénère +%d PM" #~ msgid "Each point of Offense grants +%d accuracy. Each level grants +%d accuracy" #~ msgstr "Chaque point d'Attaque donne +%d en précision. Chaque niveau donne +%d en précision" #~ msgid "Each point of Defense grants +%d avoidance. Each level grants +%d avoidance" #~ msgstr "Chaque point de Défense donne +%d en esquive. Chaque niveau donne +%d d'esquive" #~ msgid "Requires a physical weapon" #~ msgstr "Nécessite une arme physique" #~ msgid "Requires a mental weapon" #~ msgstr "Nécessite une arme mentale" #~ msgid "Requires an offense weapon" #~ msgstr "Nécessite une arme d'attaque" #~ msgid "Flare" #~ msgstr "Flare" #~ msgid "Accuracy (vs lvl 5):" #~ msgstr "Précision (vs niv.5):" #~ msgid "Avoidance (vs lvl 5):" #~ msgstr "Esquive (vs niv5):" #~ msgid "Stats" #~ msgstr "Statistiques" #~ msgid "Grand Master" #~ msgstr "Grand maître" #~ msgid "Master" #~ msgstr "Maître" #~ msgid "Warrior" #~ msgstr "Guerrier" #~ msgid "Wizard" #~ msgstr "Mage" #~ msgid "Ranger" #~ msgstr "Rôdeur" #~ msgid "Paladin" #~ msgstr "Paladin" #~ msgid "Rogue" #~ msgstr "Voleur" #~ msgid "Knight" #~ msgstr "Chevalier" #~ msgid "Shaman" #~ msgstr "Chamane" #~ msgid "Cleric" #~ msgstr "Clerc" #~ msgid "Battle Mage" #~ msgstr "Mage de guerre" #~ msgid "Heavy Archer" #~ msgstr "Archer lourd" flare-engine-0.19/mods/default/languages/engine.gd.po000066400000000000000000000610231224717101500225330ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # GunChleoc , 2013. msgid "" msgstr "" "Project-Id-Version: flare-engine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2013-11-29 19:38+0100\n" "Last-Translator: GunChleoc \n" "Language-Team: Fòram na Gàidhlig http://www.foramnagaidhlig.net\n" "Language: gd\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : " "(n > 2 && n < 20) ? 2 : 3;\n" "X-Generator: Virtaal 0.7.1\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "Meal do naidheachd, ruig thu leibheil %d!" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "Faodaidh tu aon bhuadh àrdachadh tro clàr-taice a' charactair." #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "" "Chaidh do ruaig. Crìoch a' gheama! Brùth air Enter gus fàgail gun tiotal." #: ../../../src/Avatar.cpp:634 msgid "You are defeated. Press Enter to continue." msgstr "Chaidh do ruaig. Brùth air Enter gus leantainn air adhart." #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "Chaidh %d %s a thoirt air falbh." #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "Chaidh %s a thoirt air falbh." #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "Fhuair thu %s." #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "Gheibh thu %s x%d." #: ../../../src/CampaignManager.cpp:168 #, c-format msgid "You receive %d %s." msgstr "Gheibh thu %d %s." #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "Gheibh thu %d PE." #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "Chaidh PB a leigheas." #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "Chaidh PG a leigheas." #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "Chaidh PB is PG a leigheas." #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "Chaidh èifeachdan dona a thoirt air falbh." #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "Chaidh PB is PG a leigheas is èifeachdan dona a thoirt air falbh." #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "mearachdadh" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "+%d PB" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "+%d PG" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "Ceann-uidhe neo-aithnichte" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "Ceart ma-thà" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "Bun-roghainnean" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "Sguir dheth" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "Video" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "Fuaim" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "Eadar-aghaidh" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "Ion-chur" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "Iuchraichean" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "Tuilleadain" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "Sònraich: " #: ../../../src/GameStateConfig.cpp:165 msgid "Reset ALL settings?" msgstr "A bheil thu airson GACH roghainn ath-shuidheachadh?" #: ../../../src/GameStateConfig.cpp:166 msgid "Use this resolution?" msgstr "A bheil thu airson an dùmhlachd-bhreacaidh seo a chleachdadh?" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "Modh làn-sgrìn" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "Gluais an gaisgeach le luchag" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "Seall teacsa na còmhraige" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "Uachdaran bathair-chruaidh" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "Bufaireadh dùbailte" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "Cleachd joystick" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "Innich le càileachd àrd" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "Faodar gamma atharrachadh" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "Beòthachadh nan leacan" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "Amas luchaige" #: ../../../src/GameStateConfig.cpp:318 msgid "Do not use mouse" msgstr "Na cleachd an luchag" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "Seall FPS" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "Seall leubailean nan hotkeys" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "Modh dath-dhoille" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "Àirde a' chiùil" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "Àirde na fuaime" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "Gamma" #: ../../../src/GameStateConfig.cpp:377 msgid "Joystick Deadzone" msgstr "Marbh-sòn an joystick" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "Dùmhlachd-bhreacaidh" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "Tuilleadain ghnìomhach" #: ../../../src/GameStateConfig.cpp:412 msgid "Available Mods" msgstr "Tuilleadain ri làimh" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "Joystick" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "Cànan" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 msgid "Disable for performance" msgstr "Cuir à comas airson dèanadas" #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "Deuchainneil" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "Airson innealan-làimhe" #: ../../../src/GameStateConfig.cpp:527 msgid "<< Disable" msgstr "<< Cuir à comas" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr "Cuir an comas >>" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "Sguab às" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "A bheil thu airson an gheama air a shàbhaladh a sguabadh às?" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "Fàg gun tiotal" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "Tagh slot" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "Geama ùr" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "Cuir tuilleadan sgeulachd an comas gus leantainn air adhart" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "Luchdaich geama" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "A' dol a-steach do shaoghal a' gheama..." #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "A' luchdaidh geama air a shàbhaladh..." #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "%s leibheil %d" #: ../../../src/GameStateLoad.cpp:579 msgid "Permadeath" msgstr "Bàs maireannach" #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "Slot falamh" #: ../../../src/GameStateNew.cpp:62 msgid "Create" msgstr "Cruthaich" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "Tagh dealbh" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "Tagh ainm" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "Bàs maireannach?" #: ../../../src/GameStateNew.cpp:179 msgid "Choose a Class" msgstr "Tagh clas" #: ../../../src/GameStatePlay.cpp:99 msgid "Loading..." msgstr "'Ga luchdadh..." #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "Tha an tasgadh làn." #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "Cluich geama" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "Cuir bun-sgeulachd an comas gus leantainn air adhart" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "Rèiteachadh" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "Cliù" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "Fàg an-seo" #: ../../../src/GameStateTitle.cpp:67 msgid "Flare Alpha v0.19" msgstr "Flare Alpha v0.19" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "Gabh ris" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "Suas" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "Sìos" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "Gu clì" #: ../../../src/InputState.cpp:627 msgid "Right" msgstr "Gu deas" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "Bàr1" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "Bàr2" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "Bàr3" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "Bàr4" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "Bàr5" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "Bàr6" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "Bàr7" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "Bàr8" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "Bàr9" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "Bàr0" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "Pearsa" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "Tasgadh" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "Cumhachdan" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "Loga" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "Prìomh1" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "Prìomh2" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "Ctrl" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "Shift" #: ../../../src/InputState.cpp:646 msgid "Delete" msgstr "Sguab às" #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "Bàr-ghnìomh - Gabh ris" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "Bàr-ghnìomh - Gu clì" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "Bàr-ghnìomh - Gu deas" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "Bàr-ghnìomh - Cleachd" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "clì" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "meadh" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "deas" #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "cuibhle suas" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "cuibhle sìos" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "luchx1" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "luchx2" #: ../../../src/ItemManager.cpp:488 msgid "Low" msgstr "Ìseal" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "Àbhaisteach" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "Àrd" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "Dàna" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "Leibheil %d" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "Dochann dlùth: %d-%d" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "Dochann dlùth: %d" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "Dochann astair: %d-%d" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "Dochann astair: %d" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "Dochann inntinneil: %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "Dochann inntinneil: %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "Ceapadh: %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "Ceapadh: %d" #: ../../../src/ItemManager.cpp:554 #, c-format msgid "%d% Speed" msgstr "Luaths de %d%" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "Meudaichidh seo %s le %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "Lùghdaichidh seo %s le %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "Feum air buadh fhiosaigeach de %d" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "Feum air buadh inntinneil de %d" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "Feum air buadh ionnsaighe de %d" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "Feum air buadh dìona de %d" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "Càileachd: %s" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, c-format msgid "Buy Price: %d %s" msgstr "Prìs ceannaich: %d %s" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, c-format msgid "Buy Price: %d %s each" msgstr "Prìs ceannaich: %d %s an urra" #: ../../../src/ItemManager.cpp:643 #, c-format msgid "Sell Price: %d %s" msgstr "Prìs reic: %d %s" #: ../../../src/ItemManager.cpp:645 #, c-format msgid "Sell Price: %d %s each" msgstr "Prìs reic: %d %s an urra" #: ../../../src/ItemManager.cpp:655 msgid "Set: " msgstr "Seata: " #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "%d nithean: " #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "Ainm" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "Leibheil" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "Fiosaigeach" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "Inntinneil" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "Ionnsaigh" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "Dìon" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "puingean air fhàgail" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "PB as motha:" #: ../../../src/MenuCharacter.cpp:340 msgid "HP Regen:" msgstr "Ath-ghintinn nam PB:" #: ../../../src/MenuCharacter.cpp:341 msgid "Ticks of HP regen per minute. " msgstr "Ath-ghintinn nam PB gach mionaid. " #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "PG as motha:" #: ../../../src/MenuCharacter.cpp:352 msgid "MP Regen:" msgstr "Ath-ghintinn nam PG:" #: ../../../src/MenuCharacter.cpp:353 msgid "Ticks of MP regen per minute. " msgstr "Ath-ghintinn nam PG gach mionaid. " #: ../../../src/MenuCharacter.cpp:358 msgid "Accuracy:" msgstr "Pongalachd:" #: ../../../src/MenuCharacter.cpp:364 msgid "Avoidance:" msgstr "Teàrnadh:" #: ../../../src/MenuCharacter.cpp:370 msgid "Melee Damage:" msgstr "Dochann dlùth:" #: ../../../src/MenuCharacter.cpp:380 msgid "Ranged Damage:" msgstr "Dochann astair:" #: ../../../src/MenuCharacter.cpp:390 msgid "Mental Damage:" msgstr "Dochann inntinneil:" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "Èiginneach:" #: ../../../src/MenuCharacter.cpp:406 msgid "Absorb:" msgstr "Ceapadh:" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "Giùlan: " #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "Cha tuit thu gu furasta nuair a thèid bualadh ort" #: ../../../src/MenuCharacter.cpp:422 msgid "Bonus XP: " msgstr "Duais PB: " #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "Bheir seo barrachd phuingean-beatha dhut leis gach marbhadh" #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "Duais" #: ../../../src/MenuCharacter.cpp:429 #, c-format msgid "Increases the %s found per drop" msgstr "Lorgaidh tu %s a bharrachd leis gach tuiteam" #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "Duais lorg nan nithean: " #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "" "Bidh barrachd teans gun leig nàmhaid nì a thuiteam nuair a mharbhas tu e" #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "Tàisleachadh: " #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "Cuiridh seo ri do chomas nach tèid do mhothachadh" #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "PE: %d" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "An ath-fhear: %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "" "Cuiridh a' bhuadh fhiosaigeach (F) ri do chomas air airm dlùtha agus ris na " "puingean-beatha iomlan agad." #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "bunait (%d), duais (%d)" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "" "Cuiridh a' bhuadh inntinneil (N) ri do chomas air airm inntinneil agus ris " "na puingean-gluasaid iomlan agad." #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "" "Cuiridh a' bhuadh ionnsaighe (I) ri do chomas air airm astair agus do " "phongalachd." #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "Cuiridh a' bhuadh dìona (D) ri do chomas armachd agus do theàrnadh." #: ../../../src/MenuCharacter.cpp:498 #, c-format msgid "Each level grants %d. " msgstr "Bheir gabh leibheil %d dhut. " #: ../../../src/MenuCharacter.cpp:500 #, c-format msgid "Each point of Physical grants %d. " msgstr "Bheir gach puing dhen bhuadh fhiosaigeach %d dhut. " #: ../../../src/MenuCharacter.cpp:502 #, c-format msgid "Each point of Mental grants %d. " msgstr "Bheir gach puing dhen bhuadh inntinneil %d dhut. " #: ../../../src/MenuCharacter.cpp:504 #, c-format msgid "Each point of Offense grants %d. " msgstr "Bheir gach puing dhen bhuadh ionnsaighe %d dhut. " #: ../../../src/MenuCharacter.cpp:506 #, c-format msgid "Each point of Defense grants %d. " msgstr "Bheir gach puing dhen bhuadh dìona %d dhut. " #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "Marbh" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "%s leibheil %d" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "Fàg an geama" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "Sàbhaladh is fàgail gun tiotal?" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "Chaill thu %d%% de %s. " #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "Chaill thu %d%% dhe na puingean-eòlais iomlan. " #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "Chaill thu %d%% dhe na puingean-eòlais airson an leibheil seo. " #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "Chaill thu %s." #: ../../../src/MenuInventory.cpp:228 #, c-format msgid "%d %s" msgstr "%d %s" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "Cleachd SHIFT gus nì a-mhàin a ghluasad." #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "Dèan CTRL-briogadh air nì a ghiùlaineas tu gus a reic." #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "Cha ghabh an nì seo cleachdadh ach on bhàr-ghnìomhan." #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "Nòtaichean" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "Sireadh" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "PE: %d/%d" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, c-format msgid "Not enough %s." msgstr "Chan eil %s gu leòr agad." #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "Malart" #: ../../../src/MenuPowers.cpp:463 msgid "Unspent skill points:" msgstr "Puingean-sgil nach deach a chleachdadh:" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" "\n" "An t-ath-leibheil:" #: ../../../src/MenuPowers.cpp:525 #, c-format msgid "Requires a %s" msgstr "Feum air %s" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "Feum air ionnsaigh fiosaigeach de %d" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "Feum air dìon fiosaigeach de %d" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "Feum air ionnsaigh inntinneil de %d" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "Feum air dìon inntinneil de %d" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, c-format msgid "Requires Level %d" msgstr "Feum air leibheil %d" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, c-format msgid "Requires %d Skill Point" msgstr "Feum air %d puingean-sgil" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "Briog air gus a neo-ghlasadh" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, c-format msgid "Requires Power: %s" msgstr "Feum air cumhachd: %s" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "Cosgaidh e %d PG" #: ../../../src/MenuPowers.cpp:625 #, c-format msgid "Costs %d HP" msgstr "Cosgaidh e %d PB" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "Fuarachadh: %d diog" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "Stòr co-roinnte" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "Ceannach air ais" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "Reiceadair" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "Sgiath +%d" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "" "Tha thu air cruth-atharrachadh mar-thà, feumaidh tu an cruth tùsail agad a " "ghabhail an toiseach." #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "Baoghlair" #: ../../../src/Utils.cpp:519 msgid "k" msgstr "k" flare-engine-0.19/mods/default/languages/engine.gl.po000066400000000000000000000733421224717101500225520ustar00rootroot00000000000000# Copyright (C) 2011 Clint Bellanger # This file is distributed under the same license as the FLARE package. # # Adrian Chaves Fernandez (Gallaecio) , 2011, 2012, 2013. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2013-04-08 19:50+0200\n" "Last-Translator: Adrián Chaves Fernández \n" "Language-Team: Galician \n" "Language: gl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Lokalize 1.5\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "Parabéns, chegaches ao nivel %d!" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "Podes aumentar un atributo desde o menú da personaxe." #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "Derrotáronte. Perdiches! Preme Intro para ir ao menú." #: ../../../src/Avatar.cpp:634 #, fuzzy msgid "You are defeated. Press Enter to continue." msgstr "Derrotáronte, e perdiches a metade do %s. Preme Intro para continuar." #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "" #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "" #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "Obtiveches unha unidade de %s." #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "Obtiveches %d unidades de %s." #: ../../../src/CampaignManager.cpp:168 #, c-format msgid "You receive %d %s." msgstr "Obtiveches %d %s." #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "A túa experiencia aumentou %d puntos." #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "Recuperaches a vida." #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "Recuperaches a enerxía." #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "Recuperaches a vida e a enerxía." #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "Elimináronse os efectos negativos." #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "Recuperaches a vida e a enerxía, e elimináronse os efectos negativos." #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "fallo" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "+%d de vida" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "+%d de enerxía" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "Destino descoñecido." #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "Aceptar" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "Restablecer" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "Cancelar" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "Vídeo" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "Son" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "Interface" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "Entrada" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "Controis" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "Mods" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "Asignar: " #: ../../../src/GameStateConfig.cpp:165 msgid "Reset ALL settings?" msgstr "Volver á configuración inicial?" #: ../../../src/GameStateConfig.cpp:166 msgid "Use this resolution?" msgstr "Usar esta resolución?" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "Pantalla completa:" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "Mover a personaxe co cursor:" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "Amosar texto de combate:" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "Superficies por hardware:" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "Dobre búfer:" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "Empregar un mando:" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "Texturas de alta calidade:" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "Permitir cambiar o gamma:" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "Animacións no revestimento:" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "Apuntar co rato:" #: ../../../src/GameStateConfig.cpp:318 #, fuzzy msgid "Do not use mouse" msgstr "Mover a personaxe co cursor:" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "Amosar os FPS:" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "Volume da música:" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "Volume dos sons:" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "Gamma:" #: ../../../src/GameStateConfig.cpp:377 #, fuzzy msgid "Joystick Deadzone" msgstr "Mando:" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "Resolución:" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "Mods activos:" #: ../../../src/GameStateConfig.cpp:412 msgid "Available Mods" msgstr "Mods dispoñíbeis:" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "Mando:" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "Idioma:" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 msgid "Disable for performance" msgstr "Desactivalo mellora o rendemento." #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "Experimental." #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "" #: ../../../src/GameStateConfig.cpp:527 msgid "<< Disable" msgstr "← Desactivar" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr "Activar →" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "Borrar a partida" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "Estás seguro?" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "Menú principal" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "Escolla un espazo" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "Nova partida" # Nin idea de onde atopar esta cadea. #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "Activa unha modificación de historia para continuar." #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "Cargar a partida" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "Cargando o mundo…" #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "Cargando a partida..." # Aparece no menú de escolla de partida, para dicir o tipo de personaxe protagonista da partida, así como o seu nivel. #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "%s de nivel %d" #: ../../../src/GameStateLoad.cpp:579 #, fuzzy msgid "Permadeath" msgstr "Perder a partida ao morrer." #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "Espazo sen usar." #: ../../../src/GameStateNew.cpp:62 msgid "Create" msgstr "Crear" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "Retrato:" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "Nome:" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "Perder a partida ao morrer." #: ../../../src/GameStateNew.cpp:179 msgid "Choose a Class" msgstr "Clase:" #: ../../../src/GameStatePlay.cpp:99 msgid "Loading..." msgstr "Cargando…" #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "O inventario está cheo." #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "Xogar" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "Activa unha modificación base para continuar." #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "Configuración" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "Saír" #: ../../../src/GameStateTitle.cpp:67 #, fuzzy msgid "Flare Alpha v0.19" msgstr "Flare 0.18 (alfa)" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "Aceptar" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "Arriba" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "Abaixo" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "Esquerda" #: ../../../src/InputState.cpp:627 msgid "Right" msgstr "Dereita" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "Acción 1" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "Acción 2" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "Acción 3" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "Acción 4" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "Acción 5" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "Acción 6" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "Acción 7" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "Acción 8" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "Acción 9" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "Acción 0" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "Personaxe" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "Inventario" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "Habilidades" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "Rexistro" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "Acción principal" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "Acción secundaria" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "Control" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "Maiúsculas" #: ../../../src/InputState.cpp:646 msgid "Delete" msgstr "Suprimir" #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "B.E." #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "B.C." #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "B.D." #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "Roda arriba" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "Roda abaixo" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "B. 1" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "B. 2" #: ../../../src/ItemManager.cpp:488 #, fuzzy msgid "Low" msgstr "Rexistro" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "Nivel %d" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "Dano corpo a corpo: %d-%d" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "Dano corpo a corpo: %d" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "Dano a distancia: %d-%d" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "Dano a distancia: %d" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "Dano mental: %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "Dano mental: %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "Absorción: %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "Absorción: %d" #: ../../../src/ItemManager.cpp:554 #, fuzzy, c-format msgid "%d% Speed" msgstr "%d%% velocidade" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "Aumenta %s en %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "Reduce %s en %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "Require %d de físico." #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "Require %d de mente." #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "Require %d de ataque." #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "Require %d de defensa." #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, c-format msgid "Buy Price: %d %s" msgstr "Prezo de compra: %d %s" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, c-format msgid "Buy Price: %d %s each" msgstr "Prezo de compra: %d %s por unidade" #: ../../../src/ItemManager.cpp:643 #, c-format msgid "Sell Price: %d %s" msgstr "Prezo de venda: %d %s" #: ../../../src/ItemManager.cpp:645 #, c-format msgid "Sell Price: %d %s each" msgstr "Prezo de venda: %d %s por unidade" #: ../../../src/ItemManager.cpp:655 msgid "Set: " msgstr "Grupo: " #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "%d obxectos: " #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "Nome" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "Nivel" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "Físico" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "Mente" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "Ataque" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "Defensa" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "puntos restantes" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "Vida máxima:" #: ../../../src/MenuCharacter.cpp:340 msgid "HP Regen:" msgstr "Recuperación:" #: ../../../src/MenuCharacter.cpp:341 #, fuzzy msgid "Ticks of HP regen per minute. " msgstr "Recuperación por minuto" #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "Enerxía máxima:" #: ../../../src/MenuCharacter.cpp:352 msgid "MP Regen:" msgstr "Rexeneración:" #: ../../../src/MenuCharacter.cpp:353 #, fuzzy msgid "Ticks of MP regen per minute. " msgstr "Rexeneración por minuto" #: ../../../src/MenuCharacter.cpp:358 msgid "Accuracy:" msgstr "Puntería:" #: ../../../src/MenuCharacter.cpp:364 msgid "Avoidance:" msgstr "Esquivar:" #: ../../../src/MenuCharacter.cpp:370 msgid "Melee Damage:" msgstr "Dano corpo a corpo:" #: ../../../src/MenuCharacter.cpp:380 msgid "Ranged Damage:" msgstr "Dano a distancia:" #: ../../../src/MenuCharacter.cpp:390 msgid "Mental Damage:" msgstr "Dano mental:" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "Crítico:" #: ../../../src/MenuCharacter.cpp:406 msgid "Absorb:" msgstr "Absorción:" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "Equilibrio: " #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "Reduce a probabilidade de tropezar ao recibir un golpe." #: ../../../src/MenuCharacter.cpp:422 msgid "Bonus XP: " msgstr "Experiencia adicional: " #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "Aumenta a experiencia conseguida ao matar." #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "Bonificación" #: ../../../src/MenuCharacter.cpp:429 #, c-format msgid "Increases the %s found per drop" msgstr "Aumenta o %s que se atopa en cada botín." #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "Atopar obxectos adicionais:" #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "Aumenta a probabilidade de que o botín ao matar inimigos conteña obxectos." #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "Sixilo: " #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "Aumenta a capacidade de pasar inadvertido ao moverse." #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "Experiencia: %d" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "Seguinte nivel: %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "O físico (F) aumenta a habilidade coas armas corpo a corpo e a vida." #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "Base: %d. Bonificación: %d." #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "A mente (M) aumenta a habilidade coas armas mentais e a enerxía." #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "O ataque (A) aumenta a habilidade coas armas a distancia e a puntería." #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "A defensa (D) aumenta a habilidade coa armadura e esquivando." #: ../../../src/MenuCharacter.cpp:498 #, fuzzy, c-format msgid "Each level grants %d. " msgstr "Cada nivel aumenta en 2 a vida." #: ../../../src/MenuCharacter.cpp:500 #, fuzzy, c-format msgid "Each point of Physical grants %d. " msgstr "Cada punto de físico aumenta en 8 a vida." #: ../../../src/MenuCharacter.cpp:502 #, fuzzy, c-format msgid "Each point of Mental grants %d. " msgstr "Cada punto de mente aumenta en 8 a enerxía." #: ../../../src/MenuCharacter.cpp:504 #, fuzzy, c-format msgid "Each point of Offense grants %d. " msgstr "Cada punto de mente aumenta en 8 a enerxía." #: ../../../src/MenuCharacter.cpp:506 #, fuzzy, c-format msgid "Each point of Defense grants %d. " msgstr "Cada punto de mente aumenta en 8 a enerxía." #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "Morto" # Indicación do inimigo ao que se está a apuntar. #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "%s (nivel %d)" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "Volver ao menú" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "Gardar e saír ao menú?" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "" #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "" #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "" #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "" # Aparece no menú de escolla de partida, para dicir o tipo de personaxe protagonista da partida, así como o seu nivel. #: ../../../src/MenuInventory.cpp:228 #, c-format msgid "%d %s" msgstr "%d %s" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "Prema Maiús para mover só un obxecto." #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "Prema Ctrl e un obxecto para vendelo." #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "Este obxecto só pode empregarse desde a barra de acción." #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "Notas" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "Misións" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "Experiencia: %d/%d" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, fuzzy, c-format msgid "Not enough %s." msgstr "Non tes dabondo." #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "Comercio" #: ../../../src/MenuPowers.cpp:463 msgid "Unspent skill points:" msgstr "Puntos de atributos sen usar:" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" #: ../../../src/MenuPowers.cpp:525 #, fuzzy, c-format msgid "Requires a %s" msgstr "Require %d de mente." #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "Require %s de ataque físico." #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "Require %d de defensa física." #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "Require %d de ataque mental." #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "Require %d de defensa mental." #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, c-format msgid "Requires Level %d" msgstr "Require o nivel %d." #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, c-format msgid "Requires %d Skill Point" msgstr "Require %d puntos de habilidade." #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "Preme para desbloquear." #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, c-format msgid "Requires Power: %s" msgstr "Require a habilidade «%s»." #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "Consume %d de enerxía" #: ../../../src/MenuPowers.cpp:625 #, c-format msgid "Costs %d HP" msgstr "Consume %d de vida" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "Recarga: %d segundos" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "Reserva compartida" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "Recuperar" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "Vendedor" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "+%d de escudo" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "Xa estás transformado, primeiro recupera a forma orixinal." #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "Aventureiro" #: ../../../src/Utils.cpp:519 #, fuzzy msgid "k" msgstr "Aceptar" #~ msgid "Character Menu (C)" #~ msgstr "Personaxe (C)" #~ msgid "Inventory Menu (I)" #~ msgstr "Inventario (I)" #~ msgid "Power Menu (P)" #~ msgstr "Habilidades (P)" #~ msgid "Log Menu (L)" #~ msgstr "Rexistro (L)" #~ msgid "Each point of Physical grants +%d HP. Each level grants +%d HP" #~ msgstr "Cada punto de físico aumenta en %d a vida. Cada nivel auméntaa en %d." #~ msgid "Ticks of HP regen per minute. Each point of Physical grants +%d HP regen. Each level grants +%d HP regen" #~ msgstr "Cantidade de vida recuperada por minuto. Cada punto de físico aumenta en %d a recuperación. Cada nivel auméntaa en %d." #~ msgid "Each point of Mental grants +%d MP. Each level grants +%d MP" #~ msgstr "Cada punto de mente aumenta en %d a rexeneración. Cada nivel auméntaa en %d." #~ msgid "Ticks of MP regen per minute. Each point of Mental grants +%d MP regen. Each level grants +%d MP regen" #~ msgstr "Cantidade de enerxía recuperada por minuto. Cada punto de mente aumenta en %d a rexeneración. Cada nivel auméntaa en %d." #~ msgid "Each point of Offense grants +%d accuracy. Each level grants +%d accuracy" #~ msgstr "Cada punto de ataque aumenta en %d a puntería. Cada nivel auméntaa en %d." #~ msgid "Each point of Defense grants +%d avoidance. Each level grants +%d avoidance" #~ msgstr "Cada punto de defensa aumenta en %d a capacidade para esquivar. Cada nivel auméntaa en %d." #~ msgid "Requires a physical weapon" #~ msgstr "Require unha arma física." #~ msgid "Requires a mental weapon" #~ msgstr "Require unha arma mental." #~ msgid "Requires an offense weapon" #~ msgstr "Require unha arma ofensiva." #~ msgid "Flare" #~ msgstr "Flare" #~ msgid "Accuracy (vs lvl 5):" #~ msgstr "Puntería (vs n5):" #~ msgid "Avoidance (vs lvl 5):" #~ msgstr "Esquivar (vs n5):" #~ msgid "Unspent attribute points" #~ msgstr "Puntos de atributos sen usar" #~ msgid "Stats" #~ msgstr "Estatísticas" #~ msgid "Grand Master" #~ msgstr "Gran mestre" #~ msgid "Master" #~ msgstr "Mestre" #~ msgid "Warrior" #~ msgstr "Guerreiro" #~ msgid "Wizard" #~ msgstr "Mago" #~ msgid "Ranger" #~ msgstr "Silvano" #~ msgid "Paladin" #~ msgstr "Paladín" #~ msgid "Rogue" #~ msgstr "Pillabán" #~ msgid "Knight" #~ msgstr "Cabaleiro" #~ msgid "Shaman" #~ msgstr "Xamán" #~ msgid "Cleric" #~ msgstr "Clérigo" #~ msgid "Battle Mage" #~ msgstr "Mago guerreiro" #~ msgid "Heavy Archer" #~ msgstr "Arqueiro pesado" #~ msgid "You receive %d gold." #~ msgstr "Obtiveches %d moedas." #~ msgid "Press a key to assign: " #~ msgstr "Prema unha tecla para asignala: " #~ msgid "Activate >>" #~ msgstr "Activar →" #~ msgid "Create Character" #~ msgstr "Crear" #~ msgid "Main Hand" #~ msgstr "Man der." #~ msgid "Body" #~ msgstr "Corpo" #~ msgid "Off Hand" #~ msgstr "Man esq." #~ msgid "Artifact" #~ msgstr "Artefacto" #~ msgid "Consumable" #~ msgstr "Consumíbel" #~ msgid "Gem" #~ msgstr "Xema" #~ msgid "Quest Item" #~ msgstr "Obxecto dunha misión" #~ msgid "%d Gold" #~ msgstr "%d moedas" #~ msgid "Total HP" #~ msgstr "Vida" #~ msgid "Total MP" #~ msgstr "Enerxía" #~ msgid "vs. Def 5" #~ msgstr "vs 5 Def." #~ msgid "vs. Off 5" #~ msgstr "vs 5 Ata." #~ msgid "Main Weapon" #~ msgstr "Arma principal" #~ msgid "Ranged Weapon" #~ msgstr "Arma a distancia" #~ msgid "Crit Chance" #~ msgstr "Probabilidade de crítico" #~ msgid "Fire Resist" #~ msgstr "Res. ao lume" #~ msgid "Ice Resist" #~ msgstr "Res. ao xeo" #~ msgid "Each level grants +1 HP regen" #~ msgstr "Cada nivel aumenta en 1 a recuperación." #~ msgid "Each level grants +2 MP" #~ msgstr "Cada nivel aumenta en 2 a enerxía." #~ msgid "Each level grants +1 MP regen" #~ msgstr "Cada nivel aumenta en 1 a rexeneración." #~ msgid "Each level grants +1 accuracy" #~ msgstr "Cada nivel aumenta en 1 a puntería." #~ msgid "Each level grants +1 avoidance" #~ msgstr "Cada nivel aumenta en 1 a capacidade para esquivar." #~ msgid "Dagger Proficiency" #~ msgstr "Habilidade coa daga" #~ msgid "Shortsword Proficiency" #~ msgstr "Habilidade coa espada curta" #~ msgid "Longsword Proficiency" #~ msgstr "Habilidade coa espada longa" #~ msgid "Greatsword Proficiency" #~ msgstr "Habilidade coa gran espada" #~ msgid "Wand Proficiency" #~ msgstr "Habilidade co pau" #~ msgid "Rod Proficiency" #~ msgstr "Habilidade coa vara" #~ msgid "Staff Proficiency" #~ msgstr "Habilidade co bastón" #~ msgid "Greatstaff Proficiency" #~ msgstr "Habilidade co gran bastón" #~ msgid "Slingshot Proficiency" #~ msgstr "Habilidade co tiracroios" #~ msgid "Shortbow Proficiency" #~ msgstr "Habilidade co arco curto" #~ msgid "Longbow Proficiency" #~ msgstr "Habilidade co arco longo" #~ msgid "Greatbow Proficiency" #~ msgstr "Habilidade co gran arco" #~ msgid "Light Armor Proficiency" #~ msgstr "Habilidade coa armadura lixeira" #~ msgid "Light Shield Proficiency" #~ msgstr "Habilidade co escudo lixeiro" #~ msgid "Heavy Armor Proficiency" #~ msgstr "Habilidade coa armadura pesada" #~ msgid "Heavy Shield Proficiency" #~ msgstr "Habilidade co escudo pesado" #~ msgid "Messages" #~ msgstr "Mensaxes" #~ msgid "Physical + Offense grants melee and ranged attacks" #~ msgstr "A combinación de físico e ataque permite os ataques corpo a corpo e a distancia" #~ msgid "Physical + Defense grants melee protection" #~ msgstr "A combinación de físico e defensa permite a protección corpo a corpo" #~ msgid "Mental + Offense grants elemental spell attacks" #~ msgstr "A combinación de mente e ataque permite encantamentos de ataque elementais" #~ msgid "Mental + Defense grants healing and magical protection" #~ msgstr "A combinación de mente e defensa permite sandar e a protección máxica" #~ msgid "Achievements" #~ msgstr "Logros" flare-engine-0.19/mods/default/languages/engine.it.po000066400000000000000000000725151224717101500225650ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR dallatower@libero.it, 2012. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2012-07-02 19:21+0100\n" "Last-Translator: Giovanni Dalla Torre \n" "Language-Team: Italiano \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "Congratulazione, sei diventato di %d° Livello!" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "Puoi aumentare un Attributo nel menù Carattere." #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "La Morte ti ha raggiunto. Game over! Premere Invio per tornare al Titolo." #: ../../../src/Avatar.cpp:634 #, fuzzy msgid "You are defeated. Press Enter to continue." msgstr "Sei stato sconfitto. Perdi metà del tuo oro. Premere Invio per continuare." #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "" #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "" #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "Ricevi %s." #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "Ricevi %s x%d." #: ../../../src/CampaignManager.cpp:168 #, fuzzy, c-format msgid "You receive %d %s." msgstr "Ricevi %s." #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "Ricevi %d XP." #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "HP ripristinati" #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "MP ripristinati" #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "HP e MP ripristinati" #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "Effetti Negativi rimossi" #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "HP e MP ripristinati, Effetti Negativi rimossi" #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "mancato" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "+%d HP" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "+%d MP" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "Destinazione sconosciuta" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "OK" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "Defaults" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "Cancellare" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "Video" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "Audio" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "Interfaccia" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "Input" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "Scorciatoie da Tastiera" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "Mods" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "Assegnazioni:" #: ../../../src/GameStateConfig.cpp:165 #, fuzzy msgid "Reset ALL settings?" msgstr "Settare TUTTI i settaggi a default?" #: ../../../src/GameStateConfig.cpp:166 #, fuzzy msgid "Use this resolution?" msgstr "Risoluzione" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "Modalità Schermo Intero" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "Muovere Eroe tramite mouse" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "Mostrate testo combattimento" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "Superfici Solide" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "Doppio buffering" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "Usare joystick" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "Texture in alta qualità" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "Abilitare Gamma concatenata" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "Titoli animati" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "Mouse aim" #: ../../../src/GameStateConfig.cpp:318 #, fuzzy msgid "Do not use mouse" msgstr "Muovere Eroe tramite mouse" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "Mostrare FPS" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "Volume Musiche" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "Volume Suono" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "Gamma" #: ../../../src/GameStateConfig.cpp:377 #, fuzzy msgid "Joystick Deadzone" msgstr "Joystick" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "Risoluzione" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "Mods Attive" #: ../../../src/GameStateConfig.cpp:412 #, fuzzy msgid "Available Mods" msgstr "Mods Disponibili" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "Joystick" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "Lingua" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 #, fuzzy msgid "Disable for performance" msgstr "Provare a disabilitare per aumentare le prestazioni" #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "Sperimentale" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "" #: ../../../src/GameStateConfig.cpp:527 #, fuzzy msgid "<< Disable" msgstr "<< Disabilitare" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr "Abilitare >>" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "Cancellare Salvataggi" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "Cancellare questo Salvataggio?" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "Ritorna al Titolo" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "Scegli Slot" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "Nuovo Gioco" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "Abilita un Story mod per continuare" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "Carica Gioco" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "Entra nel mondo del gioco..." #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "Caricamento gioco salvato..." #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "Livello %d %s" #: ../../../src/GameStateLoad.cpp:579 #, fuzzy msgid "Permadeath" msgstr "Morte definitiva?" #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "Slot libero" #: ../../../src/GameStateNew.cpp:62 #, fuzzy msgid "Create" msgstr "Carattere" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "Scegliti il tuo Ritratto" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "Scegliti il tuo Nome" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "Morte definitiva?" #: ../../../src/GameStateNew.cpp:179 #, fuzzy msgid "Choose a Class" msgstr "Scegli Slot" #: ../../../src/GameStatePlay.cpp:99 #, fuzzy msgid "Loading..." msgstr "Caricamento gioco salvato..." #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "L'inventario è pieno." #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "Giocare" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "Abilitare un Core mod per continuare" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "Configurazione" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "Uscire dal Gioco" #: ../../../src/GameStateTitle.cpp:67 #, fuzzy msgid "Flare Alpha v0.19" msgstr "Flare Alpha v0.18" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "Accetto" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "Alto" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "Basso" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "Sinistra" #: ../../../src/InputState.cpp:627 #, fuzzy msgid "Right" msgstr "Destra" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "Bar1" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "Bar2" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "Bar3" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "Bar4" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "Bar5" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "Bar6" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "Bar7" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "Bar8" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "Bar9" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "Bar0" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "Carattere" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "Inventario" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "Poteri" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "Log" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "Principale1" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "Principale2" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "Ctrl" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "Shift" #: ../../../src/InputState.cpp:646 #, fuzzy msgid "Delete" msgstr "Cancellare Salvataggi" #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "pulsante sinistro" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "pulsante centrale" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "pulsante destro" #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "rotella in alto" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "rotella in basso" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "mbx1" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "mbx2" #: ../../../src/ItemManager.cpp:488 #, fuzzy msgid "Low" msgstr "Log" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "Livello %d" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "Danno da Mischia: %d-%d" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "Danno da Mischia: %d" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "Danno da Lancio: %d-%d" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "Danno da Lancio: %d" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "Danno Magico: %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "Danno Magico: %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "Assorbimento: %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "Assorbimento: %d" #: ../../../src/ItemManager.cpp:554 #, fuzzy, c-format msgid "%d% Speed" msgstr "%d%% Velocità" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "Incremento %s di %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "Decremento %s di %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "Richiesto Potere Fisico %d" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "Richiesto Potere Magico %d" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "Richiesto Potere Offensivo %d" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "Richiesto Potere Difensivo %d" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, fuzzy, c-format msgid "Buy Price: %d %s" msgstr "Prezzo d'acquisto: %d oro" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, fuzzy, c-format msgid "Buy Price: %d %s each" msgstr "Prezzo d'acquisto: %d oro ciascuno" #: ../../../src/ItemManager.cpp:643 #, fuzzy, c-format msgid "Sell Price: %d %s" msgstr "Prezzo di vendita: %d oro" #: ../../../src/ItemManager.cpp:645 #, fuzzy, c-format msgid "Sell Price: %d %s each" msgstr "Prezzo di vendita: %d oro ciascuno" #: ../../../src/ItemManager.cpp:655 #, fuzzy msgid "Set: " msgstr "Set: " #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "%d oggetti: " #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "Nome" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "Livello" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "Fisico" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "Magico" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "Offensivo" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "Difensivo" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "Punti rimanenti" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "HP massimi" #: ../../../src/MenuCharacter.cpp:340 #, fuzzy msgid "HP Regen:" msgstr "Rigenerazione" #: ../../../src/MenuCharacter.cpp:341 #, fuzzy msgid "Ticks of HP regen per minute. " msgstr "Punti HP rigenerati per minuto" #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "MP massimi" #: ../../../src/MenuCharacter.cpp:352 #, fuzzy msgid "MP Regen:" msgstr "Rigenerazione" #: ../../../src/MenuCharacter.cpp:353 #, fuzzy msgid "Ticks of MP regen per minute. " msgstr "Punti MP rigenerati per minuto" #: ../../../src/MenuCharacter.cpp:358 #, fuzzy msgid "Accuracy:" msgstr "Precisione vs. Dif 1" #: ../../../src/MenuCharacter.cpp:364 #, fuzzy msgid "Avoidance:" msgstr "Schivare vs. Off 1" #: ../../../src/MenuCharacter.cpp:370 #, fuzzy msgid "Melee Damage:" msgstr "Danno da Mischia: %d" #: ../../../src/MenuCharacter.cpp:380 #, fuzzy msgid "Ranged Damage:" msgstr "Danno da Lancio: %d" #: ../../../src/MenuCharacter.cpp:390 #, fuzzy msgid "Mental Damage:" msgstr "Danno Magico: %d" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "Critico: " #: ../../../src/MenuCharacter.cpp:406 #, fuzzy msgid "Absorb:" msgstr "Assorbimento:" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "Equilibrio:" #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "Riduce le probabilità di inciampare quando colpiti" #: ../../../src/MenuCharacter.cpp:422 msgid "Bonus XP: " msgstr "Bonus XP: " #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "Aumenta i punti XP guadagnati per uccisione" #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "Bonus" #: ../../../src/MenuCharacter.cpp:429 #, fuzzy, c-format msgid "Increases the %s found per drop" msgstr "Incremento %s di %d" #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "Bonus oggetti trovati: " #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "Aumenta la probabilità che un nemico lascerà cadere un oggetto quando ucciso" #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "Furtività:" #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "Aumenta la tua abilità a muoversi furtivamente" #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "Esperienza XP: %d" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "Prossimo: %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "Fisico (P) aumenta competenza uso armi da mischia e totale punti salute HP." #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "base (%d), bonus (%d)" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "Magico (M) aumenta competenza uso armi da mischia e totale punti mana MP." #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "Offensivo (O) aumenta competenza uso armi da lancio e precisione." #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "Difensivo (D) aumenta competenza uso armature e capacità di schivare." #: ../../../src/MenuCharacter.cpp:498 #, fuzzy, c-format msgid "Each level grants %d. " msgstr "Ogni Livello ottieni +2 HP" #: ../../../src/MenuCharacter.cpp:500 #, fuzzy, c-format msgid "Each point of Physical grants %d. " msgstr "Perogni punto Fisico ottieni +8 HP" #: ../../../src/MenuCharacter.cpp:502 #, fuzzy, c-format msgid "Each point of Mental grants %d. " msgstr "Perogni punto Mental grants +8 MP" #: ../../../src/MenuCharacter.cpp:504 #, fuzzy, c-format msgid "Each point of Offense grants %d. " msgstr "Perogni punto Mental grants +8 MP" #: ../../../src/MenuCharacter.cpp:506 #, fuzzy, c-format msgid "Each point of Defense grants %d. " msgstr "Perogni punto Mental grants +8 MP" #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "Morte" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "%s livello %d" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "Uscire" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "Salvare e ritornare al Titolo?" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "" #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "" #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "" #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "" #: ../../../src/MenuInventory.cpp:228 #, fuzzy, c-format msgid "%d %s" msgstr "Livello %d %s" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "Usare SHIFT per muovere solo un oggetto." #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "CTRL-click selezionare più ogetti da vendere." #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "Questo elemento può essere usato solo dalla barra azioni." #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "Note" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "Missioni" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "XP: %d/%d" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, fuzzy, c-format msgid "Not enough %s." msgstr "Non hai abbastanza soldi." #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "Commerciante" #: ../../../src/MenuPowers.cpp:463 #, fuzzy msgid "Unspent skill points:" msgstr "Punti attributo non utilizzati" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" #: ../../../src/MenuPowers.cpp:525 #, fuzzy, c-format msgid "Requires a %s" msgstr "Richiesto Potere Magico %d" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "Richiesto Potere Fisico Offensivo %d" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "Richiesto Potere Fisico Difensivo %d" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "Richiesto Potere Magico Offensivo %d" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "Richiesto Potere Magico Difensivo %d" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, fuzzy, c-format msgid "Requires Level %d" msgstr "Richiesto Potere Magico %d" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, fuzzy, c-format msgid "Requires %d Skill Point" msgstr "Richiesta arma da mischia" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "Cliccare per sboccare" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, fuzzy, c-format msgid "Requires Power: %s" msgstr "Richiesto Potere Magico %d" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "Costo %d MP" #: ../../../src/MenuPowers.cpp:625 #, fuzzy, c-format msgid "Costs %d HP" msgstr "Costo %d MP" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "Congelamento: %d secondi" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "Condividere Stash" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "Ricomprare" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "Venditore" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "+%d scudi" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "Sei già trasformato, annulla trasformazione prima" #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "Avventuriero" #: ../../../src/Utils.cpp:519 #, fuzzy msgid "k" msgstr "Ok" #~ msgid "Character Menu (C)" #~ msgstr "Menu Carattere (C)" #~ msgid "Inventory Menu (I)" #~ msgstr "Inventario (I)" #~ msgid "Power Menu (P)" #~ msgstr "Menu Poteri(P)" #~ msgid "Log Menu (L)" #~ msgstr "Log Menu (L)" #, fuzzy #~ msgid "Each point of Physical grants +%d HP. Each level grants +%d HP" #~ msgstr "Perogni punto Fisico ottieni +4 HP in rigenerazione" #~ msgid "Ticks of HP regen per minute. Each point of Physical grants +%d HP regen. Each level grants +%d HP regen" #~ msgstr "HP rigenerati per minuto. Ogni punto Fisico garantisce +%d HP rigenerati, ogni livello garantisce +%d HP rigenerati" #, fuzzy #~ msgid "Each point of Mental grants +%d MP. Each level grants +%d MP" #~ msgstr "Perogni punto Mental ottieni +4 MP in rigenerazione" #~ msgid "Ticks of MP regen per minute. Each point of Mental grants +%d MP regen. Each level grants +%d MP regen" #~ msgstr "MP rigenerati per minuto. Ogni punto Mentale garantisce +%d MP rigenerati, ogni livello garantisce +%d MP rigenerati" #, fuzzy #~ msgid "Each point of Offense grants +%d accuracy. Each level grants +%d accuracy" #~ msgstr "Perogni punto Offensivo ottieni +5 in precisione" #, fuzzy #~ msgid "Each point of Defense grants +%d avoidance. Each level grants +%d avoidance" #~ msgstr "Perogni punto Defense ottieni +5 in schivare" #~ msgid "Requires a physical weapon" #~ msgstr "Richiesta arma da mischia" #~ msgid "Requires a mental weapon" #~ msgstr "Richiesta arma magica" #~ msgid "Requires an offense weapon" #~ msgstr "Richiesta arma da lancio" #~ msgid "Flare" #~ msgstr "Flare" #, fuzzy #~ msgid "Accuracy (vs lvl 5):" #~ msgstr "Precisione vs. Dif 1" #, fuzzy #~ msgid "Avoidance (vs lvl 5):" #~ msgstr "Schivare vs. Off 1" #~ msgid "Stats" #~ msgstr "Statistiche" #~ msgid "Grand Master" #~ msgstr "Grande Maestro" #~ msgid "Master" #~ msgstr "Maestro" #~ msgid "Warrior" #~ msgstr "Guerriero" #~ msgid "Wizard" #~ msgstr "Stegone" #~ msgid "Ranger" #~ msgstr "Guardiacaccia" #~ msgid "Paladin" #~ msgstr "Paladino" #~ msgid "Rogue" #~ msgstr "Bardo" #~ msgid "Knight" #~ msgstr "Cavaliere" #~ msgid "Shaman" #~ msgstr "Shamano" #~ msgid "Cleric" #~ msgstr "Chierico" #~ msgid "Battle Mage" #~ msgstr "Mago" #~ msgid "Heavy Archer" #~ msgstr "Archere" #~ msgid "You receive %d gold." #~ msgstr "Ricevi %d oro." #~ msgid "Press a key to assign: " #~ msgstr "Premere un tasto per assegnare:" #~ msgid "Activate >>" #~ msgstr "Attivare >>" #~ msgid "Create Character" #~ msgstr "Creareti il tuo Carattere" #~ msgid "Main Hand" #~ msgstr "Mano Princiale" #~ msgid "Body" #~ msgstr "Busto" #~ msgid "Off Hand" #~ msgstr "Mano Secondaria" #~ msgid "Artifact" #~ msgstr "Artefatto" #~ msgid "Consumable" #~ msgstr "Consumabile" #~ msgid "Gem" #~ msgstr "Gemma" #~ msgid "Quest Item" #~ msgstr "Oggetto della missione" #~ msgid "%d Gold" #~ msgstr "%d Oro" #~ msgid "Total HP" #~ msgstr "Totale HP" #~ msgid "Total MP" #~ msgstr "Totale MP" #~ msgid "vs. Def 5" #~ msgstr "vs. Dif 5" #~ msgid "vs. Off 5" #~ msgstr "vs. Off 5" #~ msgid "Main Weapon" #~ msgstr "Arma principale" #~ msgid "Ranged Weapon" #~ msgstr "Arma a distanza" #~ msgid "Crit Chance" #~ msgstr "Colpo Critico" #~ msgid "Fire Resist" #~ msgstr "Resistenza al Fuoco" #~ msgid "Ice Resist" #~ msgstr "Resistenza al Freddo" #~ msgid "Each level grants +1 HP regen" #~ msgstr "Ogni Livello ottieni +1 HP in rigenerazione" #~ msgid "Each level grants +2 MP" #~ msgstr "Ogni Livello ottieni +2 MP" #~ msgid "Each level grants +1 MP regen" #~ msgstr "Ogni Livello ottieni +1 MP in rigenerazione" #~ msgid "Each level grants +1 accuracy" #~ msgstr "Ogni Livello ottieni +1 in precisione" #~ msgid "Each level grants +1 avoidance" #~ msgstr "Ogni Livello ottieni +1 in schivare" #~ msgid "Dagger Proficiency" #~ msgstr "Competenza utilizzo Pugnali" #~ msgid "Shortsword Proficiency" #~ msgstr "Competenza utilizzo Spada Corta" #~ msgid "Longsword Proficiency" #~ msgstr "Competenza utilizzo Spada Lunga" #~ msgid "Greatsword Proficiency" #~ msgstr "Competenza utilizzo Spadone a due mani" #~ msgid "Wand Proficiency" #~ msgstr "Competenza utilizzo Bachetta Magica" #~ msgid "Rod Proficiency" #~ msgstr "Competenza utilizzo Verga" #~ msgid "Staff Proficiency" #~ msgstr "Competenza utilizzo Staffa" #~ msgid "Greatstaff Proficiency" #~ msgstr "Competenza utilizzo Grade Staffa" #~ msgid "Slingshot Proficiency" #~ msgstr "Competenza utilizzo Fionda" #~ msgid "Shortbow Proficiency" #~ msgstr "Competenza utilizzo Arco Corto" #~ msgid "Longbow Proficiency" #~ msgstr "Competenza utilizzo Arco Lungo" #~ msgid "Greatbow Proficiency" #~ msgstr "Competenza utilizzo Arco da Guerra" #~ msgid "Light Armor Proficiency" #~ msgstr "Competenza utilizzo Armatura Leggera" #~ msgid "Light Shield Proficiency" #~ msgstr "Competenza utilizzo Scudo Leggero" #~ msgid "Heavy Armor Proficiency" #~ msgstr "Competenza utilizzo Armatura Pesante" #~ msgid "Heavy Shield Proficiency" #~ msgstr "Competenza utilizzo Scudo Pesante" #~ msgid "Messages" #~ msgstr "Messaggio" #~ msgid "Physical + Offense grants melee and ranged attacks" #~ msgstr "Fisico + Offensivo ottieni attacchi da mischia e da lancio" #~ msgid "Physical + Defense grants melee protection" #~ msgstr "Fisico + Difensivo ottieni protezione in mischia" #~ msgid "Mental + Offense grants elemental spell attacks" #~ msgstr "Magico + Offensivo ottieni incantesimi di attacco elemntale" #~ msgid "Mental + Defense grants healing and magical protection" #~ msgstr "Magico + Difensivo ottieni incantesimi di guarigione e protezione" flare-engine-0.19/mods/default/languages/engine.ja.po000066400000000000000000000744521224717101500225450ustar00rootroot00000000000000# FLARE (Free/Libre Action RPG Engine) # Copyright (C) 2011 Clint Bellanger # This file is distributed under the same license as the FLARE package. # Paul Wortmann (RoboPaul) , 2011. msgid "" msgstr "" "Project-Id-Version: 0.17\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2013-03-21 11:18+0900\n" "Last-Translator: Paul Wortmann \n" "Language-Team: Paul Wortmann \n" "Language: Japanese\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.5.5\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "おめでとう、あなたはレベル %d に達している!" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "あなたは、文字のメニューを介して1つの属性を高める可能性があります。" #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "あなたは敗北している。ゲームオーバー! Enterキーを押して続行します。" #: ../../../src/Avatar.cpp:634 #, fuzzy msgid "You are defeated. Press Enter to continue." msgstr "あなたは敗北している。あなたは半分自分の%sを失う。 Enterキーを押して続行します。" #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "" #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "" #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "あなたは %s を受け取る。" #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "あなたは %s %d の を受け取る。" #: ../../../src/CampaignManager.cpp:168 #, c-format msgid "You receive %d %s." msgstr "あなたは %d %s を受け取る。" #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "あなたは %d XPを受け取ります。" #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "HPが回復した" #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "MPが回復した" #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "HPとMPが回復した" #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "負の影響は排除" #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "HPとMP復元、削除の負の効果" #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "ミス" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "+%d HP" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "+%d MP" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "未知の目的地" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "オーケ" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "デフォルト" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "キャンセル" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "ビデオ" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "オーディオ" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "インタフェース" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "入力" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "キー設定" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "モッズ" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "割り当てる:" #: ../../../src/GameStateConfig.cpp:165 msgid "Reset ALL settings?" msgstr "すべての設定をリセット?" #: ../../../src/GameStateConfig.cpp:166 msgid "Use this resolution?" msgstr "この解像度を使うのか?" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "フルスクリーンモード" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "マウスでキャラクターを動かす" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "戦闘のテキストを表示" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "ハードウェアサーフェス" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "ダブルバッファリング" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "ジョイスティックを使用する" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "高品質のテクスチャ" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "ガンマの変更許可" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "アニメーション·タイル" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "マウスの狙い" #: ../../../src/GameStateConfig.cpp:318 #, fuzzy msgid "Do not use mouse" msgstr "マウスでキャラクターを動かす" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "FPSを表示" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "音楽の音量" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "効果音の音量" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "ガンマ" #: ../../../src/GameStateConfig.cpp:377 #, fuzzy msgid "Joystick Deadzone" msgstr "ジョイスティック" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "解像度" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "アクティブモッズ" #: ../../../src/GameStateConfig.cpp:412 msgid "Available Mods" msgstr "利用可能モッズ" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "ジョイスティック" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "言語" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 msgid "Disable for performance" msgstr "パフォーマンスのために無効にする" #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "実験的" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "" #: ../../../src/GameStateConfig.cpp:527 msgid "<< Disable" msgstr "<<は無効" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr ">>を有効に" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "セーブゲームを削除する" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "このセーブゲームを削除しますか" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "タイトルに戻ります。" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "スロットを選択します。" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "新しいゲーム。" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "継続する話モッズを有効に" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "ロードゲーム。" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "ゲームの世界に入る…" #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "保存したゲームをロードする..." #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "レベル %d %s" #: ../../../src/GameStateLoad.cpp:579 #, fuzzy msgid "Permadeath" msgstr "死永久?" #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "空のスロット。" #: ../../../src/GameStateNew.cpp:62 msgid "Create" msgstr "作る" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "画像を選択します。" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "名前を選択します。" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "死永久?" #: ../../../src/GameStateNew.cpp:179 msgid "Choose a Class" msgstr "クラスを選択" #: ../../../src/GameStatePlay.cpp:99 msgid "Loading..." msgstr "読み込んでいます..." #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "インベントリがいっぱいです。" #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "ゲームをプレイ" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "継続するコアモッズを有効に" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "設定" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "ゲームを終了します" #: ../../../src/GameStateTitle.cpp:67 #, fuzzy msgid "Flare Alpha v0.19" msgstr "フレア 0.18 (アルファ)" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "受け入れる" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "上" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "下" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "左" #: ../../../src/InputState.cpp:627 msgid "Right" msgstr "右" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "バー1" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "バー2" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "バー3" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "バー4" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "バー5" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "バー6" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "バー7" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "バー8" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "バー9" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "バー0" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "キャラクター" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "在庫品" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "能力" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "ログ" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "メイン1" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "メイン2" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "\tコントロール" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "シフト" #: ../../../src/InputState.cpp:646 msgid "Delete" msgstr "削除する" #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "マウスの左ボタン" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "マウスの中ボタン" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "マウスの右ボタン" #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "マウスホイールアップ" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "マウスホイールダウン" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "マウスのX1ボタン" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "マウスのX2ボタン" #: ../../../src/ItemManager.cpp:488 #, fuzzy msgid "Low" msgstr "ログ" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "レベル %d" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "近接攻撃ダメージ: %d-%d" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "近接攻撃ダメージ: %d" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "飛ダメージ: %d-%d" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "飛ダメージ: %d" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "精神ダメージ: %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "精神ダメージ: %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "吸収: %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "吸収: %d" #: ../../../src/ItemManager.cpp:554 #, fuzzy, c-format msgid "%d% Speed" msgstr "%dスピード" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "増加 %s で %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "軽減 %s で %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "%d の物理が必要です。" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "%d 精神が必要です。" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "%d 犯罪が必要です。" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "%d 防衛が必要です。" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, c-format msgid "Buy Price: %d %s" msgstr "価格を購入する: %d %s金" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, c-format msgid "Buy Price: %d %s each" msgstr "価格を購入する: %d %s金の各" #: ../../../src/ItemManager.cpp:643 #, c-format msgid "Sell Price: %d %s" msgstr "価格を販売: %d %s金" #: ../../../src/ItemManager.cpp:645 #, c-format msgid "Sell Price: %d %s each" msgstr "価格を販売: %d %s金の各" #: ../../../src/ItemManager.cpp:655 msgid "Set: " msgstr "次: " #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "%d アイテム:" #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "名" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "レベル" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "物理" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "精神" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "犯罪" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "防衛" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "残りのポイント" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "最大HP:" #: ../../../src/MenuCharacter.cpp:340 msgid "HP Regen:" msgstr "HP再生" #: ../../../src/MenuCharacter.cpp:341 #, fuzzy msgid "Ticks of HP regen per minute. " msgstr "HPのダニは、毎分生成。" #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "最大MP:" #: ../../../src/MenuCharacter.cpp:352 msgid "MP Regen:" msgstr "MP再生" #: ../../../src/MenuCharacter.cpp:353 #, fuzzy msgid "Ticks of MP regen per minute. " msgstr "MPのダニは、毎分生成。" #: ../../../src/MenuCharacter.cpp:358 msgid "Accuracy:" msgstr "精度:" #: ../../../src/MenuCharacter.cpp:364 msgid "Avoidance:" msgstr "回避:" #: ../../../src/MenuCharacter.cpp:370 msgid "Melee Damage:" msgstr "近接攻撃ダメージ:" #: ../../../src/MenuCharacter.cpp:380 msgid "Ranged Damage:" msgstr "飛ダメージ:" #: ../../../src/MenuCharacter.cpp:390 msgid "Mental Damage:" msgstr "精神ダメージ:" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "クリティカル:" #: ../../../src/MenuCharacter.cpp:406 msgid "Absorb:" msgstr "吸収" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "ポイズ:" #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "打ったときつまずきのあなたのチャンスを低減" #: ../../../src/MenuCharacter.cpp:422 #, fuzzy msgid "Bonus XP: " msgstr "ボーナス" #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "XPは殺すごとに獲得増加" #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "ボーナス" #: ../../../src/MenuCharacter.cpp:429 #, c-format msgid "Increases the %s found per drop" msgstr "%sはドロップごと見つかっ増加" #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "ボーナスアイテムを見つける:" #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "殺されたときに敵がアイテムをドロップする可能性が高いでしょう" #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "ステルス:" #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "検出されず移動する能力を増大させる" #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "%d の経験" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "次: %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "物理(P)は、近接武器の熟練度と合計HPを増加させる。" #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "基本 (%d), ボーナス (%d)" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "精神的な(M)は、精神的な武器の熟練度と全体のMPを増加させる。" #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "犯罪(O)は、遠隔武器の熟練度と精度を向上させます。" #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "防衛(D)は、鎧の習熟度と回避を増加させる。" #: ../../../src/MenuCharacter.cpp:498 #, fuzzy, c-format msgid "Each level grants %d. " msgstr "各レベルは、HPの+2点が付与されます。" #: ../../../src/MenuCharacter.cpp:500 #, fuzzy, c-format msgid "Each point of Physical grants %d. " msgstr "物理的な助成金のHPの+8点の各点。" #: ../../../src/MenuCharacter.cpp:502 #, fuzzy, c-format msgid "Each point of Mental grants %d. " msgstr "精神助成金+8 MPの各点。" #: ../../../src/MenuCharacter.cpp:504 #, fuzzy, c-format msgid "Each point of Offense grants %d. " msgstr "精神助成金+8 MPの各点。" #: ../../../src/MenuCharacter.cpp:506 #, fuzzy, c-format msgid "Each point of Defense grants %d. " msgstr "精神助成金+8 MPの各点。" #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "死んだ" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "%s レベル %d" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "終了" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "保存し、タイトルメニューに終了しますか" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "" #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "" #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "" #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "" #: ../../../src/MenuInventory.cpp:228 #, c-format msgid "%d %s" msgstr "%d %s" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "一つの項目だけを移動するにはSHIFTキーを使用してください。" #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "CTRL-クリックして販売する実施項目を。" #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "この項目は、アクションバーから使用することができます。" #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "注釈" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "クエスト" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "XP側:%d/%dの" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, fuzzy, c-format msgid "Not enough %s." msgstr "お金が足りない" #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "" #: ../../../src/MenuPowers.cpp:463 msgid "Unspent skill points:" msgstr "未使用のスキルポイント:" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" #: ../../../src/MenuPowers.cpp:525 #, fuzzy, c-format msgid "Requires a %s" msgstr "%d 精神が必要です。" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "物理攻撃 %d が必要です。" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "物理防御 %d が必要です。" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "精神攻撃 %d が必要です。" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "精神的な防衛 %d が必要です。" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, c-format msgid "Requires Level %d" msgstr "レベル%dが必要です" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, c-format msgid "Requires %d Skill Point" msgstr "%d個のスキルポイントが必要です" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "ロックを解除するにはクリック" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, c-format msgid "Requires Power: %s" msgstr "%s 精神が必要です。" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "費用は、%d はMPです。" #: ../../../src/MenuPowers.cpp:625 #, c-format msgid "Costs %d HP" msgstr "%dのHPが必要" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "クールダウンは%d秒" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "共有スタッシュ" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "買い戻し" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "売手" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "+%d シールド" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "あなたは、すでに最初の非変換、変換されます" #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "冒険家" #: ../../../src/Utils.cpp:519 #, fuzzy msgid "k" msgstr "オーケ" #~ msgid "Character Menu (C)" #~ msgstr "キャラクターのメニュー (C)" #~ msgid "Inventory Menu (I)" #~ msgstr "在庫メニュー (I)" #~ msgid "Power Menu (P)" #~ msgstr "能力のメニュー (P)" #~ msgid "Log Menu (L)" #~ msgstr "ログのメニュー (L)" #~ msgid "Each point of Physical grants +%d HP. Each level grants +%d HP" #~ msgstr "物理的な助成金の各ポイント+%d個のHP。各レベルの権限付与+%dは、HP" #~ msgid "Ticks of HP regen per minute. Each point of Physical grants +%d HP regen. Each level grants +%d HP regen" #~ msgstr "分当たりHP自然回復。物理的な助成金の各点は、+%dのHP自然回復。各レベルの権限付与+%dは、HP自然回復" #~ msgid "Each point of Mental grants +%d MP. Each level grants +%d MP" #~ msgstr "精神的な助成金の各ポイント+%d個のMP。各レベルの権限付与は+%dはMP" #~ msgid "Ticks of MP regen per minute. Each point of Mental grants +%d MP regen. Each level grants +%d MP regen" #~ msgstr "毎分MP自然回復。精神的な助成金の各点は、+%d個のMP自然回復。各レベルの権限付与+%dのMP自然回復" #~ msgid "Each point of Offense grants +%d accuracy. Each level grants +%d accuracy" #~ msgstr "犯罪の助成金の各点は、+%d個の精度。各レベルは+%dの精度を付与" #~ msgid "Each point of Defense grants +%d avoidance. Each level grants +%d avoidance" #~ msgstr "防衛補助金の各点は、+%dは回避。各レベルの権限付与は+%dの回避" #~ msgid "Requires a physical weapon" #~ msgstr "物理的な武器が必要です。" #~ msgid "Requires a mental weapon" #~ msgstr "精神的な武器が必要です。" #~ msgid "Requires an offense weapon" #~ msgstr "攻撃武器が必要です。" #~ msgid "Flare" #~ msgstr "フレア" #, fuzzy #~ msgid "Accuracy (vs lvl 5):" #~ msgstr "精度対防衛1" #, fuzzy #~ msgid "Avoidance (vs lvl 5):" #~ msgstr "回避対犯罪1" #, fuzzy #~ msgid "Stats" #~ msgstr "統計情報" #~ msgid "Grand Master" #~ msgstr "グランドマスター" #~ msgid "Master" #~ msgstr "マスター" #~ msgid "Warrior" #~ msgstr "戦士" #~ msgid "Wizard" #~ msgstr "魔女" #~ msgid "Ranger" #~ msgstr "射手" #~ msgid "Paladin" #~ msgstr "英雄" #~ msgid "Rogue" #~ msgstr "泥棒" #~ msgid "Knight" #~ msgstr "騎士" #~ msgid "Shaman" #~ msgstr "シャーマン" #~ msgid "Cleric" #~ msgstr "聖職者" #~ msgid "Battle Mage" #~ msgstr "バトルメイジ" #~ msgid "Heavy Archer" #~ msgstr "強い射手" #~ msgid "You receive %d gold." #~ msgstr "あなたは %d 金を受け取ります。" #~ msgid "Create Character" #~ msgstr "キャラクタを作成する。" #~ msgid "Main Hand" #~ msgstr "主な手" #~ msgid "Body" #~ msgstr "体" #~ msgid "Off Hand" #~ msgstr "第二の手" #~ msgid "Artifact" #~ msgstr "骨董" #~ msgid "Consumable" #~ msgstr "消耗品" #~ msgid "Gem" #~ msgstr "原石" #~ msgid "Quest Item" #~ msgstr "探求のもの" #~ msgid "%d Gold" #~ msgstr "%d 金" #~ msgid "Total HP" #~ msgstr "HPの全部" #~ msgid "Total MP" #~ msgstr "MPの全部" #~ msgid "vs. Def 5" #~ msgstr "防衛5対" #~ msgid "vs. Off 5" #~ msgstr "対犯罪5" #~ msgid "Main Weapon" #~ msgstr "主な武器" #~ msgid "Ranged Weapon" #~ msgstr "遠隔武器" #~ msgid "Crit Chance" #~ msgstr "重要走向確率" #~ msgid "Fire Resist" #~ msgstr "耐火" #~ msgid "Ice Resist" #~ msgstr "氷への抵抗" #~ msgid "Each level grants +1 HP regen" #~ msgstr "各レベルは+1 HPの再生を許可します。" #~ msgid "Each level grants +2 MP" #~ msgstr "各レベルは+2 MPを与えます。" #~ msgid "Each level grants +1 MP regen" #~ msgstr "各レベルは、+1 MP再生を与えます。" #~ msgid "Each level grants +1 accuracy" #~ msgstr "各レベルは+1の精度を与えます。" #~ msgid "Each level grants +1 avoidance" #~ msgstr "各レベルは+1回避を与えます。" #~ msgid "Dagger Proficiency" #~ msgstr "ダガー能力。" #~ msgid "Shortsword Proficiency" #~ msgstr "短い剣の能力。" #~ msgid "Longsword Proficiency" #~ msgstr "長い剣の能力。" #~ msgid "Greatsword Proficiency" #~ msgstr "偉大な剣の能力。" #~ msgid "Wand Proficiency" #~ msgstr "ワンド能力。" #~ msgid "Rod Proficiency" #~ msgstr "ロッド能力。" #~ msgid "Staff Proficiency" #~ msgstr "スタッフの能力。" #~ msgid "Greatstaff Proficiency" #~ msgstr "素晴らしいスタッフの能力。" #~ msgid "Slingshot Proficiency" #~ msgstr "スリングショット能力。" #~ msgid "Shortbow Proficiency" #~ msgstr "短弓の能力。" #~ msgid "Longbow Proficiency" #~ msgstr "長い弓の能力。" #~ msgid "Greatbow Proficiency" #~ msgstr "偉大な弓の能力。" #~ msgid "Light Armor Proficiency" #~ msgstr "軽装鎧の能力。" #~ msgid "Light Shield Proficiency" #~ msgstr "遮光能力。" #~ msgid "Heavy Armor Proficiency" #~ msgstr "重い鎧の能力。" #~ msgid "Heavy Shield Proficiency" #~ msgstr "重い遮蔽能力。" #~ msgid "Messages" #~ msgstr "メッセージ" #~ msgid "Physical + Offense grants melee and ranged attacks" #~ msgstr "物理的および犯罪の助成金メレーと遠隔攻撃。" #~ msgid "Physical + Defense grants melee protection" #~ msgstr "物理的および防衛の補助金の近接防御。" #~ msgid "Mental + Offense grants elemental spell attacks" #~ msgstr "精神と犯罪の助成金元素の呪文攻撃を。" #~ msgid "Mental + Defense grants healing and magical protection" #~ msgstr "精神的、防衛の補助金の治癒と魔法防御。" flare-engine-0.19/mods/default/languages/engine.nb.po000066400000000000000000000525501224717101500225450ustar00rootroot00000000000000# Norwegian Bokmal translations for FLARE (Free/Libre Action RPG Engine). # Copyright (C) 2012 Clint Bellanger # This file is distributed under the same license as the FLARE package. # Hans Joachim Desserud , 2012. msgid "" msgstr "" "Project-Id-Version: Flare 0.19\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2012-12-24 14:36+0100\n" "Last-Translator: Hans Joachim Desserud \n" "Language-Team: Norwegian Bokmal\n" "Language: nb\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "Gratulerer, du har nådd nivå %d!" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "" #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "" #: ../../../src/Avatar.cpp:634 msgid "You are defeated. Press Enter to continue." msgstr "Du har blitt beseiret. Trykk Enter for å fortsette." #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "%d %s fjernet." #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "%s fjernet." #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "Du mottar %s." #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "Du mottar %s x%d." #: ../../../src/CampaignManager.cpp:168 #, c-format msgid "You receive %d %s." msgstr "Du mottar %s x%d." #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "" #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "" #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "" #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "" #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "Negative effekter fjernet." #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "" #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "bom" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "Ukjent destinasjon" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "Ok" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "Standard" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "Avbryt" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "Video" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "Lyd" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "Grensesnitt" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "Hurtigtaster" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "Tildel: " #: ../../../src/GameStateConfig.cpp:165 msgid "Reset ALL settings?" msgstr "Still tilbake ALLE innstillinger?" #: ../../../src/GameStateConfig.cpp:166 msgid "Use this resolution?" msgstr "Behold denne oppløsningen?" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "Fullskjerm" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "Flytt helten med musepeker" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "Vis tekst i kamp" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "Bruk joystick" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "Animerte fliser" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "Sikte med musepekeren" #: ../../../src/GameStateConfig.cpp:318 msgid "Do not use mouse" msgstr "Ikke bruk mus" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "Vis hurtigtaster" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "Modus for fargeblinde" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "Musikkvolum" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "Lydvolum" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "" #: ../../../src/GameStateConfig.cpp:377 msgid "Joystick Deadzone" msgstr "" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "Oppløsning" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "" #: ../../../src/GameStateConfig.cpp:412 msgid "Available Mods" msgstr "" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "Joystick" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "Språk" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 msgid "Disable for performance" msgstr "" #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "Eksperimentell" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "For håndholdte enheter" #: ../../../src/GameStateConfig.cpp:527 msgid "<< Disable" msgstr "<< Deaktiver" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr "Aktiver >>" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "Slett lagret spill" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "Slett dette spillet?" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "Avslutt til hovedmeny" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "Velg en plass" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "Nytt spill" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "Last spill" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "Åpner spillverden..." #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "Laster lagret spill..." #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "Nivå %d %s" #: ../../../src/GameStateLoad.cpp:579 msgid "Permadeath" msgstr "Permanent død" #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "Ledig plass" #: ../../../src/GameStateNew.cpp:62 msgid "Create" msgstr "Opprett" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "Velg et portrett" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "Velg et navn" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "Permanent død?" #: ../../../src/GameStateNew.cpp:179 msgid "Choose a Class" msgstr "Velg en klasse" #: ../../../src/GameStatePlay.cpp:99 msgid "Loading..." msgstr "Laster..." #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "Du har ikke plass til flere gjenstander." #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "Start spill" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "Innstillinger" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "Avslutt spill" #: ../../../src/GameStateTitle.cpp:67 msgid "Flare Alpha v0.19" msgstr "Flare alfa v0.19" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "Godta" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "Opp" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "Ned" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "Venstre" #: ../../../src/InputState.cpp:627 msgid "Right" msgstr "Høyre" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "Karakter" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "Krefter" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "Logg" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "Hoved1" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "Hoved2" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "" #: ../../../src/InputState.cpp:646 msgid "Delete" msgstr "" #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "venstre museknapp" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "midterste museknapp" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "høyre museknapp" #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "hjul opp" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "hjul ned" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "museknappx1" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "museknappx2" #: ../../../src/ItemManager.cpp:488 msgid "Low" msgstr "Dårlig" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "Normal" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "Høy" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "Episk" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "Nivå %d" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "Mental skade: %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "Mental skade: %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "Absorberer: %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "Absorberer: %d" #: ../../../src/ItemManager.cpp:554 #, c-format msgid "%d% Speed" msgstr "%d% Hastighet" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "Øker %s med %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "Reduserer %s by %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "Kvalitet: %s" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, c-format msgid "Buy Price: %d %s" msgstr "Kjøp for: %d %s" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, c-format msgid "Buy Price: %d %s each" msgstr "Kjøp for: %d %s hver" #: ../../../src/ItemManager.cpp:643 #, c-format msgid "Sell Price: %d %s" msgstr "Selg for: %d %s" #: ../../../src/ItemManager.cpp:645 #, c-format msgid "Sell Price: %d %s each" msgstr "Selg for: %d %s hver" #: ../../../src/ItemManager.cpp:655 msgid "Set: " msgstr "Sett: " #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "%d gjenstander: " #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "Navn" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "Nivå" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "ubrukte poeng" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "" #: ../../../src/MenuCharacter.cpp:340 msgid "HP Regen:" msgstr "" #: ../../../src/MenuCharacter.cpp:341 msgid "Ticks of HP regen per minute. " msgstr "" #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "" #: ../../../src/MenuCharacter.cpp:352 msgid "MP Regen:" msgstr "" #: ../../../src/MenuCharacter.cpp:353 msgid "Ticks of MP regen per minute. " msgstr "" #: ../../../src/MenuCharacter.cpp:358 msgid "Accuracy:" msgstr "Treffsikkerhet" #: ../../../src/MenuCharacter.cpp:364 msgid "Avoidance:" msgstr "" #: ../../../src/MenuCharacter.cpp:370 msgid "Melee Damage:" msgstr "" #: ../../../src/MenuCharacter.cpp:380 msgid "Ranged Damage:" msgstr "" #: ../../../src/MenuCharacter.cpp:390 msgid "Mental Damage:" msgstr "Mental skade:" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "" #: ../../../src/MenuCharacter.cpp:406 msgid "Absorb:" msgstr "Absorberer:" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "Holdning: " #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "Reduserer sjansen for å snuble når du blir truffet" #: ../../../src/MenuCharacter.cpp:422 msgid "Bonus XP: " msgstr "" #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "" #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "Bonus" #: ../../../src/MenuCharacter.cpp:429 #, c-format msgid "Increases the %s found per drop" msgstr "" #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "" #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "" #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "" #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "" #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "Neste: %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "" #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "" #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "" #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "" #: ../../../src/MenuCharacter.cpp:498 #, c-format msgid "Each level grants %d. " msgstr "Hvert nivå gir %d. " #: ../../../src/MenuCharacter.cpp:500 #, c-format msgid "Each point of Physical grants %d. " msgstr "" #: ../../../src/MenuCharacter.cpp:502 #, c-format msgid "Each point of Mental grants %d. " msgstr "" #: ../../../src/MenuCharacter.cpp:504 #, c-format msgid "Each point of Offense grants %d. " msgstr "" #: ../../../src/MenuCharacter.cpp:506 #, c-format msgid "Each point of Defense grants %d. " msgstr "" #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "Død" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "%s nivå %d" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "Avslutt" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "Lagre og gå til hovedmeny?" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "Mistet %d%% of %s. " #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "" #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "" #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "Mistet %s." #: ../../../src/MenuInventory.cpp:228 #, c-format msgid "%d %s" msgstr "%d %s" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "Bruk SHIFT for å flytte en enkelt gjenstand." #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "CTRL-klikk på en gjenstand for å selge den." #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "" #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "Notater" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "Oppdrag" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, c-format msgid "Not enough %s." msgstr "Ikke nok %s." #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "" #: ../../../src/MenuPowers.cpp:463 msgid "Unspent skill points:" msgstr "" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" #: ../../../src/MenuPowers.cpp:525 #, c-format msgid "Requires a %s" msgstr "Krever en %s" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, c-format msgid "Requires Level %d" msgstr "Krever nivå %d" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, c-format msgid "Requires %d Skill Point" msgstr "" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, c-format msgid "Requires Power: %s" msgstr "" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "" #: ../../../src/MenuPowers.cpp:625 #, c-format msgid "Costs %d HP" msgstr "" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "+%d Skjold" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "" #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "Eventyrer" #: ../../../src/Utils.cpp:519 msgid "k" msgstr "" flare-engine-0.19/mods/default/languages/engine.nl.po000066400000000000000000000670711224717101500225630ustar00rootroot00000000000000# Copyright (C) 2012 Bas Doodeman # This file is distributed under the same license as the Flare package. # # Bas Doodeman , 2012. # msgid "" msgstr "" "Project-Id-Version: 0.16\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2012-08-23 21:23+0200\n" "Last-Translator: Bas Doodeman \n" "Language-Team: Dutch; Flemish <>\n" "Language: Dutch\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bits\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "Gefeliciteerd, je hebt niveau %d bereikt!" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "Je kunt één eigenschap in het karakter menu verhogen." #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "Je bent verslagen. Spel afgelopen! Druk op Enter, om naar het hoofdmenu terug te keren." #: ../../../src/Avatar.cpp:634 #, fuzzy msgid "You are defeated. Press Enter to continue." msgstr "Je bent verslagen. Je verliest de helft van je goud. Druk op Enter om verder te gaan." #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "" #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "" #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "Je ontvangt %s." #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "Je ontvangt %s x%d." #: ../../../src/CampaignManager.cpp:168 #, fuzzy, c-format msgid "You receive %d %s." msgstr "Je ontvangt %s." #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "Je ontvangt %d EP." #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "" #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "" #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "" #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "" #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "" #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "Onbekende bestemming" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "Standaardwaarden" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "Annuleren" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "Video" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "Audio" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "Omgeving" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "Invoer" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "Sneltoetsen" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "Mods" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "" #: ../../../src/GameStateConfig.cpp:165 #, fuzzy msgid "Reset ALL settings?" msgstr "ALLE instellingen terugzetten op de standaardwaarden?" #: ../../../src/GameStateConfig.cpp:166 #, fuzzy msgid "Use this resolution?" msgstr "Resolutie" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "Volledig scherm" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "Muisbesturing" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "Laat strijdtekst zien" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "Hardware oppervlakken" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "Dubbele buffering" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "Gebruik de Joystick" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "" #: ../../../src/GameStateConfig.cpp:318 #, fuzzy msgid "Do not use mouse" msgstr "Muisbesturing" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "Muziekvolume" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "Geluidsvolume" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "Gammacorrectie" #: ../../../src/GameStateConfig.cpp:377 #, fuzzy msgid "Joystick Deadzone" msgstr "Joystick" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "Resolutie" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "Actieve Mods" #: ../../../src/GameStateConfig.cpp:412 #, fuzzy msgid "Available Mods" msgstr "Beschikbare Mods" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "Joystick" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "Taal" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 #, fuzzy msgid "Disable for performance" msgstr "Uitschakelen kan presaties verbeteren" #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "" #: ../../../src/GameStateConfig.cpp:527 #, fuzzy msgid "<< Disable" msgstr "<< Deactiveren" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr "" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "Spel verwijderen" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "Dit spel werkelijk verwijderen?" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "Terug naar het menu" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "Kies een Slot" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "New Spel" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "Spel Laden" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "Betreden spelwereld..." #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "Laden opgeslagen spel..." #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "Niveau %d %s" #: ../../../src/GameStateLoad.cpp:579 #, fuzzy msgid "Permadeath" msgstr "Permanente dood?" #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "Leeg Slot" #: ../../../src/GameStateNew.cpp:62 #, fuzzy msgid "Create" msgstr "Karakter" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "Kies een Portret" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "Kies een Naam" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "Permanente dood?" #: ../../../src/GameStateNew.cpp:179 #, fuzzy msgid "Choose a Class" msgstr "Kies een Slot" #: ../../../src/GameStatePlay.cpp:99 #, fuzzy msgid "Loading..." msgstr "Laden opgeslagen spel..." #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "Geen ruimte meer." #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "Spel Spelen" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "Instellingen" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "Spel Stoppen" #: ../../../src/GameStateTitle.cpp:67 #, fuzzy msgid "Flare Alpha v0.19" msgstr "Flare Alpha v0.18" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "" #: ../../../src/InputState.cpp:627 #, fuzzy msgid "Right" msgstr "Ridder" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "Karakter" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "Voorraad" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "Vaardigheden" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "Log" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "" #: ../../../src/InputState.cpp:646 #, fuzzy msgid "Delete" msgstr "Spel verwijderen" #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "" #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "" #: ../../../src/ItemManager.cpp:488 #, fuzzy msgid "Low" msgstr "Log" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "Niveau %d" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "Mêleeschade: %d-%d" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "Mêleeschade: %d" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "Bereiksschade: %d-%d" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "Bereiksschade: %d" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "Mentale schade: %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "Mentale schade: %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "Absorbtie: %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "Absorbtie: %d" #: ../../../src/ItemManager.cpp:554 #, c-format msgid "%d% Speed" msgstr "" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "Verhoogd %s met %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "Verlaagd %s met %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "Vereist %d Fysiek" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "Vereist %d Mentaal" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "Vereist %d Aanval" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "Vereist %d Verdediging" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, fuzzy, c-format msgid "Buy Price: %d %s" msgstr "Aankoopprijs: %d goud" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, fuzzy, c-format msgid "Buy Price: %d %s each" msgstr "Aankoopprijs: %d goud per stuk" #: ../../../src/ItemManager.cpp:643 #, fuzzy, c-format msgid "Sell Price: %d %s" msgstr "Verkoopprijs: %d goud" #: ../../../src/ItemManager.cpp:645 #, fuzzy, c-format msgid "Sell Price: %d %s each" msgstr "Verkoopprijs: %d goud per stuk" #: ../../../src/ItemManager.cpp:655 #, fuzzy msgid "Set: " msgstr "Volgende: %d" #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "" #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "Naam" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "Niveau" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "Fysiek" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "Mentaal" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "Aanval" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "Verdediging" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "Punten resterend" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "" #: ../../../src/MenuCharacter.cpp:340 #, fuzzy msgid "HP Regen:" msgstr "Herstel" #: ../../../src/MenuCharacter.cpp:341 #, fuzzy msgid "Ticks of HP regen per minute. " msgstr "Herstel van TP per minuut" #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "" #: ../../../src/MenuCharacter.cpp:352 #, fuzzy msgid "MP Regen:" msgstr "Herstel" #: ../../../src/MenuCharacter.cpp:353 #, fuzzy msgid "Ticks of MP regen per minute. " msgstr "MP herstel per minuut" #: ../../../src/MenuCharacter.cpp:358 #, fuzzy msgid "Accuracy:" msgstr "Nwkeurigh tov. Verdg 1" #: ../../../src/MenuCharacter.cpp:364 #, fuzzy msgid "Avoidance:" msgstr "Ontweiking. tov. Aanv 1" #: ../../../src/MenuCharacter.cpp:370 #, fuzzy msgid "Melee Damage:" msgstr "Mêleeschade: %d" #: ../../../src/MenuCharacter.cpp:380 #, fuzzy msgid "Ranged Damage:" msgstr "Bereiksschade: %d" #: ../../../src/MenuCharacter.cpp:390 #, fuzzy msgid "Mental Damage:" msgstr "Mentale schade: %d" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "" #: ../../../src/MenuCharacter.cpp:406 #, fuzzy msgid "Absorb:" msgstr "Absorbtie" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "" #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "" #: ../../../src/MenuCharacter.cpp:422 msgid "Bonus XP: " msgstr "" #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "" #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "" #: ../../../src/MenuCharacter.cpp:429 #, fuzzy, c-format msgid "Increases the %s found per drop" msgstr "Verhoogd %s met %d" #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "" #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "" #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "" #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "" #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "EP: %d" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "Volgende: %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "Fysiek (P) verhoogd beheersing van mêlee wapens en maximale TP." #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "basis (%d), bonus (%d)" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "Mentaal (M) verhoogd beheersing van mentale wapens en maximale MP" #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "Aanval (A) verhoogd beheersing van bereikswapens en nauwkeurigheid." #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "Verdediging (V) verhoogd beheersing van wapenuitrusting en ontwijken." #: ../../../src/MenuCharacter.cpp:498 #, fuzzy, c-format msgid "Each level grants %d. " msgstr "Ieder niveau verhoogd TP met 2" #: ../../../src/MenuCharacter.cpp:500 #, fuzzy, c-format msgid "Each point of Physical grants %d. " msgstr "Ieder punt Fysiek verhoogd TP met 8" #: ../../../src/MenuCharacter.cpp:502 #, fuzzy, c-format msgid "Each point of Mental grants %d. " msgstr "Ieder punt Mentaal verhoogd MP met 8" #: ../../../src/MenuCharacter.cpp:504 #, fuzzy, c-format msgid "Each point of Offense grants %d. " msgstr "Ieder punt Mentaal verhoogd MP met 8" #: ../../../src/MenuCharacter.cpp:506 #, fuzzy, c-format msgid "Each point of Defense grants %d. " msgstr "Ieder punt Mentaal verhoogd MP met 8" #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "Dood" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "%s niveau %d" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "Stoppen" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "Opslaan en naar het hoofdmenu" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "" #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "" #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "" #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "" #: ../../../src/MenuInventory.cpp:228 #, fuzzy, c-format msgid "%d %s" msgstr "Niveau %d %s" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "Houd SHIFT ingedrukt, om slechts één artikel te verplaatsen." #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "Houd CTRL ingedrukt en klik op een artikel om het te verkopen." #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "Dit artikel kan alleen vanaf de actiebalk gebruikt worden." #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "Opdrachten" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "EP: %d/%d" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, c-format msgid "Not enough %s." msgstr "" #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "Handelen" #: ../../../src/MenuPowers.cpp:463 #, fuzzy msgid "Unspent skill points:" msgstr "Ongebruikte eigenschapspunten" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" #: ../../../src/MenuPowers.cpp:525 #, fuzzy, c-format msgid "Requires a %s" msgstr "Vereist %d Mentaal" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "Vereist %d Fysieke Aanval" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "Vereist %d Fysieke Verdediging" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "Vereist %d Mentale Aanval" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "Vereist %d Mentale Verdediging" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, fuzzy, c-format msgid "Requires Level %d" msgstr "Vereist %d Mentaal" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, fuzzy, c-format msgid "Requires %d Skill Point" msgstr "Vereist een fysiek wapen" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, fuzzy, c-format msgid "Requires Power: %s" msgstr "Vereist %d Mentaal" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "Kost %d MP" #: ../../../src/MenuPowers.cpp:625 #, fuzzy, c-format msgid "Costs %d HP" msgstr "Kost %d MP" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "Afkoeltijd: %d seconden" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "Verkoper" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "" #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "Avonturier" #: ../../../src/Utils.cpp:519 #, fuzzy msgid "k" msgstr "Accepteren" #~ msgid "Character Menu (C)" #~ msgstr "Karakter Menu (C)" #~ msgid "Inventory Menu (I)" #~ msgstr "Voorraad Menu (I)" #~ msgid "Power Menu (P)" #~ msgstr "Vaardigheden Menu (P)" #~ msgid "Log Menu (L)" #~ msgstr "Log Menu (L)" #, fuzzy #~ msgid "Each point of Physical grants +%d HP. Each level grants +%d HP" #~ msgstr "Ieder punt Fysiek verhoogd TP herstel met 4" #, fuzzy #~ msgid "Each point of Mental grants +%d MP. Each level grants +%d MP" #~ msgstr "Ieder punt mentaal verhoogd MP-herstel met 4" #, fuzzy #~ msgid "Each point of Offense grants +%d accuracy. Each level grants +%d accuracy" #~ msgstr "Ieder punt Aanval verhoogd nauwkeurigheid met 5" #, fuzzy #~ msgid "Each point of Defense grants +%d avoidance. Each level grants +%d avoidance" #~ msgstr "Ieder punt Verdediging verhoogd ontwijken met 5" #~ msgid "Requires a physical weapon" #~ msgstr "Vereist een fysiek wapen" #~ msgid "Requires a mental weapon" #~ msgstr "Vereist een mentaal wapen" #~ msgid "Requires an offense weapon" #~ msgstr "Vereist een aanvallend wapen" #~ msgid "Flare" #~ msgstr "Flare" #, fuzzy #~ msgid "Accuracy (vs lvl 5):" #~ msgstr "Nwkeurigh tov. Verdg 1" #, fuzzy #~ msgid "Avoidance (vs lvl 5):" #~ msgstr "Ontweiking. tov. Aanv 1" #, fuzzy #~ msgid "Stats" #~ msgstr "Statistieken" #~ msgid "Grand Master" #~ msgstr "Grootmeester" #~ msgid "Master" #~ msgstr "Meester" #~ msgid "Warrior" #~ msgstr "Strijder" #~ msgid "Wizard" #~ msgstr "Magiër" #~ msgid "Ranger" #~ msgstr "Woudloper" #~ msgid "Paladin" #~ msgstr "Paladin" #~ msgid "Rogue" #~ msgstr "Schurk" #~ msgid "Knight" #~ msgstr "Ridder" #~ msgid "Shaman" #~ msgstr "Sjaman" #~ msgid "Cleric" #~ msgstr "Priester" #~ msgid "Battle Mage" #~ msgstr "Strijdmagiër" #~ msgid "Heavy Archer" #~ msgstr "Scherpschutter" #~ msgid "You receive %d gold." #~ msgstr "Je ontvangt %d goud." #~ msgid "Press a key to assign: " #~ msgstr "Druk een toets om toe te kennen: " #~ msgid "Activate >>" #~ msgstr "Activeren >>" #~ msgid "Create Character" #~ msgstr "Karakter Aanmaken" #~ msgid "Main Hand" #~ msgstr "Wapenhand" #~ msgid "Body" #~ msgstr "Lichaam" #~ msgid "Off Hand" #~ msgstr "Schildhand" #~ msgid "Artifact" #~ msgstr "Artefact" #~ msgid "Consumable" #~ msgstr "Verbruiksartikel" #~ msgid "Gem" #~ msgstr "Edelsteen" #~ msgid "Quest Item" #~ msgstr "Opdracht gerelateerd artikel" #~ msgid "%d Gold" #~ msgstr "%d Goud" #~ msgid "Total HP" #~ msgstr "Totale TP" #~ msgid "Total MP" #~ msgstr "Totale MP" #~ msgid "vs. Def 5" #~ msgstr "tov. Verdg 5" #~ msgid "vs. Off 5" #~ msgstr "tov. Aanv 5" #~ msgid "Main Weapon" #~ msgstr "Hoofdwapen" #~ msgid "Ranged Weapon" #~ msgstr "Bereikswapen" #~ msgid "Crit Chance" #~ msgstr "Fataal Kans" #~ msgid "Fire Resist" #~ msgstr "Vuurweerstand" #~ msgid "Ice Resist" #~ msgstr "IJsweerstand" #~ msgid "Each level grants +1 HP regen" #~ msgstr "Ieder niveau verhoogd TP herstel met 1" #~ msgid "Each level grants +2 MP" #~ msgstr "Ieder niveau verhoogd MP met 2" #~ msgid "Each level grants +1 MP regen" #~ msgstr "Ieder niveau verhoogd MP herstel met 1" #~ msgid "Each level grants +1 accuracy" #~ msgstr "Ieder niveai verhoogd nauwkeurigheid met 1" #~ msgid "Each level grants +1 avoidance" #~ msgstr "Ieder niveau verhoogd ontwijken met 1" #~ msgid "Dagger Proficiency" #~ msgstr "Bekwaamheid: Dolk" #~ msgid "Shortsword Proficiency" #~ msgstr "Bekwaamheid: Kort Zwaard" #~ msgid "Longsword Proficiency" #~ msgstr "Bekwaamheid: Lang Zwaard" #~ msgid "Greatsword Proficiency" #~ msgstr "Bekwaamheid: Grootzwaard" #~ msgid "Wand Proficiency" #~ msgstr "Bekwaamheid: Toverstok" #~ msgid "Rod Proficiency" #~ msgstr "Bekwaamheid: Staaf" #~ msgid "Staff Proficiency" #~ msgstr "Bekwaamheid: Staf" #~ msgid "Greatstaff Proficiency" #~ msgstr "Bekwaamheid: Grootstaf" #~ msgid "Slingshot Proficiency" #~ msgstr "Bekwaamheid: Katapult" #~ msgid "Shortbow Proficiency" #~ msgstr "Bekwaamheid: Korte Boog" #~ msgid "Longbow Proficiency" #~ msgstr "Bekwaamheid: Lange boog" #~ msgid "Greatbow Proficiency" #~ msgstr "Bekwaamheid: Grote Boog" #~ msgid "Light Armor Proficiency" #~ msgstr "Bekwaamheid: Lichte Wapenuitrusting" #~ msgid "Light Shield Proficiency" #~ msgstr "Bekwaamheid: Licht schild" #~ msgid "Heavy Armor Proficiency" #~ msgstr "Bekwaamheid: Zware Wapenuitrusting" #~ msgid "Heavy Shield Proficiency" #~ msgstr "Bekwaamheid: Zwaar Schild" #~ msgid "Messages" #~ msgstr "Berichten" #~ msgid "Physical + Offense grants melee and ranged attacks" #~ msgstr "Fysiek + Aanval geeft mêlee- en bereiksaanvallen." #~ msgid "Physical + Defense grants melee protection" #~ msgstr "Fysiek + Verdediging geeft mêlee bescherming" #~ msgid "Mental + Offense grants elemental spell attacks" #~ msgstr "Mentaal + Aanval geeft aanvallende element magie" #~ msgid "Mental + Defense grants healing and magical protection" #~ msgstr "Mentaal + Verdediging geeft genezen en magische bescherming" flare-engine-0.19/mods/default/languages/engine.pl.po000066400000000000000000000625111224717101500225570ustar00rootroot00000000000000# Copyright (C) 2013 Paweł Puszczyński # This file is distributed under the same license as the PACKAGE package. # # Paweł Puszczyński , 2013. # msgid "" msgstr "" "Project-Id-Version: 0.19\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2013-03-22 11:58+0100\n" "Last-Translator: Paweł Puszczyński \n" "Language-Team: \n" "Language: Polish\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "Gratulacje, twoja postać wstąpiła na %d poziom!" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "Możesz zwiększyć jeden ze swoich atrybutów w Menu Postaci." #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "Pokonano Cię. Koniec gry! Wciśnij Enter, aby wrócić do Menu Głównego." #: ../../../src/Avatar.cpp:634 #, fuzzy msgid "You are defeated. Press Enter to continue." msgstr "Pokonano Cię. Wciśnij Enter, aby kontynuować." #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "Usunięto %d %s." #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "Usunięto %s." #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "Otrzymujesz %s." #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "Otrzymujesz %s x%d." #: ../../../src/CampaignManager.cpp:168 #, c-format msgid "You receive %d %s." msgstr "Otrzymujesz %d %s." #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "Otrzymujesz %d PD." #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "PŻ odnowione." #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "PM odnowione." #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "PŻ i PM odnowione." #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "Negatywne efekty usunięte." #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "PŻ i PM odnowione, negatywne efekty usunięte." #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "pudło" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "+%d PŻ" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "+%d PM" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "Cel nieznany" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "OK" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "Domyślne" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "Anuluj" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "Grafika" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "Dźwięk" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "Interfejs" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "Kontrolery" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "Klawiszologia" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "Mody" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "Przypisz: " #: ../../../src/GameStateConfig.cpp:165 msgid "Reset ALL settings?" msgstr "Zresetować WSZYSTKIE ustawienia?" #: ../../../src/GameStateConfig.cpp:166 msgid "Use this resolution?" msgstr "Pozostawić tą rozdzielczość?" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "Pełny ekran" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "Poruszaj się używając myszki" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "Pokaż tekst podczas walki" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "Generowanie sprzętowe" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "Podwójne buforowanie" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "Użyj joysticka" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "Tekstury Wysokiej Jakości" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "Zezwól na zmianę jasności" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "Animowane pola" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "Celowanie myszką" #: ../../../src/GameStateConfig.cpp:318 #, fuzzy msgid "Do not use mouse" msgstr "Nie używaj myszy" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "Pokaż klatki na sekundę" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "Pokaż etykiety klawiszy szybkiego dostępu" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "Minimalizacja kolorów" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "Głośność muzyki" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "Głośność efektów" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "Jasność" #: ../../../src/GameStateConfig.cpp:377 #, fuzzy msgid "Joystick Deadzone" msgstr "Martwa strefa Joystick-a" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "Rozdzielczość" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "Aktywne mody" #: ../../../src/GameStateConfig.cpp:412 msgid "Available Mods" msgstr "Dostępne mody" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "Joystick" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "Język" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 msgid "Disable for performance" msgstr "Wyłącz dla lepszej wydajności" #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "Eksperymentalne" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "Dla urządzeń przenośnych" #: ../../../src/GameStateConfig.cpp:527 msgid "<< Disable" msgstr "<< Wyłącz" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr "Włącz >>" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "Usuń zapis" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "Usunąć ten zapis?" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "Wyjdź do Menu" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "Wybierz stan gry" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "Nowa Gra" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "Włącz mod kampanii, by kontynuować" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "Wczytaj Grę" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "Wkraczanie do świata gry..." #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "Wczytywanie stanu gry..." #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "Poziom %d %s" #: ../../../src/GameStateLoad.cpp:579 #, fuzzy msgid "Permadeath" msgstr "Tryb ze śmiercią permamentną" #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "Puste miejsce" #: ../../../src/GameStateNew.cpp:62 msgid "Create" msgstr "Stwórz" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "Wybierz potret" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "Wybierz Imię" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "Jedno życie?" #: ../../../src/GameStateNew.cpp:179 msgid "Choose a Class" msgstr "Wybierz klasę postaci" #: ../../../src/GameStatePlay.cpp:99 msgid "Loading..." msgstr "Wczytywanie..." #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "Ekwipunek jest pełny." #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "Zacznij grę" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "Włącz mod rdzenia, aby kontynuować" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "Konfiguracja" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "Lista płac" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "Wyjdź z Gry" #: ../../../src/GameStateTitle.cpp:67 #, fuzzy msgid "Flare Alpha v0.19" msgstr "Flare Alpha v0.19" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "Akceptuj" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "Góra" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "Dół" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "Lewo" #: ../../../src/InputState.cpp:627 msgid "Right" msgstr "Prawo" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "Pas1" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "Pas2" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "Pas3" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "Pas4" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "Pas5" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "Pas6" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "Pas7" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "Pas8" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "Pas9" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "Pas0" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "Postać" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "Ekwipunek" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "Umiejętności" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "Dziennik" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "Główny1" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "Główny2" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "Ctrl" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "Shift" #: ../../../src/InputState.cpp:646 msgid "Delete" msgstr "Delete" #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "Wybór elementu na Pasku Akcji" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "Kursor na Pasku Akcji w lewo" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "Kursor na Pasku Akcji w prawo" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "Użycie elementu na Pasku Akcji" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "lpm" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "śpm" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "ppm" #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "kółko w górę" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "kółko w dół" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "mbx1" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "mbx2" #: ../../../src/ItemManager.cpp:488 #, fuzzy msgid "Low" msgstr "Łatwy" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "Normalny" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "Trudny" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "Epicki" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "Poziom %d" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "Obrażenia w zwarciu: %d-%d" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "Obrażenia w zwarciu: %d" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "Obrażenia dystansowe: %d-%d" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "Obrażenia dystansowe: %d" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "Obrażenia umysłowe: %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "Obrażenia umysłowe: %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "Absorbcja: %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "Absorbcja: %d" #: ../../../src/ItemManager.cpp:554 #, fuzzy, c-format msgid "%d% Speed" msgstr "%d% Szybkość" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "%s zwiększona o %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "%s zmniejszona o %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "Wymaga %d Siły Fizycznej" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "Wymaga %d Siły Umysłu" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "Wymaga %d Ataku" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "Wymaga %d Obrony" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "Jakość: %s" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, c-format msgid "Buy Price: %d %s" msgstr "Cena kupna: %d %s" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, c-format msgid "Buy Price: %d %s each" msgstr "Cena kupna: %d %s sztuka" #: ../../../src/ItemManager.cpp:643 #, c-format msgid "Sell Price: %d %s" msgstr "Wartość sprzedaży: %d %s" #: ../../../src/ItemManager.cpp:645 #, c-format msgid "Sell Price: %d %s each" msgstr "Wartość sprzedaży: %d %s sztuka" #: ../../../src/ItemManager.cpp:655 msgid "Set: " msgstr "Zestaw: " #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "%d przedmioty: " #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "Imię" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "Poziom" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "Siła fizyczna" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "Siła umysłu" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "Atak" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "Obrona" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "Pozostałe punkty" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "Maksymalna liczba PŻ:" #: ../../../src/MenuCharacter.cpp:340 msgid "HP Regen:" msgstr "Regeneracja PŻ:" #: ../../../src/MenuCharacter.cpp:341 msgid "Ticks of HP regen per minute." msgstr "Liczba przywróconych PŻ na minutę." #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "Maksymalna liczba PM:" #: ../../../src/MenuCharacter.cpp:352 msgid "MP Regen:" msgstr "Regeneracja PM:" #: ../../../src/MenuCharacter.cpp:353 msgid "Ticks of MP regen per minute. " msgstr "Liczba przywróconych PM na minutę." #: ../../../src/MenuCharacter.cpp:358 msgid "Accuracy:" msgstr "Celność:" #: ../../../src/MenuCharacter.cpp:364 msgid "Avoidance:" msgstr "Szansa na unik:" #: ../../../src/MenuCharacter.cpp:370 msgid "Melee Damage:" msgstr "Obrażenia w zwarciu:" #: ../../../src/MenuCharacter.cpp:380 msgid "Ranged Damage:" msgstr "Obrażenia dystansowe:" #: ../../../src/MenuCharacter.cpp:390 msgid "Mental Damage:" msgstr "Obrażenia umysłowe:" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "Szansa na atak krytyczny" #: ../../../src/MenuCharacter.cpp:406 msgid "Absorb:" msgstr "Absorbcja:" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "Równowaga: " #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "Zmniejsza szansę na utratę równowagi przy trafieniu" #: ../../../src/MenuCharacter.cpp:422 #, fuzzy msgid "Bonus XP: " msgstr "Dodatkowe PD: " #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "Zwiększa zdobywane PD za każde zabicie" #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "Premia" #: ../../../src/MenuCharacter.cpp:429 #, c-format msgid "Increases the %s found per drop" msgstr "Zwiększa ilość znajdowanego %s" #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "Dodatkowa szansa na przedmioty: " #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "Zwiększa szansę na upuszczenie przedmiotu przez wroga, gdy zginie" #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "Skradanie się: " #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "Zwiększa zdolność poruszania się niezauważenie" #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "PD: %d" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "Następny: %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "Siła Fizyczna (P) zwiększa skuteczność walki wręcz i maksymalną liczbę PŻ." #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "Podstawa (%d), dodatkowo (%d)" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "Siła Umysłu (M) zwiększa skuteczność posługiwania się bronią magiczną i maksymalną liczbę PM" #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "Atak (O) zwiększa skuteczność posługiwania się bronią dystansową i celność." #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "Obrona (D) zwiększa skuteczność działania zbroi i szansę na unik." #: ../../../src/MenuCharacter.cpp:498 #, c-format msgid "Each level grants %d. " msgstr "Każdy poziom zapewnia %d. " #: ../../../src/MenuCharacter.cpp:500 #, fuzzy, c-format msgid "Each point of Physical grants %d. " msgstr "Każdy punkt Siły Fizycznej dodaje +%d. " #: ../../../src/MenuCharacter.cpp:502 #, fuzzy, c-format msgid "Each point of Mental grants %d. " msgstr "Każdy punkt Siły Umysłu dodaje +%d. " #: ../../../src/MenuCharacter.cpp:504 #, fuzzy, c-format msgid "Each point of Offense grants %d. " msgstr "Każdy punkt Siły Umysłu dodaje +%d. " #: ../../../src/MenuCharacter.cpp:506 #, fuzzy, c-format msgid "Each point of Defense grants %d. " msgstr "Każdy punkt Siły Umysłu dodaje +%d. " #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "Nie żyje" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "%s poziom %d" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "Wyjdź" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "Zapisać i wyjść do menu?" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "Utracono %d%% %s. " #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "Utracono %d%% PD. " #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "Utracono %d%% PD z obecnego poziomu. " #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "Utracono %s." #: ../../../src/MenuInventory.cpp:228 #, c-format msgid "%d %s" msgstr "%d %s" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "Przytrzymaj SHIFT, żeby przenieść tylko jeden przedmiot." #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "CTRL-kliknij na przedmiot, by go sprzedać" #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "Ten przedmiot może być użyty jedynie z paska akcji." #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "Notatki" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "Zadania" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "PD: %d/%d" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, fuzzy, c-format msgid "Not enough %s." msgstr "Za mało %s." #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "Handel" #: ../../../src/MenuPowers.cpp:463 msgid "Unspent skill points:" msgstr "Niewydane punkty umiejętności:" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" "\n" "Następny poziom:" #: ../../../src/MenuPowers.cpp:525 #, fuzzy, c-format msgid "Requires a %s" msgstr "Wymaga %s" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "Wymaga %d Fizycznego ataku" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "Wymaga %d Fizycznej obrony" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "Wymaga %d Umysłowego ataku" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "Wymaga %d Umysłowej obrony" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, c-format msgid "Requires Level %d" msgstr "Wymaga %d poziomu" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, c-format msgid "Requires %d Skill Point" msgstr "Wymaga %d Punktu Umiejętności" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "Naciśnij, by odblokować" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, c-format msgid "Requires Power: %s" msgstr "Wymagana Moc: %s" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "Koszt: %d PM" #: ../../../src/MenuPowers.cpp:625 #, c-format msgid "Costs %d HP" msgstr "Koszt: %d PŻ" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "Odnowienie: %d sekund" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "Wspólna Skrytka" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "Kup z powrotem" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "Sprzedawca" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "=%d Tarcza" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "Już jesteś po transformacji, wpierw cofnij transformację." #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "Poszukiwacz przygód" #: ../../../src/Utils.cpp:519 #, fuzzy msgid "k" msgstr "Ok" #~ msgid "Character Menu (C)" #~ msgstr "Menu Postaci (C)" #~ msgid "Inventory Menu (I)" #~ msgstr "Menu Ekwipunku (I)" #~ msgid "Power Menu (P)" #~ msgstr "Menu Umiejętności (P)" #~ msgid "Log Menu (L)" #~ msgstr "Menu Dziennika (L)" #~ msgid "Ticks of HP regen per minute. Each point of Physical grants +%d HP regen. Each level grants +%d HP regen" #~ msgstr "PŻ uzupełniane na minutę. Każdy punkt Siły Fizycznej przyspiesza regenerację PŻ o +%d. Każdy poziom przyspiesza regenerację PŻ o +%d" #~ msgid "Ticks of MP regen per minute. Each point of Mental grants +%d MP regen. Each level grants +%d MP regen" #~ msgstr "PM uzupełniane na minutę. Każdy punkt Siły Umysłu przyspiesza regenerację PM o +%d. Każdy poziom przyspiesza regenerację PM o +%d" #~ msgid "Each point of Offense grants +%d accuracy. Each level grants +%d accuracy" #~ msgstr "Każdy punkt Ataku dodaje +%d do celności. Każdy poziom dodaje +%d do celności" #~ msgid "Each point of Defense grants +%d avoidance. Each level grants +%d avoidance" #~ msgstr "Każdy punkt Obrony dodaje +%d do szansy na unik. Każdy poziom dodaje +%d do szansy na unik" #~ msgid "Requires a physical weapon" #~ msgstr "Wymaga broni do walki wręcz" #~ msgid "Requires a mental weapon" #~ msgstr "Wymaga broni magicznej" #~ msgid "Requires an offense weapon" #~ msgstr "Wymaga broni dystansowej" flare-engine-0.19/mods/default/languages/engine.pot000066400000000000000000000471441224717101500223360ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "" #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "" #: ../../../src/Avatar.cpp:634 msgid "You are defeated. Press Enter to continue." msgstr "" #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "" #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "" #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "" #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "" #: ../../../src/CampaignManager.cpp:168 #, c-format msgid "You receive %d %s." msgstr "" #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "" #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "" #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "" #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "" #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "" #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "" #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "" #: ../../../src/GameStateConfig.cpp:165 msgid "Reset ALL settings?" msgstr "" #: ../../../src/GameStateConfig.cpp:166 msgid "Use this resolution?" msgstr "" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "" #: ../../../src/GameStateConfig.cpp:318 msgid "Do not use mouse" msgstr "" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "" #: ../../../src/GameStateConfig.cpp:377 msgid "Joystick Deadzone" msgstr "" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "" #: ../../../src/GameStateConfig.cpp:412 msgid "Available Mods" msgstr "" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 msgid "Disable for performance" msgstr "" #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "" #: ../../../src/GameStateConfig.cpp:527 msgid "<< Disable" msgstr "" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr "" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "" #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "" #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "" #: ../../../src/GameStateLoad.cpp:579 msgid "Permadeath" msgstr "" #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "" #: ../../../src/GameStateNew.cpp:62 msgid "Create" msgstr "" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "" #: ../../../src/GameStateNew.cpp:179 msgid "Choose a Class" msgstr "" #: ../../../src/GameStatePlay.cpp:99 msgid "Loading..." msgstr "" #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "" #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "" #: ../../../src/GameStateTitle.cpp:67 msgid "Flare Alpha v0.19" msgstr "" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "" #: ../../../src/InputState.cpp:627 msgid "Right" msgstr "" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "" #: ../../../src/InputState.cpp:646 msgid "Delete" msgstr "" #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "" #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "" #: ../../../src/ItemManager.cpp:488 msgid "Low" msgstr "" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "" #: ../../../src/ItemManager.cpp:554 #, c-format msgid "%d% Speed" msgstr "" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, c-format msgid "Buy Price: %d %s" msgstr "" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, c-format msgid "Buy Price: %d %s each" msgstr "" #: ../../../src/ItemManager.cpp:643 #, c-format msgid "Sell Price: %d %s" msgstr "" #: ../../../src/ItemManager.cpp:645 #, c-format msgid "Sell Price: %d %s each" msgstr "" #: ../../../src/ItemManager.cpp:655 msgid "Set: " msgstr "" #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "" #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "" #: ../../../src/MenuCharacter.cpp:340 msgid "HP Regen:" msgstr "" #: ../../../src/MenuCharacter.cpp:341 msgid "Ticks of HP regen per minute. " msgstr "" #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "" #: ../../../src/MenuCharacter.cpp:352 msgid "MP Regen:" msgstr "" #: ../../../src/MenuCharacter.cpp:353 msgid "Ticks of MP regen per minute. " msgstr "" #: ../../../src/MenuCharacter.cpp:358 msgid "Accuracy:" msgstr "" #: ../../../src/MenuCharacter.cpp:364 msgid "Avoidance:" msgstr "" #: ../../../src/MenuCharacter.cpp:370 msgid "Melee Damage:" msgstr "" #: ../../../src/MenuCharacter.cpp:380 msgid "Ranged Damage:" msgstr "" #: ../../../src/MenuCharacter.cpp:390 msgid "Mental Damage:" msgstr "" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "" #: ../../../src/MenuCharacter.cpp:406 msgid "Absorb:" msgstr "" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "" #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "" #: ../../../src/MenuCharacter.cpp:422 msgid "Bonus XP: " msgstr "" #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "" #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "" #: ../../../src/MenuCharacter.cpp:429 #, c-format msgid "Increases the %s found per drop" msgstr "" #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "" #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "" #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "" #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "" #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "" #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "" #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "" #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "" #: ../../../src/MenuCharacter.cpp:498 #, c-format msgid "Each level grants %d. " msgstr "" #: ../../../src/MenuCharacter.cpp:500 #, c-format msgid "Each point of Physical grants %d. " msgstr "" #: ../../../src/MenuCharacter.cpp:502 #, c-format msgid "Each point of Mental grants %d. " msgstr "" #: ../../../src/MenuCharacter.cpp:504 #, c-format msgid "Each point of Offense grants %d. " msgstr "" #: ../../../src/MenuCharacter.cpp:506 #, c-format msgid "Each point of Defense grants %d. " msgstr "" #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "" #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "" #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "" #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "" #: ../../../src/MenuInventory.cpp:228 #, c-format msgid "%d %s" msgstr "" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "" #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "" #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "" #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, c-format msgid "Not enough %s." msgstr "" #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "" #: ../../../src/MenuPowers.cpp:463 msgid "Unspent skill points:" msgstr "" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" #: ../../../src/MenuPowers.cpp:525 #, c-format msgid "Requires a %s" msgstr "" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, c-format msgid "Requires Level %d" msgstr "" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, c-format msgid "Requires %d Skill Point" msgstr "" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, c-format msgid "Requires Power: %s" msgstr "" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "" #: ../../../src/MenuPowers.cpp:625 #, c-format msgid "Costs %d HP" msgstr "" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "" #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "" #: ../../../src/Utils.cpp:519 msgid "k" msgstr "" flare-engine-0.19/mods/default/languages/engine.ru.po000066400000000000000000000670701224717101500225770ustar00rootroot00000000000000# Russian translation of Flare engine # Переводы на русский язык движка Flare # Copyright (C) 2011 Clint Bellanger # This file is distributed under the same license as the FLARE package. # # Sergey Basalaev , 2011-2013. # Evgen Pavlov , 2013. msgid "" msgstr "" "Project-Id-Version: flare-engine 0.18\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2013-11-26 00:36+0100\n" "Last-Translator: Sergey Basalaev \n" "Language-Team: Russian https://github.com/SBasalaev/flare-game/wiki/\n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.5.4\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "Поздравляем, вы достигли уровня %d!" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "Вы можете увеличить один атрибут через меню Персонаж." #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "Вы убиты. Игра окончена! Нажмите Ввод, чтобы выйти в Меню." #: ../../../src/Avatar.cpp:634 msgid "You are defeated. Press Enter to continue." msgstr "Вы потерпели поражение. Нажмите Ввод для продолжения." #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "%d %s удалено." #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "%s удалено." #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "Вы получаете %s." #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "Вы получаете %s x%d." #: ../../../src/CampaignManager.cpp:168 #, c-format msgid "You receive %d %s." msgstr "Вы получаете %d %s." #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "Вы получаете %d опыта." #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "Жизнь восстановлена." #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "Мана восстановлена." #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "Жизнь и мана восстановлены." #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "Отрицательные эффекты убраны." #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "Жизнь и мана восстановлены, отрицательные эффекты убраны" #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "промах" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "+%d жизни" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "+%d маны" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "Место назначения неизвестно" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "ОК" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "По умолчанию" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "Отмена" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "Видео" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "Аудио" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "Интерфейс" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "Ввод" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "Привязки клавиш" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "Дополнения" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "Назначить: " #: ../../../src/GameStateConfig.cpp:165 msgid "Reset ALL settings?" msgstr "Сбросить ВСЕ настройки?" #: ../../../src/GameStateConfig.cpp:166 msgid "Use this resolution?" msgstr "Использовать это разрешение?" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "Полноэкранный режим" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "Перемещать героя мышью" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "Показывать сообщения битвы" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "Аппаратные поверхности" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "Двойная буферизация" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "Использовать джойстик" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "Текстуры высокого качества" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "Включить изменение гаммы" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "Анимированные тайлы" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "Прицел мышью" #: ../../../src/GameStateConfig.cpp:318 msgid "Do not use mouse" msgstr "Не использовать мышь" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "Показывать FPS" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "Метки горячих клавиш" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "Режим цветовой слепоты" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "Громкость музыки" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "Громкость звука" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "Гамма" #: ../../../src/GameStateConfig.cpp:377 msgid "Joystick Deadzone" msgstr "Мёртвая зона джойстика" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "Разрешение" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "Активные дополнения" #: ../../../src/GameStateConfig.cpp:412 msgid "Available Mods" msgstr "Доступные дополнения" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "Джойстик" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "Язык" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 msgid "Disable for performance" msgstr "Уберите, если игра тормозит" #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "Экспериментальное" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "Для наладонных устройств" #: ../../../src/GameStateConfig.cpp:527 msgid "<< Disable" msgstr "<< Отключить" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr "Включить >>" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "Удалить игру" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "Удалить эту сохранённую игру?" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "Выйти в меню" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "Выберите слот" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "Новая игра" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "Включите сюжетное дополнение для продолжения" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "Загрузить игру" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "Вход в игровой мир..." #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "Загрузка сохранённой игры..." #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "Уровень %d %s" #: ../../../src/GameStateLoad.cpp:579 msgid "Permadeath" msgstr "Одна жизнь" #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "Пустой слот" #: ../../../src/GameStateNew.cpp:62 msgid "Create" msgstr "Создать" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "Выберите портрет" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "Выберите имя" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "Одна жизнь?" #: ../../../src/GameStateNew.cpp:179 msgid "Choose a Class" msgstr "Выберите класс" #: ../../../src/GameStatePlay.cpp:99 msgid "Loading..." msgstr "Загрузка..." #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "Инвентарь полон." #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "Играть" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "Включите основное дополнение для продолжения" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "Настройки" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "Авторы" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "Выйти" #: ../../../src/GameStateTitle.cpp:67 msgid "Flare Alpha v0.19" msgstr "Flare Alpha v0.19" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "Принять" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "Вверх" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "Вниз" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "Влево" #: ../../../src/InputState.cpp:627 msgid "Right" msgstr "Вправо" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "Меню1" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "Меню2" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "Меню3" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "Меню4" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "Меню5" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "Меню6" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "Меню7" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "Меню8" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "Меню9" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "Меню0" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "Персонаж" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "Инвентарь" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "Силы" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "Журнал" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "Главное1" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "Главное2" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "Ctrl" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "Shift" #: ../../../src/InputState.cpp:646 msgid "Delete" msgstr "Удалить" #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "Панель действий: принять" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "Панель действий: влево" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "Панель действий: вправо" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "Панель действий: использовать" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "ЛКМ" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "СКМ" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "ПКМ" #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "колесо вверх" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "колесо вниз" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "КМx1" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "КМx2" # качество - средний род #: ../../../src/ItemManager.cpp:488 msgid "Low" msgstr "Низкое" # качество - средний род #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "Среднее" # качество - средний род #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "Высокое" # качество - средний род #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "Эпическое" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "Уровень %d" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "Ближний урон: %d-%d" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "Ближний урон: %d" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "Дальний урон: %d-%d" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "Дальний урон: %d" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "Ментальный урон: %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "Ментальный урон: %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "Поглощение: %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "Поглощение: %d" #: ../../../src/ItemManager.cpp:554 #, c-format msgid "%d% Speed" msgstr "%d%% скорости" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "Увеличивает %s на %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "Уменьшает %s на %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "Требуется сила %d" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "Требуется интеллект %d" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "Требуется ловкость %d" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "Требуется защита %d" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "Качество: %s" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, c-format msgid "Buy Price: %d %s" msgstr "Цена покупки: %d %s" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, c-format msgid "Buy Price: %d %s each" msgstr "Цена покупки: %d %s каждый" #: ../../../src/ItemManager.cpp:643 #, c-format msgid "Sell Price: %d %s" msgstr "Цена продажи: %d %s" #: ../../../src/ItemManager.cpp:645 #, c-format msgid "Sell Price: %d %s each" msgstr "Цена продажи: %d %s каждый" #: ../../../src/ItemManager.cpp:655 msgid "Set: " msgstr "Установить: " #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "%d предметов: " #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "Имя" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "Уровень" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "Сила" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "Интеллект" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "Ловкость" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "Защита" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "очков осталось" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "Максимум здоровья:" #: ../../../src/MenuCharacter.cpp:340 msgid "HP Regen:" msgstr "Восстановление здоровья:" #: ../../../src/MenuCharacter.cpp:341 msgid "Ticks of HP regen per minute. " msgstr "Восстановливается единиц здоровья в минуту. " #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "Максимум маны:" #: ../../../src/MenuCharacter.cpp:352 msgid "MP Regen:" msgstr "Восстановление маны:" #: ../../../src/MenuCharacter.cpp:353 msgid "Ticks of MP regen per minute. " msgstr "Восстанавливается единиц маны в минуту. " #: ../../../src/MenuCharacter.cpp:358 msgid "Accuracy:" msgstr "Меткость: " #: ../../../src/MenuCharacter.cpp:364 msgid "Avoidance:" msgstr "Уклонение: " #: ../../../src/MenuCharacter.cpp:370 msgid "Melee Damage:" msgstr "Ближний урон:" #: ../../../src/MenuCharacter.cpp:380 msgid "Ranged Damage:" msgstr "Дальний урон:" #: ../../../src/MenuCharacter.cpp:390 msgid "Mental Damage:" msgstr "Ментальный урон:" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "Критический урон:" #: ../../../src/MenuCharacter.cpp:406 msgid "Absorb:" msgstr "Поглощение:" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "Самообладание: " #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "Уменьшает шанс задержки при получении урона" #: ../../../src/MenuCharacter.cpp:422 msgid "Bonus XP: " msgstr "Бонус опыта: " #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "Увеличивает количество опыта, получаемого за убийство" #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "Бонус" #: ../../../src/MenuCharacter.cpp:429 #, c-format msgid "Increases the %s found per drop" msgstr "Увеличивает количество выпадающего %s" #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "Бонус нахождения предметов: " #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "Повышает вероятность выпадения предмета при смерти противника" #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "Скрытность: " #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "Повышает способность двигаться незамеченным" #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "Опыт: %d" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "Следующий: %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "Сила (С) увеличивает владение оружием ближнего боя и полное здоровье." #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "базовое (%d), бонус (%d)" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "Интеллект (И) увеличивает владение ментальным оружием и полную ману." #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "Ловкость (Л) увеличивает владению оружием дальнего боя и меткость." #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "Защита (З) увеличивает владение бронёй и уклонение." #: ../../../src/MenuCharacter.cpp:498 #, c-format msgid "Each level grants %d. " msgstr "Каждый уровень даёт %d. " #: ../../../src/MenuCharacter.cpp:500 #, c-format msgid "Each point of Physical grants %d. " msgstr "Каждое очко силы даёт %d. " #: ../../../src/MenuCharacter.cpp:502 #, c-format msgid "Each point of Mental grants %d. " msgstr "Каждое очко интеллекта даёт %d. " #: ../../../src/MenuCharacter.cpp:504 #, c-format msgid "Each point of Offense grants %d. " msgstr "Каждое очко ловкости даёт %d. " #: ../../../src/MenuCharacter.cpp:506 #, c-format msgid "Each point of Defense grants %d. " msgstr "Каждое очко защиты даёт %d. " #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "Мёртв" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "%s уровень %d" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "Выйти" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "Сохранить и выйти в меню?" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "Потеряно %d%% из %s. " #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "Потеряно %d%% полного опыта. " #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "Потеряно %d%% опыта текущего уровня. " #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "Потеряно %s." #: ../../../src/MenuInventory.cpp:228 #, c-format msgid "%d %s" msgstr "%d %s" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "Используйте SHIFT, чтобы переместить только один предмет." #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "Используйте CTRL+щелчок на предмете в инвентаре, чтобы продать его." #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "Этот предмет можно использовать только с панели действия." #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "Заметки" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "Задания" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "Опыт: %d/%d" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, c-format msgid "Not enough %s." msgstr "Недостаточно %s." #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "Торговать" #: ../../../src/MenuPowers.cpp:463 msgid "Unspent skill points:" msgstr "Неистраченные очки навыков:" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" "\n" "Следующий уровень:" #: ../../../src/MenuPowers.cpp:525 #, c-format msgid "Requires a %s" msgstr "Требуется %s" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "Требуется сила+ловкость %d" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "Требуется сила+защита %d" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "Требуется интеллект+ловкость %d" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "Требуется интеллект+защита %d" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, c-format msgid "Requires Level %d" msgstr "Требуется уровень %d" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, c-format msgid "Requires %d Skill Point" msgstr "Требуется %d очков навыка" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "Щёлкните, чтобы разблокировать" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, c-format msgid "Requires Power: %s" msgstr "Требуется сила: %s" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "Стоит %d маны" #: ../../../src/MenuPowers.cpp:625 #, c-format msgid "Costs %d HP" msgstr "Стоит %d жизни" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "Восстановление: %d секунд" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "Общие запасы" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "Выкуп" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "Торговец" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "+%d Щит" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "Вы уже трансформированы, сперва растрансформируйтесь." #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "Приключенец" # сокращение для «кило» #: ../../../src/Utils.cpp:519 msgid "k" msgstr "к" #~ msgid "Requires a physical weapon" #~ msgstr "Требуется оружие ближнего боя" #~ msgid "Requires a mental weapon" #~ msgstr "Требуется ментальное оружие" #~ msgid "Requires an offense weapon" #~ msgstr "Требуется оружие дальнего боя" flare-engine-0.19/mods/default/languages/engine.sk.po000066400000000000000000000655241224717101500225700ustar00rootroot00000000000000# FLARE (Free/Libre Action RPG Engine) # Copyright (C) 2011 Clint Bellanger # This file is distributed under the same license as the FLARE package. # Miro Janosik , 2012. msgid "" msgstr "" "Project-Id-Version: 0.15\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2012-01-03+GMT+1\n" "Last-Translator: Miro Janosik \n" "Language-Team: Slovak \n" "Language: Slovak\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "Gratulujem, dosiahol si stupeň %d!" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "Teraz si môžeš zlepšiť jeden atribút cez Menu Postavy" #: ../../../src/Avatar.cpp:631 #, fuzzy msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "Porazili ťa. Prišiel si o polovicu zlata. Stlač Enter pre pokračovanie." #: ../../../src/Avatar.cpp:634 #, fuzzy msgid "You are defeated. Press Enter to continue." msgstr "Porazili ťa. Prišiel si o polovicu zlata. Stlač Enter pre pokračovanie." #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "" #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "" #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "Dostal si %s." #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "Dostal si %s x%d." #: ../../../src/CampaignManager.cpp:168 #, fuzzy, c-format msgid "You receive %d %s." msgstr "Dostal si %s." #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "Dostal si %d XP." #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "" #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "" #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "" #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "" #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "" #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "Neznámy cieľ" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "Zruš" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "" #: ../../../src/GameStateConfig.cpp:165 msgid "Reset ALL settings?" msgstr "" #: ../../../src/GameStateConfig.cpp:166 msgid "Use this resolution?" msgstr "" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "" #: ../../../src/GameStateConfig.cpp:318 msgid "Do not use mouse" msgstr "" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "" #: ../../../src/GameStateConfig.cpp:377 msgid "Joystick Deadzone" msgstr "" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "" #: ../../../src/GameStateConfig.cpp:412 msgid "Available Mods" msgstr "" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 msgid "Disable for performance" msgstr "" #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "" #: ../../../src/GameStateConfig.cpp:527 msgid "<< Disable" msgstr "" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr "" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "Zmazať Pozíciu" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "Zmazať túto pozíciu?" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "Návrat na úvod" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "Vyber priečinok" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "Nová Hra" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "Nahraj Hru" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "Vstupuješ do sveta hry..." #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "Nahrávam uloženú hru..." #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "Stupeň %d %s" #: ../../../src/GameStateLoad.cpp:579 msgid "Permadeath" msgstr "" #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "Prázdny priečinok" #: ../../../src/GameStateNew.cpp:62 #, fuzzy msgid "Create" msgstr "Postava" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "Vyber si Vzhľad" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "Vyber si Meno" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "" #: ../../../src/GameStateNew.cpp:179 #, fuzzy msgid "Choose a Class" msgstr "Vyber priečinok" #: ../../../src/GameStatePlay.cpp:99 #, fuzzy msgid "Loading..." msgstr "Nahrávam uloženú hru..." #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "Vrecká sú plné." #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "Hrať Hru" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "Ukončiť Hru" #: ../../../src/GameStateTitle.cpp:67 #, fuzzy msgid "Flare Alpha v0.19" msgstr "Flare Alpha v0.18" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "" #: ../../../src/InputState.cpp:627 #, fuzzy msgid "Right" msgstr "Rytier" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "Postava" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "Vrecká" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "Sily" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "Poznámky" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "" #: ../../../src/InputState.cpp:646 #, fuzzy msgid "Delete" msgstr "Zmazať Pozíciu" #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "" #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "" #: ../../../src/ItemManager.cpp:488 #, fuzzy msgid "Low" msgstr "Poznámky" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "Stupeň %d" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "Priame zranenie: %d-%d" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "Priame zranenie: %d" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "Zranenie strelou: %d-%d" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "Zranenie strelou: %d" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "Psychické zranenie: %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "Psychické zranenie: %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "Pohlť: %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "Pohlť: %d" #: ../../../src/ItemManager.cpp:554 #, c-format msgid "%d% Speed" msgstr "" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "Zvýši %s o %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "Zníži %s o %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "Vyžaduje Silu %d" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "Vyžaduje Psychiku %d" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "Vyžaduje Útok %d" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "Vyžaduje Obranu %d" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, fuzzy, c-format msgid "Buy Price: %d %s" msgstr "Nákupná Cena: %d zlatiek" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, fuzzy, c-format msgid "Buy Price: %d %s each" msgstr "Nákupná Cena za kus: %d zlatiek" #: ../../../src/ItemManager.cpp:643 #, fuzzy, c-format msgid "Sell Price: %d %s" msgstr "Predajná Cena: %d zlatiek" #: ../../../src/ItemManager.cpp:645 #, fuzzy, c-format msgid "Sell Price: %d %s each" msgstr "Predajná Cena za kus: %d zlatiek" #: ../../../src/ItemManager.cpp:655 #, fuzzy msgid "Set: " msgstr "Nasl.: %d" #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "" #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "Meno" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "Stupeň" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "Sila" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "Psychika" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "Útok" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "Obrana" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "" #: ../../../src/MenuCharacter.cpp:340 #, fuzzy msgid "HP Regen:" msgstr "Regenerácia" #: ../../../src/MenuCharacter.cpp:341 #, fuzzy msgid "Ticks of HP regen per minute. " msgstr "Rýchlosť regenerácie HP za minútu" #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "" #: ../../../src/MenuCharacter.cpp:352 #, fuzzy msgid "MP Regen:" msgstr "Regenerácia" #: ../../../src/MenuCharacter.cpp:353 #, fuzzy msgid "Ticks of MP regen per minute. " msgstr "Rýchlosť regenerácie MP za minútu" #: ../../../src/MenuCharacter.cpp:358 #, fuzzy msgid "Accuracy:" msgstr "Presnosť vs. Obr 1" #: ../../../src/MenuCharacter.cpp:364 #, fuzzy msgid "Avoidance:" msgstr "Vyhýb vs. Útok 1" #: ../../../src/MenuCharacter.cpp:370 #, fuzzy msgid "Melee Damage:" msgstr "Priame zranenie: %d" #: ../../../src/MenuCharacter.cpp:380 #, fuzzy msgid "Ranged Damage:" msgstr "Zranenie strelou: %d" #: ../../../src/MenuCharacter.cpp:390 #, fuzzy msgid "Mental Damage:" msgstr "Psychické zranenie: %d" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "" #: ../../../src/MenuCharacter.cpp:406 #, fuzzy msgid "Absorb:" msgstr "Absorbcia" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "" #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "" #: ../../../src/MenuCharacter.cpp:422 msgid "Bonus XP: " msgstr "" #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "" #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "" #: ../../../src/MenuCharacter.cpp:429 #, fuzzy, c-format msgid "Increases the %s found per drop" msgstr "Zvýši %s o %d" #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "" #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "" #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "" #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "" #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "XP: %d" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "Nasl.: %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "Sila (P) zvyšuje zručnosť s ručnými zbraňami a zdravie." #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "základ (%d), bonus (%d)" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "Psychika (M) zvyšuje zručnosť s psychickými zbraňami a manu." #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "Útok (O) zvyšuje zručnosť so strelnými zbraňami a presnosť." #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "Obrana (D) zvyšuje zručnosť s brnením a vyhýbanie sa." #: ../../../src/MenuCharacter.cpp:498 #, fuzzy, c-format msgid "Each level grants %d. " msgstr "Každý stupeň poskytne +2 HP" #: ../../../src/MenuCharacter.cpp:500 #, fuzzy, c-format msgid "Each point of Physical grants %d. " msgstr "Každý bod Sily poskytne +8 HP" #: ../../../src/MenuCharacter.cpp:502 #, fuzzy, c-format msgid "Each point of Mental grants %d. " msgstr "Každý bod Psychiky poskytne +8 MP" #: ../../../src/MenuCharacter.cpp:504 #, fuzzy, c-format msgid "Each point of Offense grants %d. " msgstr "Každý bod Psychiky poskytne +8 MP" #: ../../../src/MenuCharacter.cpp:506 #, fuzzy, c-format msgid "Each point of Defense grants %d. " msgstr "Každý bod Psychiky poskytne +8 MP" #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "Mŕtvy" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "%s stupeň %d" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "Ukonči" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "Ulož a choď na úvod?" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "" #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "" #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "" #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "" #: ../../../src/MenuInventory.cpp:228 #, fuzzy, c-format msgid "%d %s" msgstr "Stupeň %d %s" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "Použi SHIFT na presun jediného predmetu." #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "CTRL+klik predá ťahaný predmet." #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "Tento predmet môžeš použiť iba z pruhu akcií." #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "Úlohy" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "XP: %d/%d" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, c-format msgid "Not enough %s." msgstr "" #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "" #: ../../../src/MenuPowers.cpp:463 msgid "Unspent skill points:" msgstr "" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" #: ../../../src/MenuPowers.cpp:525 #, fuzzy, c-format msgid "Requires a %s" msgstr "Vyžaduje Psychiku %d" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "Vyžaduje Silu Útoku %d" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "Vyžaduje Silu Obrany %d" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "Vyžaduje Psychický Útok %d" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "Vyžaduje Psychickú Obranu %d" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, fuzzy, c-format msgid "Requires Level %d" msgstr "Vyžaduje Psychiku %d" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, fuzzy, c-format msgid "Requires %d Skill Point" msgstr "Vyžaduje fyzickú zbraň" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, fuzzy, c-format msgid "Requires Power: %s" msgstr "Vyžaduje Psychiku %d" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "Spotrebuje %d MP" #: ../../../src/MenuPowers.cpp:625 #, fuzzy, c-format msgid "Costs %d HP" msgstr "Spotrebuje %d MP" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "Vychladnutie: %d sekúnd" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "Predavač" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "" #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "Dobrodruh" #: ../../../src/Utils.cpp:519 msgid "k" msgstr "" #~ msgid "Character Menu (C)" #~ msgstr "Menu Postavy (C)" #~ msgid "Inventory Menu (I)" #~ msgstr "Obsah Vreciek (I)" #~ msgid "Power Menu (P)" #~ msgstr "Menu Sily (P)" #~ msgid "Log Menu (L)" #~ msgstr "Menu Denníka (L)" #, fuzzy #~ msgid "Each point of Physical grants +%d HP. Each level grants +%d HP" #~ msgstr "Každý bod Sily poskytne regeneráciu +4 HP" #, fuzzy #~ msgid "Each point of Mental grants +%d MP. Each level grants +%d MP" #~ msgstr "Každý bod Psychiky poskytne regeneráciu +4 MP" #, fuzzy #~ msgid "Each point of Offense grants +%d accuracy. Each level grants +%d accuracy" #~ msgstr "Každý bod Útoku poskytne presnosť +5" #, fuzzy #~ msgid "Each point of Defense grants +%d avoidance. Each level grants +%d avoidance" #~ msgstr "Každý bod Obrany poskytne +5 vyhýbaniu" #~ msgid "Requires a physical weapon" #~ msgstr "Vyžaduje fyzickú zbraň" #~ msgid "Requires a mental weapon" #~ msgstr "Vyžaduje psychickú zbraň" #~ msgid "Requires an offense weapon" #~ msgstr "Vyžaduje útočnú zbraň" #~ msgid "Flare" #~ msgstr "Flare" #, fuzzy #~ msgid "Accuracy (vs lvl 5):" #~ msgstr "Presnosť vs. Obr 1" #, fuzzy #~ msgid "Avoidance (vs lvl 5):" #~ msgstr "Vyhýb vs. Útok 1" #, fuzzy #~ msgid "Stats" #~ msgstr "Štatistika" #~ msgid "Grand Master" #~ msgstr "Starešina" #~ msgid "Master" #~ msgstr "Vodca" #~ msgid "Warrior" #~ msgstr "Bojovník" #~ msgid "Wizard" #~ msgstr "Čarodej" #~ msgid "Ranger" #~ msgstr "Strelec" #~ msgid "Paladin" #~ msgstr "Paladin" #~ msgid "Rogue" #~ msgstr "Gauner" #~ msgid "Knight" #~ msgstr "Rytier" #~ msgid "Shaman" #~ msgstr "Šaman" #~ msgid "Cleric" #~ msgstr "Liečiteľ" #~ msgid "Battle Mage" #~ msgstr "Bojový Mág" #~ msgid "Heavy Archer" #~ msgstr "Ostrostrelec" #~ msgid "You receive %d gold." #~ msgstr "Dostal si %d zlatiek." #~ msgid "Create Character" #~ msgstr "Vytvor Postavu" #~ msgid "Main Hand" #~ msgstr "Silnejšia Ruka" #~ msgid "Body" #~ msgstr "Telo" #~ msgid "Off Hand" #~ msgstr "Slabšia Ruka" #~ msgid "Artifact" #~ msgstr "Artefakt" #~ msgid "Consumable" #~ msgstr "Jedlé" #~ msgid "Gem" #~ msgstr "Klenot" #~ msgid "Quest Item" #~ msgstr "Hľadaná Vec" #~ msgid "%d Gold" #~ msgstr "%d Zlatiek" #~ msgid "Total HP" #~ msgstr "Plné zdravie" #~ msgid "Total MP" #~ msgstr "Plná Mana" #~ msgid "vs. Def 5" #~ msgstr "vs. Obrana 5" #~ msgid "vs. Off 5" #~ msgstr "vs. Útok 5" #~ msgid "Main Weapon" #~ msgstr "Hlavná Zbraň" #~ msgid "Ranged Weapon" #~ msgstr "Strelná Zbraň" #~ msgid "Crit Chance" #~ msgstr "Kritická Šanca" #~ msgid "Fire Resist" #~ msgstr "Odolný Ohňu" #~ msgid "Ice Resist" #~ msgstr "Odolný Ľadu" #~ msgid "Each level grants +1 HP regen" #~ msgstr "Každý stupeň poskytne regeneráciu +1 HP" #~ msgid "Each level grants +2 MP" #~ msgstr "Každý stupeň posktyne +2 MP" #~ msgid "Each level grants +1 MP regen" #~ msgstr "Každý stupeň poskytne regeneráciu +1 MP" #~ msgid "Each level grants +1 accuracy" #~ msgstr "Každý stupeň posktyne presnosť +1" #~ msgid "Each level grants +1 avoidance" #~ msgstr "Každý stupeň poskytne +1 vyhýbaniu" #~ msgid "Dagger Proficiency" #~ msgstr "Zručnosť s Dýkou" #~ msgid "Shortsword Proficiency" #~ msgstr "Zručnosť s Krátkym Mečom" #~ msgid "Longsword Proficiency" #~ msgstr "Zručnosť s Dlhým Mečom" #~ msgid "Greatsword Proficiency" #~ msgstr "Zručnosť s Veľkým Mečom" #~ msgid "Wand Proficiency" #~ msgstr "Zručnosť s Paličkou" #~ msgid "Rod Proficiency" #~ msgstr "Zručnosť s Tyčou" #~ msgid "Staff Proficiency" #~ msgstr "Zručnosť s Palicou" #~ msgid "Greatstaff Proficiency" #~ msgstr "Zručnosť s Veľkou Palicou" #~ msgid "Slingshot Proficiency" #~ msgstr "Zručnosť s Prakom" #~ msgid "Shortbow Proficiency" #~ msgstr "Zručnosť s Krátkym Lukom" #~ msgid "Longbow Proficiency" #~ msgstr "Zručnosť s Dlhým Lukom" #~ msgid "Greatbow Proficiency" #~ msgstr "Zručnosť s Veľkým Lukom" #~ msgid "Light Armor Proficiency" #~ msgstr "Zručnosť s Ľahkým Brnením" #~ msgid "Light Shield Proficiency" #~ msgstr "Zručnosť s Ľahkým Štítom" #~ msgid "Heavy Armor Proficiency" #~ msgstr "Zručnosť s Ťažkým Brnením" #~ msgid "Heavy Shield Proficiency" #~ msgstr "Zručnosť s Ťažkým Štítom" #~ msgid "Messages" #~ msgstr "Správy" #~ msgid "Physical + Offense grants melee and ranged attacks" #~ msgstr "Sila + Útok umožňuje ručné a strelné útoky" #~ msgid "Physical + Defense grants melee protection" #~ msgstr "Sila + Obrana umožňuje obranu na blízko" #~ msgid "Mental + Offense grants elemental spell attacks" #~ msgstr "Psychika + Útok umožňuje útočiť elementálnymi kúzlami" #~ msgid "Mental + Defense grants healing and magical protection" #~ msgstr "Psychika + Obrana umožňuje liečenie a magickú obranu" flare-engine-0.19/mods/default/languages/engine.sv.po000066400000000000000000000707421224717101500226010ustar00rootroot00000000000000# FLARE (Free/Libre Action RPG Engine) # Copyright (C) 2011 Clint Bellanger # This file is distributed under the same license as the FLARE package. # FIRST AUTHOR , YEAR. msgid "" msgstr "" "Project-Id-Version: Flare 0.17\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2013-03-24 14:10+0100\n" "Last-Translator: Henrik Andersson \n" "Language-Team: SWEDISH \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: Swedish\n" "X-Poedit-Country: SWEDEN\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "Grattis, du har nått nivå %d!" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "Du får nu öka på en egenskap i karaktärsmenyn." #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "Du är besegrad. Spelet är över! Tryck Retur för att fortsätta." #: ../../../src/Avatar.cpp:634 #, fuzzy msgid "You are defeated. Press Enter to continue." msgstr "Du är besegrad. Du förlorar hälften av ditt %s. Tryck Retur för att fortsätta." #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "" #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "" #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "Du får %s." #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "Du får %s x%d." #: ../../../src/CampaignManager.cpp:168 #, c-format msgid "You receive %d %s." msgstr "Du får %d %s." #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "Du får %d XP." #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "HP äterställd." #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "MP återställd." #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "HP och MP återställt." #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "Negativa effekter borttagna." #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "HP och MP återställt, negativa effekter borttagna" #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "miss" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "+%d HP" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "+%d MP" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "Okänd destination" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "OK" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "Standard" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "Avbryt" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "Video" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "Ljud" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "Gränssnitt" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "Inmatning" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "Tangentbindningar" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "Mods" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "Tilldela:" #: ../../../src/GameStateConfig.cpp:165 msgid "Reset ALL settings?" msgstr "Återställ samtliga inställningar?" #: ../../../src/GameStateConfig.cpp:166 msgid "Use this resolution?" msgstr "Använd denna upplösning?" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "Fullskärmsläge" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "Flytta hjälten med muspekaren" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "Visa text vid strid" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "Dubbelbuffring" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "Använd joystick" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "Högkvalitativa texturer" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "Tillåt ändring av gamma" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "Animerade tiles" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "Sikta med muspekaren" #: ../../../src/GameStateConfig.cpp:318 #, fuzzy msgid "Do not use mouse" msgstr "Flytta hjälten med muspekaren" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "Visa FPS" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "Musikvolym" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "Ljudvolym" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "Gamma" #: ../../../src/GameStateConfig.cpp:377 #, fuzzy msgid "Joystick Deadzone" msgstr "Joystick" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "Upplösning" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "Aktiva Mods" #: ../../../src/GameStateConfig.cpp:412 msgid "Available Mods" msgstr "Tillgängliga Mods" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "Joystick" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "Språk" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 msgid "Disable for performance" msgstr "Inaktivera för prestanda" #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "Experimentell" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "" #: ../../../src/GameStateConfig.cpp:527 msgid "<< Disable" msgstr "<< Inaktivera" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr "Aktivera >>" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "Radera sparat spel" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "Vill du radera det sparade spelet?" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "Avsluta och gå till huvudmenyn" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "Välj en plats" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "Nytt spel" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "Aktivera en story mod för att fortsätta" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "Ladda spel" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "Öppnar spelvärlden..." #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "Läser in sparat spel..." #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "Nivå %d %s" #: ../../../src/GameStateLoad.cpp:579 #, fuzzy msgid "Permadeath" msgstr "Permanent död?" #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "Ledig plats" #: ../../../src/GameStateNew.cpp:62 msgid "Create" msgstr "Skapa" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "Välj ett ansikte" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "Ange namn" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "Permanent död?" #: ../../../src/GameStateNew.cpp:179 msgid "Choose a Class" msgstr "Välj en Klass" #: ../../../src/GameStatePlay.cpp:99 msgid "Loading..." msgstr "Laddar..." #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "Du har inte plats för fler föremål." #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "Starta spelet" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "Aktivera en core mod för att fortsätta" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "Konfiguration" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "Avsluta spelet" #: ../../../src/GameStateTitle.cpp:67 #, fuzzy msgid "Flare Alpha v0.19" msgstr "Flare Alpha v0.18" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "Acceptera" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "" #: ../../../src/InputState.cpp:627 msgid "Right" msgstr "Höger" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "Karaktär" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "Inventarie" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "Krafter" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "Logg" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "" #: ../../../src/InputState.cpp:646 msgid "Delete" msgstr "Ta bort" #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "" #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "" #: ../../../src/ItemManager.cpp:488 #, fuzzy msgid "Low" msgstr "Logg" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "Nivå %d" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "Närstridsskada: %d-%d" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "Närstridsskada: %d" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "Distansskada: %d-%d" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "Distansskada: %d" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "Mental skada: %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "Mental skada: %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "Absorberar: %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "Absorberar: %d" #: ../../../src/ItemManager.cpp:554 #, fuzzy, c-format msgid "%d% Speed" msgstr "%d%% Hastighet" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "Ökar %s med %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "Minskar %s med %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "Kräver fysik %d" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "Kräver mental styrka %d" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "Kräver anfall %d" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "Kräver försvar %d" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, c-format msgid "Buy Price: %d %s" msgstr "Köpesumma: %d %s" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, c-format msgid "Buy Price: %d %s each" msgstr "Köpesumma: %d %s per styck" #: ../../../src/ItemManager.cpp:643 #, c-format msgid "Sell Price: %d %s" msgstr "Säljes för: %d %s" #: ../../../src/ItemManager.cpp:645 #, c-format msgid "Sell Price: %d %s each" msgstr "Säljes för: %d %s per styck" #: ../../../src/ItemManager.cpp:655 msgid "Set: " msgstr "" #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "%d föremål:" #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "Namn" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "Nivå" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "Fysik" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "Mental styrka" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "Anfall" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "Försvar" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "återstående poäng" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "Max HP:" #: ../../../src/MenuCharacter.cpp:340 msgid "HP Regen:" msgstr "HP Regenerering:" #: ../../../src/MenuCharacter.cpp:341 #, fuzzy msgid "Ticks of HP regen per minute. " msgstr "HP-regenereringar per minut" #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "Max MP:" #: ../../../src/MenuCharacter.cpp:352 msgid "MP Regen:" msgstr "MP Regenerering:" #: ../../../src/MenuCharacter.cpp:353 #, fuzzy msgid "Ticks of MP regen per minute. " msgstr "MP-regenereringar per minut" #: ../../../src/MenuCharacter.cpp:358 msgid "Accuracy:" msgstr "Noggrannhet:" #: ../../../src/MenuCharacter.cpp:364 msgid "Avoidance:" msgstr "Undvikande:" #: ../../../src/MenuCharacter.cpp:370 msgid "Melee Damage:" msgstr "Närstridsskada:" #: ../../../src/MenuCharacter.cpp:380 msgid "Ranged Damage:" msgstr "Distansskada:" #: ../../../src/MenuCharacter.cpp:390 msgid "Mental Damage:" msgstr "Mental skada:" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "Kritisk:" #: ../../../src/MenuCharacter.cpp:406 msgid "Absorb:" msgstr "Absorberar:" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "Balans:" #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "Minskar din chans att snava när du blir träffad" #: ../../../src/MenuCharacter.cpp:422 msgid "Bonus XP: " msgstr "Bonus XP:" #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "Ökar XP erhållet per död fiende" #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "Bonus" #: ../../../src/MenuCharacter.cpp:429 #, c-format msgid "Increases the %s found per drop" msgstr "Ökar %s som död fiende lämnar efter sig" #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "Bonus objekt funnet:" #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "Ökar chansen att fiender lämnar efter sig något vid död" #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "List:" #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "Ökar din förmåga att röra dig oupptäckt" #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "XP: %d" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "Nästa: %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "Fysik (P) ökar skickligheten i närstrid och total HP." #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "bas (%d), bonus (%d)" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "Mental styrka (M) ökar färdighet med mentala vapen och total MP." #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "Anfall ökar färdigheten och noggrannheten med distanssvapen." #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "Försvar (D) ökar färdighet med rustning och undvikande." #: ../../../src/MenuCharacter.cpp:498 #, fuzzy, c-format msgid "Each level grants %d. " msgstr "Varje nivå ger +2 HP" #: ../../../src/MenuCharacter.cpp:500 #, fuzzy, c-format msgid "Each point of Physical grants %d. " msgstr "Varje fysikpoäng ger +8 HP" #: ../../../src/MenuCharacter.cpp:502 #, fuzzy, c-format msgid "Each point of Mental grants %d. " msgstr "Varje poäng i mental styrka ger +8 MP" #: ../../../src/MenuCharacter.cpp:504 #, fuzzy, c-format msgid "Each point of Offense grants %d. " msgstr "Varje poäng i mental styrka ger +8 MP" #: ../../../src/MenuCharacter.cpp:506 #, fuzzy, c-format msgid "Each point of Defense grants %d. " msgstr "Varje poäng i mental styrka ger +8 MP" #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "Död" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "%s nivå %d" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "Avsluta" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "Spara och gå till huvudmenyn?" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "" #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "" #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "" #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "" #: ../../../src/MenuInventory.cpp:228 #, c-format msgid "%d %s" msgstr "%d %s" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "Använd SHIFT för att flytta enstaka föremål." #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "CTRL-klicka på ett föremål du har för att sälja det." #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "Det här föremålet kan bara användas från handlingslisten." #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "Noteringar" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "Uppdrag" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "XP: %d/%d" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, fuzzy, c-format msgid "Not enough %s." msgstr "Inte tillräckligr med pengar." #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "Handel" #: ../../../src/MenuPowers.cpp:463 msgid "Unspent skill points:" msgstr "Outnyttjade attributpoäng:" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" #: ../../../src/MenuPowers.cpp:525 #, fuzzy, c-format msgid "Requires a %s" msgstr "Kräver mental styrka %d" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "Kräver fysiskt anfall %d" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "Kräver fysiskt försvar %d" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "Kräver mentalt anfall %d" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "Kräver mentalt försvar %d" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, c-format msgid "Requires Level %d" msgstr "Kräver nivå %d" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, c-format msgid "Requires %d Skill Point" msgstr "Kräver %d skicklighetspoäng" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "Klicka för att låsa upp" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, c-format msgid "Requires Power: %s" msgstr "Kräver styrka: %s" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "Kostar %d MP" #: ../../../src/MenuPowers.cpp:625 #, c-format msgid "Costs %d HP" msgstr "Kostar %d HP" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "Svalnar av: %d sekunder" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "Delad gömma" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "Återköp" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "Affärsman" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "+%d Sköld" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "Du är redan i omvandlad form, omvandla dig tillbaka först." #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "Äventyrare" #: ../../../src/Utils.cpp:519 #, fuzzy msgid "k" msgstr "Ok" #~ msgid "Character Menu (C)" #~ msgstr "Karaktärsmenyn (C)" #~ msgid "Inventory Menu (I)" #~ msgstr "Föremålsmenyn (I)" #~ msgid "Power Menu (P)" #~ msgstr "Kraftmenyn (P)" #~ msgid "Log Menu (L)" #~ msgstr "Loggmenyn (L)" #~ msgid "Each point of Physical grants +%d HP. Each level grants +%d HP" #~ msgstr "Varje poäng i fysik ger +%d HP. Varje nivå ger +%d HP" #~ msgid "Ticks of HP regen per minute. Each point of Physical grants +%d HP regen. Each level grants +%d HP regen" #~ msgstr "Mängd av HP regenerering per minut. Varje poäng av fysisk styrka ger +%d HP regenerering. Varje nivå ger +%d HP regenerering" #~ msgid "Each point of Mental grants +%d MP. Each level grants +%d MP" #~ msgstr "Varje poäng i mental styrka ger +%d MP regenerering. Varje nivå ger +%d MP" #~ msgid "Ticks of MP regen per minute. Each point of Mental grants +%d MP regen. Each level grants +%d MP regen" #~ msgstr "Mängd av MP regenerering per minut, Varje poäng av mental styrka ger +%d MP regenerering. Varje nivå ger +%d MP regenerering" #~ msgid "Each point of Offense grants +%d accuracy. Each level grants +%d accuracy" #~ msgstr "Varje poäng i anfall ger +%d i noggrannhet. Varje nivå ger +%d i noggrannhet" #~ msgid "Each point of Defense grants +%d avoidance. Each level grants +%d avoidance" #~ msgstr "Varje poäng i försvar ger +%d i undvikande. Varje nivå ger +%d i undvikande." #~ msgid "Requires a physical weapon" #~ msgstr "Kräver ett fysiskt vapen" #~ msgid "Requires a mental weapon" #~ msgstr "Kräver ett mentalt vapen" #~ msgid "Requires an offense weapon" #~ msgstr "Kräver ett anfallsvapen" #~ msgid "Flare" #~ msgstr "Flare" #~ msgid "Accuracy (vs lvl 5):" #~ msgstr "Noggrannhet (vs lvl 5):" #~ msgid "Avoidance (vs lvl 5):" #~ msgstr "Undvikande (vs. lvl 4)" #~ msgid "Stats" #~ msgstr "Statistik" #~ msgid "Grand Master" #~ msgstr "Stormästare" #~ msgid "Master" #~ msgstr "Mästare" #~ msgid "Warrior" #~ msgstr "Krigare" #~ msgid "Wizard" #~ msgstr "Trollkarl" #~ msgid "Ranger" #~ msgstr "Vandrare" #~ msgid "Paladin" #~ msgstr "Paladin" #~ msgid "Rogue" #~ msgstr "Landstrykare" #~ msgid "Knight" #~ msgstr "Riddare" #~ msgid "Shaman" #~ msgstr "Shaman" #~ msgid "Cleric" #~ msgstr "Klerk" #~ msgid "Battle Mage" #~ msgstr "Stridsmagiker" #~ msgid "Heavy Archer" #~ msgstr "Pilbågsskytt" #~ msgid "You receive %d gold." #~ msgstr "Du får %d guld." #~ msgid "Create Character" #~ msgstr "Skapa karaktär" #~ msgid "Main Hand" #~ msgstr "Stark hand" #~ msgid "Body" #~ msgstr "Kropp" #~ msgid "Off Hand" #~ msgstr "Svag hand" #~ msgid "Artifact" #~ msgstr "Artefakt" #~ msgid "Consumable" #~ msgstr "Ätbart" #~ msgid "Gem" #~ msgstr "Ädelsten" #~ msgid "Quest Item" #~ msgstr "Uppdragsrelaterat föremål" #~ msgid "%d Gold" #~ msgstr "%d guld" #~ msgid "Total HP" #~ msgstr "Totala HP" #~ msgid "Total MP" #~ msgstr "Totala MP" #~ msgid "vs. Def 5" #~ msgstr "vs. försvar 5" #~ msgid "vs. Off 5" #~ msgstr "vs. anfall 5" #~ msgid "Main Weapon" #~ msgstr "Huvudvapen" #~ msgid "Ranged Weapon" #~ msgstr "Avståndsvapen" #~ msgid "Crit Chance" #~ msgstr "Kritisk chans" #~ msgid "Fire Resist" #~ msgstr "Motståndskraft mot eld" #~ msgid "Ice Resist" #~ msgstr "Motståndskraft mot is" #~ msgid "Each level grants +1 HP regen" #~ msgstr "Varje nivå ger +1 HP regenerering" #~ msgid "Each level grants +2 MP" #~ msgstr "Varje nivå ger +2 MP" #~ msgid "Each level grants +1 MP regen" #~ msgstr "Varje nivå ger +1 MP regenerering" #~ msgid "Each level grants +1 accuracy" #~ msgstr "Varje nivå ger +1 i noggrannhet" #~ msgid "Each level grants +1 avoidance" #~ msgstr "Varje nivå ger +1 i undvikande" #~ msgid "Dagger Proficiency" #~ msgstr "Skicklighet med kniv" #~ msgid "Shortsword Proficiency" #~ msgstr "Skicklighet med svärd" #~ msgid "Longsword Proficiency" #~ msgstr "Skicklighet med långsvärd" #~ msgid "Greatsword Proficiency" #~ msgstr "Skicklighet med stort svärd" #~ msgid "Wand Proficiency" #~ msgstr "Skicklighet med trollstav" #~ msgid "Rod Proficiency" #~ msgstr "Skicklighet med käpp" #~ msgid "Staff Proficiency" #~ msgstr "Skicklighet med stav" #~ msgid "Greatstaff Proficiency" #~ msgstr "Skicklighet med stor stav" #~ msgid "Slingshot Proficiency" #~ msgstr "Skicklighet med slangbella" #~ msgid "Shortbow Proficiency" #~ msgstr "Skicklighet i pilpåge" #~ msgid "Longbow Proficiency" #~ msgstr "Skicklighet i långbåge" #~ msgid "Greatbow Proficiency" #~ msgstr "Skicklighet i stor pilbåge" #~ msgid "Light Armor Proficiency" #~ msgstr "Skicklighet med lätt rustning" #~ msgid "Light Shield Proficiency" #~ msgstr "Skicklighet med lätt sköld" #~ msgid "Heavy Armor Proficiency" #~ msgstr "Skicklighet med tung rustning" #~ msgid "Heavy Shield Proficiency" #~ msgstr "Skicklighet med tung sköld" #~ msgid "Messages" #~ msgstr "Meddelanden" #~ msgid "Physical + Offense grants melee and ranged attacks" #~ msgstr "Fysik + anfall möjliggör närstrid och avståndsattacker" #~ msgid "Physical + Defense grants melee protection" #~ msgstr "Fysik + försvar möjliggör skydd i närstrid" #~ msgid "Mental + Offense grants elemental spell attacks" #~ msgstr "Mental styrka + anfall möjliggör enkla trollformelsattacker" #~ msgid "Mental + Defense grants healing and magical protection" #~ msgstr "Mental styrka + försvar möjliggör helande och magiskt skydd" flare-engine-0.19/mods/default/languages/engine.uk.po000066400000000000000000000673311224717101500225700ustar00rootroot00000000000000# Ukrainian language for FLARE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Igor Paliychuk , 2011, 2012. # msgid "" msgstr "" "Project-Id-Version: 0.19\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2013-03-16 11:05+0300\n" "Last-Translator: Igor Paliychuk \n" "Language-Team: Ukrainian \n" "Language: Ukrainian\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "Ура, ви перейшли на рівень %d!" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "Ви можете покращити характеристику в Меню Персонажа." #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "Вас перемогли. Кінець гри! Натисніть Enter щоб повернутись до меню." #: ../../../src/Avatar.cpp:634 msgid "You are defeated. Press Enter to continue." msgstr "Вас перемогли. Натисніть Enter щоб продовжити." #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "%d %s втрачено." #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "%s втрачено." #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "Ви отримали %s." #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "Ви отримали %s x%d." #: ../../../src/CampaignManager.cpp:168 #, c-format msgid "You receive %d %s." msgstr "Ви отримали %d %s." #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "Ви здобули %d ДВ." #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "ЗД відновлено." #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "МН відновлено." #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "ЗД та МН відновлені." #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "Шкідливі ефекти усунено." #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "ЗД та МН відновлені, шкідливі ефекти усунено" #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "промах" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "+%d ЗД" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "+%d МН" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "Невідомий пункт призначення" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "Гаразд" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "Типово" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "Скасувати" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "Відео" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "Аудіо" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "Інтерфейс" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "Керування" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "Клавіші" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "Моди" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "Задати: " #: ../../../src/GameStateConfig.cpp:165 msgid "Reset ALL settings?" msgstr "Скинути ВСЕ?" #: ../../../src/GameStateConfig.cpp:166 msgid "Use this resolution?" msgstr "Використати це розширення?" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "На весь екран" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "Переміщення мишкою" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "Показувати текст бою" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "Апаратні поверхні" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "Подвійна буферизація" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "Ввімк. джойстик" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "Високоякісні текстури" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "Дозволити зміну гами" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "Анімація оточення" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "Цілитись мишкою" #: ../../../src/GameStateConfig.cpp:318 msgid "Do not use mouse" msgstr "Не користуватись мишкою" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "Показувати FPS" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "Мітки гарячих клавіш" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "Безколірний режим" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "Гучність музики" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "Гучність звуків" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "Гама" #: ../../../src/GameStateConfig.cpp:377 msgid "Joystick Deadzone" msgstr "Мертва зона джойстика" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "Розширення" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "Активні моди" #: ../../../src/GameStateConfig.cpp:412 msgid "Available Mods" msgstr "Наявні моди" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "Джойстик" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "Мова" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 msgid "Disable for performance" msgstr "Вимкніть для швидкодії" #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "Експериментально" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "Для портативних пристроїв" #: ../../../src/GameStateConfig.cpp:527 msgid "<< Disable" msgstr "<< Вимкнути" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr "Ввімкнути >>" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "Видалити" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "Видалити цього персонажа?" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "Головне меню" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "Виберіть слот" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "Нова гра" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "Увімкніть мод повісті щоб продовжити" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "Завантажити" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "Входжу в ігровий світ..." #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "Завантажую збереження..." #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "Рівень %d %s" #: ../../../src/GameStateLoad.cpp:579 msgid "Permadeath" msgstr "Не воскресає" #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "Порожній слот" #: ../../../src/GameStateNew.cpp:62 msgid "Create" msgstr "Створити" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "Виберіть портрет" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "Вкажіть ім'я" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "Не воскресає" #: ../../../src/GameStateNew.cpp:179 msgid "Choose a Class" msgstr "Виберіть клас" #: ../../../src/GameStatePlay.cpp:99 msgid "Loading..." msgstr "Завантаження..." #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "Інвентар заповнений." #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "Грати гру" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "Увімкніть базовий мод щоб продовжити" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "Параметри" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "Автори" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "Вийти з гри" #: ../../../src/GameStateTitle.cpp:67 msgid "Flare Alpha v0.19" msgstr "Flare Альфа v0.19" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "Прийняти" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "Вверх" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "Вниз" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "Вліво" #: ../../../src/InputState.cpp:627 msgid "Right" msgstr "Вправо" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "Слот1" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "Слот2" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "Слот3" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "Слот4" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "Слот5" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "Слот6" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "Слот7" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "Слот8" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "Слот9" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "Слот0" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "Персонаж" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "Інвентар" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "Уміння" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "Журнал" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "Дія1" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "Дія2" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "Ctrl" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "Shift" #: ../../../src/InputState.cpp:646 msgid "Delete" msgstr "Видалити" #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "Панель дій: Прийняти" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "Панель дій: Вліво" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "Панель дій: Вправо" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "Панель дій: Використати" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "лкм" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "скм" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "пкм" #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "кол вверх" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "кол вниз" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "кмx1" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "кмx2" #: ../../../src/ItemManager.cpp:488 msgid "Low" msgstr "Низька" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "Звичайна" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "Висока" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "Епічна" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "Рівень %d" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "Ближня шкода: %d-%d" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "Ближня шкода: %d" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "Дальня шкода: %d-%d" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "Дальня шкода: %d" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "Психічна шкода: %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "Психічна шкода: %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "Поглинання: %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "Поглинання: %d" #: ../../../src/ItemManager.cpp:554 #, c-format msgid "%d% Speed" msgstr "%d% Швидкості" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "Збільшує %s на %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "Зменшує %s на %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "Вимагає %d Фізики" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "Вимагає %d Психіки" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "Вимагає %d Нападу" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "Вимагає %d Захисту" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "Якість: %s" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, c-format msgid "Buy Price: %d %s" msgstr "Ціна купівлі: %d %s" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, c-format msgid "Buy Price: %d %s each" msgstr "Вартість купівлі: %d %s кожен" #: ../../../src/ItemManager.cpp:643 #, c-format msgid "Sell Price: %d %s" msgstr "Ціна продажу: %d %s" #: ../../../src/ItemManager.cpp:645 #, c-format msgid "Sell Price: %d %s each" msgstr "Вартість продажу: %d %s кожен" #: ../../../src/ItemManager.cpp:655 msgid "Set: " msgstr "Набір: " #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "%d предмети: " #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "Ім'я" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "Рівень" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "Фізика" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "Психіка" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "Напад" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "Захист" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "очок залишилось" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "Макс ЗД:" #: ../../../src/MenuCharacter.cpp:340 msgid "HP Regen:" msgstr "Відновлення ЗД:" #: ../../../src/MenuCharacter.cpp:341 msgid "Ticks of HP regen per minute. " msgstr "Відновлення ЗД за хвилину. " #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "Макс МН:" #: ../../../src/MenuCharacter.cpp:352 msgid "MP Regen:" msgstr "Відновлення МН:" #: ../../../src/MenuCharacter.cpp:353 msgid "Ticks of MP regen per minute. " msgstr "Відновлення МП за хвилину. " #: ../../../src/MenuCharacter.cpp:358 msgid "Accuracy:" msgstr "Точність:" #: ../../../src/MenuCharacter.cpp:364 msgid "Avoidance:" msgstr "Ухилення:" #: ../../../src/MenuCharacter.cpp:370 msgid "Melee Damage:" msgstr "Ближня шкода:" #: ../../../src/MenuCharacter.cpp:380 msgid "Ranged Damage:" msgstr "Дальня шкода:" #: ../../../src/MenuCharacter.cpp:390 msgid "Mental Damage:" msgstr "Психічна шкода:" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "Крит:" #: ../../../src/MenuCharacter.cpp:406 msgid "Absorb:" msgstr "Поглинання:" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "Рівновага: " #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "Знижує ймовірність спотикання при попаданні" #: ../../../src/MenuCharacter.cpp:422 msgid "Bonus XP: " msgstr "Бонус ДВ: " #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "Збільшує ДВ отриманий за вбивство" #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "Бонус" #: ../../../src/MenuCharacter.cpp:429 #, c-format msgid "Increases the %s found per drop" msgstr "Збільшує %s знайдене за падіння" #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "Бонус знайдених предметів: " #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "Збільшує ймовірність того, що ворог впустить предмет, коли буде вбитий" #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "Хитрість: " #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "Збільшує уміння рухатись непоміченим" #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "Досвід: %d" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "Наступний: %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "Фізика (P) збільшує володіння зброєю ближнього бою та значення Життя." #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "базове (%d), бонус (%d)" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "Психіка (M) збільшує володіння психічною зброєю та значення Мани." #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "Напад (O) збільшує володіння зброєю дальноього бою та точність." #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "Захист (D) збільшує володіння обладунками та ухилення." #: ../../../src/MenuCharacter.cpp:498 #, c-format msgid "Each level grants %d. " msgstr "Кожен рівень додає %d. " #: ../../../src/MenuCharacter.cpp:500 #, c-format msgid "Each point of Physical grants %d. " msgstr "Кожне очко Фізики додає %d. " #: ../../../src/MenuCharacter.cpp:502 #, c-format msgid "Each point of Mental grants %d. " msgstr "Кожне очко Психіки додає %d. " #: ../../../src/MenuCharacter.cpp:504 #, c-format msgid "Each point of Offense grants %d. " msgstr "Кожне очко Нападу додає %d. " #: ../../../src/MenuCharacter.cpp:506 #, c-format msgid "Each point of Defense grants %d. " msgstr "Кожне очко Захисту додає %d. " #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "Мертвий" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "%s рівень %d" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "Вийти" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "Зберегти та вийти?" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "Втрачено %d%% з %s. " #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "Втрачено %d%% з загального ДВ. " #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "Втрачено %d%% з ДВ поточного рівня. " #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "Втрачено %s." #: ../../../src/MenuInventory.cpp:228 #, c-format msgid "%d %s" msgstr "%d %s" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "SHIFT для переміщення одного предмету." #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "CTRL-клік на предметі щоб його продати." #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "Цей предмет може бути використаний лише з панелі дій." #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "Замітки" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "Квести" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "Досвід: %d/%d" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, c-format msgid "Not enough %s." msgstr "Недостатньо %s." #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "Торгувати" #: ../../../src/MenuPowers.cpp:463 msgid "Unspent skill points:" msgstr "Невитрачені очки умінь:" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" "\n" "Наступний рівень:" #: ../../../src/MenuPowers.cpp:525 #, c-format msgid "Requires a %s" msgstr "Вимагає %s" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "Потрібен Фізичний Напад %d" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "Потрібен Фізичний Захист %d" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "Потрібен Психічний Напад %d" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "Потрібен Психічний Захист %d" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, c-format msgid "Requires Level %d" msgstr "Вимагає Рівень %d" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, c-format msgid "Requires %d Skill Point" msgstr "Вимагає %d Очко Умінь" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "Клацніть для вивчення" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, c-format msgid "Requires Power: %s" msgstr "Вимагає Уміння: %s" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "Коштує %d MP" #: ../../../src/MenuPowers.cpp:625 #, c-format msgid "Costs %d HP" msgstr "Коштує %d HP" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "Перезарядка: %d секунд" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "Загальний тайник" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "Зворотня покупка" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "Торговець" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "+%d Захисту" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "Ви вже трансформовані, спершу відновіть початкову форму." #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "Шукач пригод" #: ../../../src/Utils.cpp:519 msgid "k" msgstr "к" #~ msgid "Character Menu (C)" #~ msgstr "Меню персонажа (C)" #~ msgid "Inventory Menu (I)" #~ msgstr "Інвентар (I)" #~ msgid "Power Menu (P)" #~ msgstr "Уміння (P)" #~ msgid "Log Menu (L)" #~ msgstr "Журнал (L)" #~ msgid "Ticks of HP regen per minute. Each point of Physical grants +%d HP regen. Each level grants +%d HP regen" #~ msgstr "Відновлення ЗД за хвилину. Кожне очко Фізики додає +%d відновлення ЗД. Кожен рівень додає +%d відновлення ЗД" #~ msgid "Ticks of MP regen per minute. Each point of Mental grants +%d MP regen. Each level grants +%d MP regen" #~ msgstr "Відновлення МН за хвилину. Кожне очко Психіки додає +%d відновлення МН. Кожен рівень додає +%d відновлення МН" #~ msgid "Each point of Offense grants +%d accuracy. Each level grants +%d accuracy" #~ msgstr "Кожне очко Нападу додає +%d точності. Кожен рівень додає +%d точності" #~ msgid "Each point of Defense grants +%d avoidance. Each level grants +%d avoidance" #~ msgstr "Кожне очко Захисту додає +%d ухилення. Кожен рівень додає +%d ухилення" #~ msgid "Requires a physical weapon" #~ msgstr "Вимагає фізичну зброю" #~ msgid "Requires a mental weapon" #~ msgstr "Вимагає психічну зброю" #~ msgid "Requires an offense weapon" #~ msgstr "Вимагає зброю нападу" flare-engine-0.19/mods/default/languages/engine.zh.po000066400000000000000000000574371224717101500226000ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-11-20 16:48+0100\n" "PO-Revision-Date: 2013-04-09 18:55+0800\n" "Last-Translator: lonsine \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../../../src/Avatar.cpp:430 #, c-format msgid "Congratulations, you have reached level %d!" msgstr "恭喜!你到到了等级 %d!" #: ../../../src/Avatar.cpp:432 msgid "You may increase one attribute through the Character Menu." msgstr "你可以在角色菜单增加一点属性" #: ../../../src/Avatar.cpp:631 msgid "You are defeated. Game over! Press Enter to exit to Title." msgstr "角色死亡,游戏结束!按下回车键返回游戏开戏。" #: ../../../src/Avatar.cpp:634 #, fuzzy msgid "You are defeated. Press Enter to continue." msgstr "角色死亡,你失去了一般的 %s. 按下回车键继续。" #: ../../../src/CampaignManager.cpp:133 #, c-format msgid "%d %s removed." msgstr "" #: ../../../src/CampaignManager.cpp:139 #, c-format msgid "%s removed." msgstr "" #: ../../../src/CampaignManager.cpp:154 #, c-format msgid "You receive %s." msgstr "你收到 %s." #: ../../../src/CampaignManager.cpp:156 #, c-format msgid "You receive %s x%d." msgstr "你收到 %s x%d." #: ../../../src/CampaignManager.cpp:168 #, c-format msgid "You receive %d %s." msgstr "你收到 %d %s." #: ../../../src/CampaignManager.cpp:178 #, c-format msgid "You receive %d XP." msgstr "你收到 %d XP." #: ../../../src/CampaignManager.cpp:184 msgid "HP restored." msgstr "HP 已恢复." #: ../../../src/CampaignManager.cpp:188 msgid "MP restored." msgstr "MP 已恢复." #: ../../../src/CampaignManager.cpp:193 msgid "HP and MP restored." msgstr "HP 和 MP 已恢复." #: ../../../src/CampaignManager.cpp:197 msgid "Negative effects removed." msgstr "负面影响已消除." #: ../../../src/CampaignManager.cpp:203 msgid "HP and MP restored, negative effects removed" msgstr "HP 和MP 已恢复, 负面影响已消除" #: ../../../src/Entity.cpp:158 msgid "miss" msgstr "未击中" #: ../../../src/Entity.cpp:278 ../../../src/PowerManager.cpp:772 #: ../../../src/StatBlock.cpp:568 #, c-format msgid "+%d HP" msgstr "+%d HP" #: ../../../src/Entity.cpp:284 ../../../src/StatBlock.cpp:573 #, c-format msgid "+%d MP" msgstr "+%d MP" #: ../../../src/EventManager.cpp:457 msgid "Unknown destination" msgstr "无法进入" #: ../../../src/GameStateConfig.cpp:74 ../../../src/GameStateConfig.cpp:166 msgid "OK" msgstr "确定" #: ../../../src/GameStateConfig.cpp:79 ../../../src/GameStateConfig.cpp:165 msgid "Defaults" msgstr "默认设置" #: ../../../src/GameStateConfig.cpp:84 ../../../src/GameStateNew.cpp:56 #: ../../../src/InputState.cpp:622 ../../../src/MenuNPCActions.cpp:71 msgid "Cancel" msgstr "取消设置" #: ../../../src/GameStateConfig.cpp:156 msgid "Video" msgstr "画面" #: ../../../src/GameStateConfig.cpp:157 msgid "Audio" msgstr "声音" #: ../../../src/GameStateConfig.cpp:158 msgid "Interface" msgstr "界面" #: ../../../src/GameStateConfig.cpp:159 msgid "Input" msgstr "输入" #: ../../../src/GameStateConfig.cpp:160 msgid "Keybindings" msgstr "快捷键" #: ../../../src/GameStateConfig.cpp:161 msgid "Mods" msgstr "模块" #: ../../../src/GameStateConfig.cpp:164 ../../../src/GameStateConfig.cpp:1003 #: ../../../src/GameStateConfig.cpp:1005 msgid "Assign: " msgstr "分配" #: ../../../src/GameStateConfig.cpp:165 msgid "Reset ALL settings?" msgstr "确定重置?" #: ../../../src/GameStateConfig.cpp:166 msgid "Use this resolution?" msgstr "使用此分辨率" #: ../../../src/GameStateConfig.cpp:288 msgid "Full Screen Mode" msgstr "全屏模式" #: ../../../src/GameStateConfig.cpp:291 msgid "Move hero using mouse" msgstr "使用鼠标移动人物" #: ../../../src/GameStateConfig.cpp:294 msgid "Show combat text" msgstr "显示战斗文字" #: ../../../src/GameStateConfig.cpp:297 msgid "Hardware surfaces" msgstr "硬件加速" #: ../../../src/GameStateConfig.cpp:300 msgid "Double buffering" msgstr "双缓冲" #: ../../../src/GameStateConfig.cpp:303 msgid "Use joystick" msgstr "使用joystick" #: ../../../src/GameStateConfig.cpp:306 msgid "High Quality Textures" msgstr "高质量背景" #: ../../../src/GameStateConfig.cpp:309 msgid "Allow changing gamma" msgstr "允许更改亮度" #: ../../../src/GameStateConfig.cpp:312 msgid "Animated tiles" msgstr "动画拼图" #: ../../../src/GameStateConfig.cpp:315 msgid "Mouse aim" msgstr "使用鼠标瞄准敌人" #: ../../../src/GameStateConfig.cpp:318 #, fuzzy msgid "Do not use mouse" msgstr "使用鼠标移动人物" #: ../../../src/GameStateConfig.cpp:321 msgid "Show FPS" msgstr "显示画面每秒帧数" #: ../../../src/GameStateConfig.cpp:324 msgid "Show Hotkeys Labels" msgstr "" #: ../../../src/GameStateConfig.cpp:327 msgid "Colorblind Mode" msgstr "" #: ../../../src/GameStateConfig.cpp:338 msgid "Music Volume" msgstr "背景音乐音量" #: ../../../src/GameStateConfig.cpp:351 msgid "Sound Volume" msgstr "游戏音乐音量" #: ../../../src/GameStateConfig.cpp:364 msgid "Gamma" msgstr "亮度" #: ../../../src/GameStateConfig.cpp:377 #, fuzzy msgid "Joystick Deadzone" msgstr "Joystick" #: ../../../src/GameStateConfig.cpp:391 msgid "Resolution" msgstr "分辨率" #: ../../../src/GameStateConfig.cpp:402 msgid "Active Mods" msgstr "激活模块" #: ../../../src/GameStateConfig.cpp:412 msgid "Available Mods" msgstr "可用模块" #: ../../../src/GameStateConfig.cpp:428 msgid "Joystick" msgstr "Joystick" #: ../../../src/GameStateConfig.cpp:440 msgid "Language" msgstr "语言" #: ../../../src/GameStateConfig.cpp:479 ../../../src/GameStateConfig.cpp:486 #: ../../../src/GameStateConfig.cpp:493 msgid "Disable for performance" msgstr "禁用以提高性能" #: ../../../src/GameStateConfig.cpp:500 msgid "Experimental" msgstr "实验功能" #: ../../../src/GameStateConfig.cpp:507 msgid "For handheld devices" msgstr "" #: ../../../src/GameStateConfig.cpp:527 msgid "<< Disable" msgstr "<< 禁用" #: ../../../src/GameStateConfig.cpp:535 msgid "Enable >>" msgstr " 启用>>" #: ../../../src/GameStateLoad.cpp:55 ../../../src/GameStateLoad.cpp:67 msgid "Delete Save" msgstr "删除角色" #: ../../../src/GameStateLoad.cpp:55 msgid "Delete this save?" msgstr "确定删除角色?" #: ../../../src/GameStateLoad.cpp:57 msgid "Exit to Title" msgstr "回到游戏开始" #: ../../../src/GameStateLoad.cpp:63 msgid "Choose a Slot" msgstr "选择一个人物" #: ../../../src/GameStateLoad.cpp:482 msgid "New Game" msgstr "新游戏" #: ../../../src/GameStateLoad.cpp:486 ../../../src/GameStateLoad.cpp:501 msgid "Enable a story mod to continue" msgstr "使用故事模式继续" #: ../../../src/GameStateLoad.cpp:496 msgid "Load Game" msgstr "载入游戏" #: ../../../src/GameStateLoad.cpp:551 msgid "Entering game world..." msgstr "进入游戏..." #: ../../../src/GameStateLoad.cpp:554 msgid "Loading saved game..." msgstr "载入游戏..." #: ../../../src/GameStateLoad.cpp:577 #, c-format msgid "Level %d %s" msgstr "级别 %d %s" #: ../../../src/GameStateLoad.cpp:579 #, fuzzy msgid "Permadeath" msgstr "死亡后不可复活?" #: ../../../src/GameStateLoad.cpp:603 msgid "Empty Slot" msgstr "空" #: ../../../src/GameStateNew.cpp:62 msgid "Create" msgstr "创建" #: ../../../src/GameStateNew.cpp:173 msgid "Choose a Portrait" msgstr "选择头像" #: ../../../src/GameStateNew.cpp:175 msgid "Choose a Name" msgstr "输入名字" #: ../../../src/GameStateNew.cpp:177 msgid "Permadeath?" msgstr "死亡后不可复活?" #: ../../../src/GameStateNew.cpp:179 msgid "Choose a Class" msgstr "选择职业" #: ../../../src/GameStatePlay.cpp:99 msgid "Loading..." msgstr "载入中..." #: ../../../src/GameStatePlay.cpp:227 ../../../src/GameStatePlay.cpp:228 #: ../../../src/GameStatePlay.cpp:245 ../../../src/GameStatePlay.cpp:246 #: ../../../src/MenuManager.cpp:658 ../../../src/MenuManager.cpp:659 #: ../../../src/MenuManager.cpp:685 ../../../src/MenuManager.cpp:686 #: ../../../src/MenuManager.cpp:865 ../../../src/MenuManager.cpp:866 #: ../../../src/MenuManager.cpp:884 ../../../src/MenuManager.cpp:885 #: ../../../src/MenuManager.cpp:1043 ../../../src/MenuManager.cpp:1044 #: ../../../src/MenuManager.cpp:1084 ../../../src/MenuManager.cpp:1085 msgid "Inventory is full." msgstr "背包已满" #: ../../../src/GameStateTitle.cpp:41 msgid "Play Game" msgstr "开始游戏" #: ../../../src/GameStateTitle.cpp:46 msgid "Enable a core mod to continue" msgstr "使用 core mod 继续" #: ../../../src/GameStateTitle.cpp:50 msgid "Configuration" msgstr "配置" #: ../../../src/GameStateTitle.cpp:55 msgid "Credits" msgstr "" #: ../../../src/GameStateTitle.cpp:60 msgid "Exit Game" msgstr "退出游戏" #: ../../../src/GameStateTitle.cpp:67 #, fuzzy msgid "Flare Alpha v0.19" msgstr "Flare 测试版 v0.18" #: ../../../src/InputState.cpp:623 msgid "Accept" msgstr "确定" #: ../../../src/InputState.cpp:624 msgid "Up" msgstr "上" #: ../../../src/InputState.cpp:625 msgid "Down" msgstr "下" #: ../../../src/InputState.cpp:626 msgid "Left" msgstr "左" #: ../../../src/InputState.cpp:627 msgid "Right" msgstr "右" #: ../../../src/InputState.cpp:628 msgid "Bar1" msgstr "槽1" #: ../../../src/InputState.cpp:629 msgid "Bar2" msgstr "槽2" #: ../../../src/InputState.cpp:630 msgid "Bar3" msgstr "槽3" #: ../../../src/InputState.cpp:631 msgid "Bar4" msgstr "槽4" #: ../../../src/InputState.cpp:632 msgid "Bar5" msgstr "槽5" #: ../../../src/InputState.cpp:633 msgid "Bar6" msgstr "槽6" #: ../../../src/InputState.cpp:634 msgid "Bar7" msgstr "槽7" #: ../../../src/InputState.cpp:635 msgid "Bar8" msgstr "槽8" #: ../../../src/InputState.cpp:636 msgid "Bar9" msgstr "槽9" #: ../../../src/InputState.cpp:637 msgid "Bar0" msgstr "槽0" #: ../../../src/InputState.cpp:638 ../../../src/MenuActionBar.cpp:380 #: ../../../src/MenuActionBar.cpp:382 ../../../src/MenuCharacter.cpp:262 msgid "Character" msgstr "角色" #: ../../../src/InputState.cpp:639 ../../../src/MenuActionBar.cpp:387 #: ../../../src/MenuActionBar.cpp:389 ../../../src/MenuInventory.cpp:224 #: ../../../src/MenuVendor.cpp:50 msgid "Inventory" msgstr "物品" #: ../../../src/InputState.cpp:640 ../../../src/MenuActionBar.cpp:394 #: ../../../src/MenuActionBar.cpp:396 ../../../src/MenuPowers.cpp:194 msgid "Powers" msgstr "技能" #: ../../../src/InputState.cpp:641 ../../../src/MenuActionBar.cpp:401 #: ../../../src/MenuActionBar.cpp:403 ../../../src/MenuLog.cpp:152 msgid "Log" msgstr "说明" #: ../../../src/InputState.cpp:642 msgid "Main1" msgstr "主槽1" #: ../../../src/InputState.cpp:643 msgid "Main2" msgstr "主槽2" #: ../../../src/InputState.cpp:644 msgid "Ctrl" msgstr "Ctrl" #: ../../../src/InputState.cpp:645 msgid "Shift" msgstr "Shift" #: ../../../src/InputState.cpp:646 msgid "Delete" msgstr "删除" #: ../../../src/InputState.cpp:647 msgid "ActionBar Accept" msgstr "" #: ../../../src/InputState.cpp:648 msgid "ActionBar Left" msgstr "" #: ../../../src/InputState.cpp:649 msgid "ActionBar Right" msgstr "" #: ../../../src/InputState.cpp:650 msgid "ActionBar Use" msgstr "" #: ../../../src/InputState.cpp:652 msgid "lmb" msgstr "左键" #: ../../../src/InputState.cpp:653 msgid "mmb" msgstr "mmb" #: ../../../src/InputState.cpp:654 msgid "rmb" msgstr "右键" #: ../../../src/InputState.cpp:655 msgid "wheel up" msgstr "向上滚轮" #: ../../../src/InputState.cpp:656 msgid "wheel down" msgstr "向下滚轮" #: ../../../src/InputState.cpp:657 msgid "mbx1" msgstr "mbx1" #: ../../../src/InputState.cpp:658 msgid "mbx2" msgstr "mbx2" #: ../../../src/ItemManager.cpp:488 #, fuzzy msgid "Low" msgstr "说明" #: ../../../src/ItemManager.cpp:492 msgid "Normal" msgstr "" #: ../../../src/ItemManager.cpp:496 msgid "High" msgstr "" #: ../../../src/ItemManager.cpp:500 msgid "Epic" msgstr "" #: ../../../src/ItemManager.cpp:513 #, c-format msgid "Level %d" msgstr "级别 %d" #: ../../../src/ItemManager.cpp:524 #, c-format msgid "Melee damage: %d-%d" msgstr "近战伤害: %d-%d" #: ../../../src/ItemManager.cpp:526 #, c-format msgid "Melee damage: %d" msgstr "近战伤害 : %d" #: ../../../src/ItemManager.cpp:530 #, c-format msgid "Ranged damage: %d-%d" msgstr "远程伤害: %d-%d" #: ../../../src/ItemManager.cpp:532 #, c-format msgid "Ranged damage: %d" msgstr "远程伤害: %d" #: ../../../src/ItemManager.cpp:536 #, c-format msgid "Mental damage: %d-%d" msgstr "精神伤害: %d-%d" #: ../../../src/ItemManager.cpp:538 #, c-format msgid "Mental damage: %d" msgstr "精神伤害: %d" #: ../../../src/ItemManager.cpp:544 #, c-format msgid "Absorb: %d-%d" msgstr "抵消攻击: %d-%d" #: ../../../src/ItemManager.cpp:546 #, c-format msgid "Absorb: %d" msgstr "抵消攻击: %d" #: ../../../src/ItemManager.cpp:554 #, fuzzy, c-format msgid "%d% Speed" msgstr "%d%% 速度" #: ../../../src/ItemManager.cpp:560 ../../../src/ItemManager.cpp:659 #, c-format msgid "Increases %s by %d" msgstr "增加 %s 量 %d" #: ../../../src/ItemManager.cpp:567 ../../../src/ItemManager.cpp:662 #, c-format msgid "Decreases %s by %d" msgstr "减少 %s 量 %d" #: ../../../src/ItemManager.cpp:588 ../../../src/MenuPowers.cpp:566 #: ../../../src/MenuPowers.cpp:569 #, c-format msgid "Requires Physical %d" msgstr "需要体力 %d" #: ../../../src/ItemManager.cpp:593 ../../../src/MenuPowers.cpp:572 #: ../../../src/MenuPowers.cpp:575 #, c-format msgid "Requires Mental %d" msgstr "需要精神 %d" #: ../../../src/ItemManager.cpp:598 ../../../src/MenuPowers.cpp:554 #: ../../../src/MenuPowers.cpp:557 #, c-format msgid "Requires Offense %d" msgstr "需要攻击 %d" #: ../../../src/ItemManager.cpp:603 ../../../src/MenuPowers.cpp:560 #: ../../../src/MenuPowers.cpp:563 #, c-format msgid "Requires Defense %d" msgstr "需要防御 %d" #: ../../../src/ItemManager.cpp:609 #, c-format msgid "Quality: %s" msgstr "" #: ../../../src/ItemManager.cpp:626 ../../../src/ItemManager.cpp:635 #, c-format msgid "Buy Price: %d %s" msgstr "购买价格: %d %s" #: ../../../src/ItemManager.cpp:628 ../../../src/ItemManager.cpp:637 #, c-format msgid "Buy Price: %d %s each" msgstr "购买单价: %d %s " #: ../../../src/ItemManager.cpp:643 #, c-format msgid "Sell Price: %d %s" msgstr "出售价格: %d %s" #: ../../../src/ItemManager.cpp:645 #, c-format msgid "Sell Price: %d %s each" msgstr "出售单价: %d %s " #: ../../../src/ItemManager.cpp:655 msgid "Set: " msgstr "设置: " #: ../../../src/ItemManager.cpp:659 ../../../src/ItemManager.cpp:662 #, c-format msgid "%d items: " msgstr "%d 物品: " #: ../../../src/MenuCharacter.cpp:275 msgid "Name" msgstr "名字" #: ../../../src/MenuCharacter.cpp:276 msgid "Level" msgstr "级别" #: ../../../src/MenuCharacter.cpp:277 msgid "Physical" msgstr "体力" #: ../../../src/MenuCharacter.cpp:278 msgid "Mental" msgstr "精神" #: ../../../src/MenuCharacter.cpp:279 msgid "Offense" msgstr "攻击" #: ../../../src/MenuCharacter.cpp:280 msgid "Defense" msgstr "防御" #: ../../../src/MenuCharacter.cpp:324 msgid "points remaining" msgstr "未用点数" #: ../../../src/MenuCharacter.cpp:334 msgid "Max HP:" msgstr "最大 HP:" #: ../../../src/MenuCharacter.cpp:340 msgid "HP Regen:" msgstr "HP 恢复:" #: ../../../src/MenuCharacter.cpp:341 msgid "Ticks of HP regen per minute. " msgstr "" #: ../../../src/MenuCharacter.cpp:346 msgid "Max MP:" msgstr "最大 MP:" #: ../../../src/MenuCharacter.cpp:352 msgid "MP Regen:" msgstr "MP 恢复:" #: ../../../src/MenuCharacter.cpp:353 msgid "Ticks of MP regen per minute. " msgstr "" #: ../../../src/MenuCharacter.cpp:358 msgid "Accuracy:" msgstr "准确:" #: ../../../src/MenuCharacter.cpp:364 msgid "Avoidance:" msgstr "敏捷:" #: ../../../src/MenuCharacter.cpp:370 msgid "Melee Damage:" msgstr "近战伤害:" #: ../../../src/MenuCharacter.cpp:380 msgid "Ranged Damage:" msgstr "远程伤害:" #: ../../../src/MenuCharacter.cpp:390 msgid "Mental Damage:" msgstr "精神伤害:" #: ../../../src/MenuCharacter.cpp:400 msgid "Crit:" msgstr "暴击:" #: ../../../src/MenuCharacter.cpp:406 msgid "Absorb:" msgstr "抵消:" #: ../../../src/MenuCharacter.cpp:416 msgid "Poise: " msgstr "平衡: " #: ../../../src/MenuCharacter.cpp:417 msgid "Reduces your chance of stumbling when hit" msgstr "减少被击中后跌倒的可能" #: ../../../src/MenuCharacter.cpp:422 msgid "Bonus XP: " msgstr "奖励 XP: " #: ../../../src/MenuCharacter.cpp:423 msgid "Increases the XP gained per kill" msgstr "增加 XP " #: ../../../src/MenuCharacter.cpp:428 msgid "Bonus" msgstr "奖励" #: ../../../src/MenuCharacter.cpp:429 #, c-format msgid "Increases the %s found per drop" msgstr "爆出金钱增加 %s " #: ../../../src/MenuCharacter.cpp:434 msgid "Bonus Item Find: " msgstr "爆出物品概率" #: ../../../src/MenuCharacter.cpp:435 msgid "Increases the chance that an enemy will drop an item when killed" msgstr "增加敌人死亡后爆出物品的概率" #: ../../../src/MenuCharacter.cpp:440 msgid "Stealth: " msgstr "潜行: " #: ../../../src/MenuCharacter.cpp:441 msgid "Increases your ability to move undetected" msgstr "提升移动时不被发现的能力" #: ../../../src/MenuCharacter.cpp:459 #, c-format msgid "XP: %d" msgstr "XP: %d" #: ../../../src/MenuCharacter.cpp:461 #, c-format msgid "Next: %d" msgstr "Next: %d" #: ../../../src/MenuCharacter.cpp:465 msgid "Physical (P) increases melee weapon proficiency and total HP." msgstr "体力 (P)增加近战武器熟练度和总l HP." #: ../../../src/MenuCharacter.cpp:466 ../../../src/MenuCharacter.cpp:470 #: ../../../src/MenuCharacter.cpp:474 ../../../src/MenuCharacter.cpp:478 #, c-format msgid "base (%d), bonus (%d)" msgstr "base (%d), bonus (%d)" #: ../../../src/MenuCharacter.cpp:469 msgid "Mental (M) increases mental weapon proficiency and total MP." msgstr "精神 (M)增加精神武器熟练度和总 MP." #: ../../../src/MenuCharacter.cpp:473 msgid "Offense (O) increases ranged weapon proficiency and accuracy." msgstr "攻击(O)增加远程武器熟练度和准确度." #: ../../../src/MenuCharacter.cpp:477 msgid "Defense (D) increases armor proficiency and avoidance." msgstr "防御 (D) 增加盾牌熟练度和敏捷度." #: ../../../src/MenuCharacter.cpp:498 #, c-format msgid "Each level grants %d. " msgstr "" #: ../../../src/MenuCharacter.cpp:500 #, fuzzy, c-format msgid "Each point of Physical grants %d. " msgstr "每点体力增加 +%d HP. 每升一级增加 +%d HP" #: ../../../src/MenuCharacter.cpp:502 #, fuzzy, c-format msgid "Each point of Mental grants %d. " msgstr "每点精神增加 +%d MP. 每升一级增加 +%d MP" #: ../../../src/MenuCharacter.cpp:504 #, fuzzy, c-format msgid "Each point of Offense grants %d. " msgstr "每点精神增加 +%d MP. 每升一级增加 +%d MP" #: ../../../src/MenuCharacter.cpp:506 #, fuzzy, c-format msgid "Each point of Defense grants %d. " msgstr "每点精神增加 +%d MP. 每升一级增加 +%d MP" #: ../../../src/MenuEnemy.cpp:117 msgid "Dead" msgstr "死亡" #: ../../../src/MenuEnemy.cpp:123 ../../../src/MenuEnemy.cpp:126 #, c-format msgid "%s level %d" msgstr "%s 级别 %d" #: ../../../src/MenuExit.cpp:31 msgid "Exit" msgstr "退出" #: ../../../src/MenuExit.cpp:48 msgid "Save and exit to title?" msgstr "保存并回到游戏开始菜单?" #: ../../../src/MenuInventory.cpp:146 #, c-format msgid "Lost %d%% of %s. " msgstr "" #: ../../../src/MenuInventory.cpp:153 #, c-format msgid "Lost %d%% of total XP. " msgstr "" #: ../../../src/MenuInventory.cpp:158 #, c-format msgid "Lost %d%% of current level XP. " msgstr "" #: ../../../src/MenuInventory.cpp:184 #, c-format msgid "Lost %s." msgstr "" #: ../../../src/MenuInventory.cpp:228 #, c-format msgid "%d %s" msgstr "%d %s" #: ../../../src/MenuInventory.cpp:263 msgid "Use SHIFT to move only one item." msgstr "使用SHIFT移动单个物品" #: ../../../src/MenuInventory.cpp:264 msgid "CTRL-click a carried item to sell it." msgstr "按住CTRL点击物品出售" #: ../../../src/MenuInventory.cpp:472 msgid "This item can only be used from the action bar." msgstr "此物品只能从动作槽使用" #: ../../../src/MenuLog.cpp:76 msgid "Notes" msgstr "提示" #: ../../../src/MenuLog.cpp:77 msgid "Quests" msgstr "任务" #: ../../../src/MenuManager.cpp:452 #, c-format msgid "XP: %d/%d" msgstr "XP: %d/%d" #: ../../../src/MenuManager.cpp:652 ../../../src/MenuManager.cpp:653 #: ../../../src/MenuManager.cpp:859 ../../../src/MenuManager.cpp:860 #: ../../../src/MenuManager.cpp:1037 ../../../src/MenuManager.cpp:1038 #, fuzzy, c-format msgid "Not enough %s." msgstr "金钱不足" #: ../../../src/MenuNPCActions.cpp:70 msgid "Trade" msgstr "交易" #: ../../../src/MenuPowers.cpp:463 msgid "Unspent skill points:" msgstr "未用点数" #: ../../../src/MenuPowers.cpp:505 msgid "" "\n" "Next Level:" msgstr "" #: ../../../src/MenuPowers.cpp:525 #, fuzzy, c-format msgid "Requires a %s" msgstr "需要精神 %d" #: ../../../src/MenuPowers.cpp:530 ../../../src/MenuPowers.cpp:533 #, c-format msgid "Requires Physical Offense %d" msgstr "需要体力+攻击 %d" #: ../../../src/MenuPowers.cpp:536 ../../../src/MenuPowers.cpp:539 #, c-format msgid "Requires Physical Defense %d" msgstr "需要体力+防御 %d" #: ../../../src/MenuPowers.cpp:542 ../../../src/MenuPowers.cpp:545 #, c-format msgid "Requires Mental Offense %d" msgstr "需要精神+攻击 %d" #: ../../../src/MenuPowers.cpp:548 ../../../src/MenuPowers.cpp:551 #, c-format msgid "Requires Mental Defense %d" msgstr "需要精神+防御 %d" #: ../../../src/MenuPowers.cpp:580 ../../../src/MenuPowers.cpp:583 #, c-format msgid "Requires Level %d" msgstr "需要级别 %d" #: ../../../src/MenuPowers.cpp:590 ../../../src/MenuPowers.cpp:595 #, c-format msgid "Requires %d Skill Point" msgstr "需要 %d 技能点" #: ../../../src/MenuPowers.cpp:603 msgid "Click to Unlock" msgstr "点击解锁" #: ../../../src/MenuPowers.cpp:611 ../../../src/MenuPowers.cpp:614 #, c-format msgid "Requires Power: %s" msgstr "需要技能点: %s" #: ../../../src/MenuPowers.cpp:621 #, c-format msgid "Costs %d MP" msgstr "消耗 %d MP" #: ../../../src/MenuPowers.cpp:625 #, c-format msgid "Costs %d HP" msgstr "消耗 %d HP" #: ../../../src/MenuPowers.cpp:629 #, c-format msgid "Cooldown: %d seconds" msgstr "冷却时间: %d 秒" #: ../../../src/MenuStash.cpp:124 msgid "Shared Stash" msgstr "储物柜" #: ../../../src/MenuVendor.cpp:51 msgid "Buyback" msgstr "购回" #: ../../../src/MenuVendor.cpp:171 msgid "Vendor" msgstr "商人" #: ../../../src/PowerManager.cpp:759 #, c-format msgid "+%d Shield" msgstr "+%d Shield" #: ../../../src/PowerManager.cpp:1006 msgid "You are already transformed, untransform first." msgstr "You are already transformed, untransform first." #: ../../../src/Settings.cpp:594 msgid "Adventurer" msgstr "玩家" #: ../../../src/Utils.cpp:519 msgid "k" msgstr "" #~ msgid "Character Menu (C)" #~ msgstr "角色菜单 (C)" #~ msgid "Inventory Menu (I)" #~ msgstr "背包菜单 (I)" #~ msgid "Power Menu (P)" #~ msgstr "技能菜单 (P)" #~ msgid "Log Menu (L)" #~ msgstr "说明菜单 (L)" #~ msgid "Ticks of HP regen per minute. Each point of Physical grants +%d HP regen. Each level grants +%d HP regen" #~ msgstr "每分钟恢复HP量. 每点体力增加 +%d HP恢复. 每升一级 +%d HP恢复" #~ msgid "Ticks of MP regen per minute. Each point of Mental grants +%d MP regen. Each level grants +%d MP regen" #~ msgstr "每分钟恢复MP量. 每点体力增加 +%d MP恢复. 每升一级 +%d MP恢复" #~ msgid "Each point of Offense grants +%d accuracy. Each level grants +%d accuracy" #~ msgstr "每点攻击增加 +%d 准确度. 每升一级增加 +%d 准确度" #~ msgid "Each point of Defense grants +%d avoidance. Each level grants +%d avoidance" #~ msgstr "每点防御增加 +%d 敏捷度. 每升一级增加 +%d 敏捷度" #~ msgid "Requires a physical weapon" #~ msgstr "需要近战武器" #~ msgid "Requires a mental weapon" #~ msgstr "需要精神武器" #~ msgid "Requires an offense weapon" #~ msgstr "需要远程武器" flare-engine-0.19/mods/default/languages/xgettext.py000077500000000000000000000076531224717101500225770ustar00rootroot00000000000000#! /usr/bin/python import os import datetime import codecs # proper UTF8 handling with files keys = [] comments = [] now = datetime.datetime.now() header = r'''# Copyright (C) 2011 Clint Bellanger # This file is distributed under the same license as the FLARE package. # # FIRST AUTHOR , YEAR. msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: {now}\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" ''' POT_STRING = u'''\ #: {comment} msgid "{msgid}" msgstr "" ''' # this extracts translatable strings from the flare data file def extract(filename): if not os.path.exists(filename): return infile = codecs.open(filename, encoding='UTF-8', mode='r') triggers = [ 'msg', 'him', 'her', 'you', 'name', 'title', 'tooltip', 'power_desc', 'quest_text', 'description', 'item_type', 'slot_name', 'tab_title', 'resist', 'currency_name', 'bonus', 'flavor', 'topic', 'option', 'caption' ] plain_text = [ 'msg', 'him', 'her', 'you', 'name', 'title', 'tooltip', 'quest_text', 'description', 'topic', 'flavor', 'caption', ] for i, line in enumerate(infile, start=1): for trigger in triggers: if line.startswith(trigger + '='): line = line.split('=')[1] line = line.strip('\n') values = line.split(',') if (trigger in plain_text): stat = line.replace("\"", "\\\""); elif len(values) == 1: # {key}={value} stat, = values elif len(values) == 2: # bonus={stat},{value} stat, value = values elif len(values) == 3: # bonus={set_level},{stat},{value} set_level, stat, value = values elif len(values) == 4: # option=base,head,portrait,name stat = values[-1] comment = filename + ':' + str(i) comments.append(comment) keys.append(stat.rstrip()) # this removes duplicates from keys in a clean way (without screwing up the order) def remove_duplicates(): global comments global keys tmp = [] tmp_c = [] for node_c,node in zip(comments,keys): if node not in tmp: tmp_c.append(node_c) tmp.append(node) comments = tmp_c keys = tmp # this writes the list of keys to a gettext .po file def save(filename): outfile = codecs.open('data.pot', encoding='UTF-8', mode='w') outfile.write(header.format(now=now.strftime('%Y-%m-%d %H:%M+%z'))) remove_duplicates() for line_c,line in zip(comments,keys): outfile.write(POT_STRING.format(comment=line_c, msgid=line)) # this extracts the quest files from the quests directory def get_quests(): quests = set() infile = open('../quests/index.txt', 'r') for line in infile.readlines(): quests.add(line.strip('\n')) infile.close() return quests # HERE'S THE MAIN EXECUTION extract('../items/items.txt') extract('../items/types.txt') extract('../items/sets.txt') extract('../menus/inventory.txt') extract('../menus/powers.txt') extract('../powers/effects.txt') extract('../powers/powers.txt') extract('../engine/elements.txt') extract('../engine/loot.txt') extract('../engine/classes.txt') extract('../engine/hero_options.txt') extract('../engine/titles.txt') extract('../engine/equip_flags.txt') for folder in ['enemies', 'maps', 'quests', 'npcs', 'cutscenes']: target = os.path.join('..', folder) if os.path.exists(target): for filename in sorted(os.listdir(target)): extract(os.path.join(target, filename)) save('data.pot') flare-engine-0.19/mods/default/menus/000077500000000000000000000000001224717101500175145ustar00rootroot00000000000000flare-engine-0.19/mods/default/menus/config.txt000066400000000000000000000037741224717101500215350ustar00rootroot00000000000000# Configuration menu Widgets Definitions. # Coordinates should be integer, representing absolute position on 640x480 screen # First two values are for label position (x,y) and two last for control (x,y) # Buttons don't have separate labels listbox_scrollbar_offset=2 [video] resolution=64,16,32,32 fullscreen=352,40,384,32 hwsurface=352,72,384,64 doublebuf=352,104,384,96 hws_note=416,72 dbuf_note=416,104 change_gamma=352,136,384,128 gamma=352,168,384,160 texture_quality=352,200,384,192 animated_tiles=352,232,384,224 anim_tiles_note=416,232 test_note=416,136 [audio] music_volume=224,8,256,0 sound_volume=224,40,256,32 [interface] language=64,16,32,32 combat_text=352,40,384,32 show_fps=352,72,384,64 colorblind=352,104,384,96 show_hotkeys=352,136,384,128 [input] joystick_device=64,16,32,32 enable_joystick=352,40,384,32 mouse_move=352,72,384,64 mouse_aim=352,104,384,96 no_mouse=352,136,384,128 joystick_deadzone=352,168,384,160 handheld_note=416,136 [key_bindings] # scrollpane values are positions x, y and sizes width, height scrollpane=0,4,600,320 # scrollpane_contents is the height of the scrollpane's internal area scrollpane_contents=880 keybinds_bg_color=26,26,26 cancel=160,10,202,10 accept=160,40,202,40 up=160,70,202,70 down=160,100,202,100 left=160,130,202,130 right=160,160,202,160 bar1=160,190,202,190 bar2=160,220,202,220 bar3=160,250,202,250 bar4=160,280,202,280 bar5=160,310,202,310 bar6=160,340,202,340 bar7=160,370,202,370 bar8=160,400,202,400 bar9=160,430,202,430 bar0=160,460,202,460 main1=160,490,202,490 main2=160,520,202,520 character=160,550,202,550 inventory=160,580,202,580 powers=160,610,202,610 log=160,640,202,640 ctrl=160,670,202,670 shift=160,700,202,700 delete=160,730,202,730 actionbar=160,760,202,760 actionbar_back=160,790,202,790 actionbar_forward=160,820,202,820 actionbar_use=160,850,202,850 secondary_offset=145,0 [mods] activemods=416,16,384,32 inactivemods=96,16,64,32 activemods_shiftup=544,128 activemods_shiftdown=544,160 activemods_deactivate=224,160 inactivemods_activate=224,128 flare-engine-0.19/mods/default/menus/fps.txt000066400000000000000000000003001224717101500210360ustar00rootroot00000000000000# Settings for the FPS displaying # position is x,y,corner, where corner is any of the following: # top_left, top_right, bottom_left, bottom_right position=0,0,bottom_right color=255,255,255 flare-engine-0.19/mods/default/menus/gameload.txt000066400000000000000000000004651224717101500220330ustar00rootroot00000000000000# Settings for the GameLoad menu # the first two values are x,y positions # some items have two more values, width and height action_button=409,384 alternate_button=409,415 portrait=320,32,320,320 gameslot=0,32,288,96 preview=0,0,512,128 name=16,16 level=24,40 map=24,56 sprite=178,-24 loading_label=480,366 flare-engine-0.19/mods/default/menus/gamenew.txt000066400000000000000000000004601224717101500217000ustar00rootroot00000000000000# Settings for the GameNew menu # the first two values are x,y positions # some items have two more values, width and height button_prev=136,216 button_next=480,216 button_permadeath=256,425 name_input=256,404 portrait_label=320,40 name_label=320,388 permadeath_label=285,436 portrait=160,60,320,320 flare-engine-0.19/mods/default/menus/menus.txt000066400000000000000000000031311224717101500214020ustar00rootroot00000000000000# Menu Definitions # First two values are x and y position; Next 2 values are width and height # The last value is the menu's alignment on the screen, possible values are: # topleft, top, topright, left, center, right, bottomleft, bottom, bottomright [menu] id=hp layout=0,0,106,33 align=topleft [menu] id=mp layout=0,18,106,33 align=topleft [menu] id=xp layout=0,36,106,26 align=topleft [menu] id=effects layout=106,0,0,0 align=topleft [menu] id=hudlog layout=32,-40,224,0 align=bottomleft [menu] id=actionbar layout=0,0,640,35 align=bottom [menu] id=enemy layout=0,0,106,33 align=top [menu] id=vendor layout=0,0,320,416 align=left soundfx_open=soundfx/inventory/inventory_page.ogg soundfx_close=soundfx/inventory/inventory_book.ogg [menu] id=talker layout=0,0,640,416 align=center [menu] id=exit layout=0,0,192,64 align=center [menu] id=minimap layout=0,0,128,128 align=topright [menu] id=character layout=0,0,320,416 align=left soundfx_open=soundfx/inventory/inventory_page.ogg soundfx_close=soundfx/inventory/inventory_book.ogg [menu] id=inventory layout=0,0,320,416 align=right soundfx_open=soundfx/inventory/inventory_page.ogg soundfx_close=soundfx/inventory/inventory_book.ogg [menu] id=powers layout=0,0,320,416 align=right soundfx_open=soundfx/inventory/inventory_page.ogg soundfx_close=soundfx/inventory/inventory_book.ogg [menu] id=log layout=0,0,320,416 align=left soundfx_open=soundfx/inventory/inventory_page.ogg soundfx_close=soundfx/inventory/inventory_book.ogg [menu] id=stash layout=0,0,320,416 align=left soundfx_open=soundfx/wood_open.ogg [menu] id=confirm layout=0,0,192,64 align=center flare-engine-0.19/mods/mods.txt000066400000000000000000000001201224717101500164350ustar00rootroot00000000000000# Mods lower on the list will overwrite data in the entries higher on the list flare-engine-0.19/src/000077500000000000000000000000001224717101500145665ustar00rootroot00000000000000flare-engine-0.19/src/AStarContainer.cpp000066400000000000000000000132671224717101500201600ustar00rootroot00000000000000/* Copyright © 2013 Ryan Dansie This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "AStarContainer.h" #include #include AStarContainer::AStarContainer(unsigned int map_width, unsigned int node_limit) : size(0) { nodes = new AStarNode*[node_limit]; map_pos = new astar_mapcol[map_width]; //initialise the map array. A -1 value will mean there is no node at that position for(unsigned i = 0; i < map_width; ++i) std::fill(map_pos[i], map_pos[i] + 256, -1); } AStarContainer::~AStarContainer() { for(unsigned int i=0; igetX()][node->getY()] = size; //reorder the heap based on f ordering, staring with thenewly added node and working up the tree from there int m = size; AStarNode* temp = NULL; while(m != 0) { //if the current nodes f value is shorter than its parent, they need to be swapped if(nodes[m]->getFinalCost() <= nodes[m/2]->getFinalCost()) { temp = nodes[m/2]; nodes[m/2] = nodes[m]; map_pos[nodes[m/2]->getX()][nodes[m/2]->getY()] = m/2; nodes[m] = temp; map_pos[nodes[m]->getX()][nodes[m]->getY()] = m; m=m/2; } else break; } size++; } AStarNode* AStarContainer::get_shortest_f() { return nodes[0]; } void AStarContainer::remove(AStarNode* node) { unsigned int heap_indexv = map_pos[node->getX()][node->getY()] + 1; //swap the last node in the list with the node being deleted nodes[heap_indexv-1] = nodes[size-1]; map_pos[nodes[heap_indexv-1]->getX()][nodes[heap_indexv-1]->getY()] = heap_indexv-1; size--; if(size == 0) { map_pos[node->getX()][node->getY()] = -1; return; } // reorder the heap to maintain the f ordering, starting at the node which replaced the deleted node, and working down the tree while(true) { //start at the node which dropped down the tree on the previous iteration unsigned int heap_indexu = heap_indexv; if(2*heap_indexu+1 <= size) { //if both children exist //Select the lowest of the two children. if(nodes[heap_indexu-1]->getFinalCost() >= nodes[2*heap_indexu-1]->getFinalCost()) heap_indexv = 2*heap_indexu; if(nodes[heap_indexv-1]->getFinalCost() >= nodes[2*heap_indexu]->getFinalCost()) heap_indexv = 2*heap_indexu+1; } else if (2*heap_indexu <= size) { //if only child #1 exists //Check if the F cost is greater than the child if(nodes[heap_indexu-1]->getFinalCost() >= nodes[2*heap_indexu-1]->getFinalCost()) heap_indexv = 2*heap_indexu; } if(heap_indexu != heap_indexv) { //If parent's F > one or both of its children, swap them AStarNode* temp = nodes[heap_indexu-1]; nodes[heap_indexu-1] = nodes[heap_indexv-1]; map_pos[nodes[heap_indexu-1]->getX()][nodes[heap_indexu-1]->getY()] = heap_indexu-1; nodes[heap_indexv-1] = temp; map_pos[nodes[heap_indexv-1]->getX()][nodes[heap_indexv-1]->getY()] = heap_indexv-1; } else { break;//if item <= both children, exit loop } }//Repeat forever //remove the node from the map pos index map_pos[node->getX()][node->getY()] = -1; } bool AStarContainer::exists(Point pos) { return map_pos[pos.x][pos.y] != -1; } AStarNode* AStarContainer::get(int x, int y) { return nodes[map_pos[x][y]]; } bool AStarContainer::isEmpty() { return size == 0; } void AStarContainer::updateParent(Point pos, Point parent_pos, float score) { get(pos.x, pos.y)->setParent(parent_pos); get(pos.x, pos.y)->setActualCost(score); //reorder the heap based on the new f value of this node. starting at the updated node and working up the tree int m = map_pos[pos.x][pos.y]; AStarNode* temp = NULL; while(m != 0) { //if the current node has a lower f value than its parent in the heap, swap them if(nodes[m]->getFinalCost() <= nodes[m/2]->getFinalCost()) { temp = nodes[m/2]; nodes[m/2] = nodes[m]; map_pos[nodes[m/2]->getX()][nodes[m/2]->getY()] = m/2; nodes[m] = temp; map_pos[nodes[m]->getX()][nodes[m]->getY()] = m; m=m/2; } else break; } } AStarCloseContainer::AStarCloseContainer(unsigned int map_width, unsigned int node_limit) : size(0) { nodes = new AStarNode*[node_limit]; map_pos = new astar_mapcol[map_width]; //initialise the map index array. A -1 value will mean there is no node at that position for (unsigned i = 0; i < map_width; ++i) std::fill(map_pos[i], map_pos[i] + 256, -1); } AStarCloseContainer::~AStarCloseContainer() { for(unsigned int i=0; igetX()][node->getY()] = size; size++; } bool AStarCloseContainer::exists(Point pos) { return map_pos[pos.x][pos.y] != -1; } AStarNode* AStarCloseContainer::get(int x, int y) { return nodes[map_pos[x][y]]; } AStarNode* AStarCloseContainer::get_shortest_h() { AStarNode *current = NULL; float lowest_score = FLT_MAX; for(unsigned int i = 0; i < size; i++) { if(nodes[i]->getH() < lowest_score) { lowest_score = nodes[i]->getH(); current = nodes[i]; } } return current; } flare-engine-0.19/src/AStarContainer.h000066400000000000000000000111041224717101500176110ustar00rootroot00000000000000/* Copyright © 2013 Ryan Dansie This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #ifndef ASTARCONTAINER_H #define ASTARCONTAINER_H #include "AStarNode.h" /* Designed to be used for the Open nodes. * Unsuitable for Closed nodes but a close node conatiner is declared below * * All code in the class assumes that the nodes and points provided are within the bounds of the map limits */ typedef short astar_mapcol[256]; class AStarContainer { public: AStarContainer(unsigned int _map_width, unsigned int node_limit); AStarContainer(const AStarContainer&); // copy constructor not yet implemented ~AStarContainer(); //assumes that the node is not already in the collection void add(AStarNode* node); //assumes that there is at least 1 node in the collection AStarNode* get_shortest_f(); //assumes that the node exists in the collection void remove(AStarNode* node); bool exists(Point pos); //assumes that the node exists in the collection AStarNode* get(int x, int y); bool isEmpty(); void updateParent(Point pos, Point parent_pos, float score); private: unsigned int size; /* This is an array of AStarNode pointers. This is the main data for this collection. * The size of the array is based on the node limit. * * The nodes in this array are ordered based on their f value and the node with the lowest f value is always at position 0. * The ordering is not linear, so after positon 0, we cannot assume that position 1 has the second shortest f value. * * The ordering is based on a binary heap structure. * Essentially, each node can have up to 2 child nodes and each child node must have a lower f value than its parent. * This rule must be maintained whenever nodes are added or removed or their f value changes * * The tree is represented by a 1 dimentional array where position 0 has children at position 1 and 2 * Node 1 would have children at position 3 and 4 and node 2 would have children at position 5 and 6 and so on * * A more detailed explanation of the structure can be found at the below web address. * Please note that there is additional code found in this class which is not mentioned in the article. This is to provide an index based on map position. * Also note that the code within the article is based on arrays with starting position 1, whereas we use 0 based arrays. * http://www.policyalmanac.org/games/binaryHeaps.htm */ AStarNode** nodes; /* This is an array of astar_mapcol (short[256]) which acts as an index for the main node array. * Its essentially a 2d array: short[map_width][256], * so elements can be accessed using cartesian coordinates e.g. map_pos[x][y] * To access an AStarNode based on map position use: nodes[map_pos[x][y]] * * The map height is always set to 256 even if the actual map is smaller. * This helps with initialisation and potentially allows the compiler to optimise array access. * * The data in this array is initialised as -1, which indicates hat there is no corresponding node for that position * This must be maintained when nodes are added, removed and re-ordered in the node array */ astar_mapcol* map_pos; }; /* This class is used to store the closed list of a* nodes * The nodes within this class have no ordering but stil have a map position index */ class AStarCloseContainer { public: AStarCloseContainer(unsigned int _map_width, unsigned int node_limit); AStarCloseContainer(const AStarCloseContainer&); // copy constructor not yet implemented ~AStarCloseContainer(); int getSize(); void add(AStarNode* node); bool exists(Point pos); AStarNode* get(int x, int y); AStarNode* get_shortest_h(); private: unsigned int size; AStarNode** nodes; astar_mapcol* map_pos; }; #endif // ASTARCONTAINER_H flare-engine-0.19/src/AStarNode.cpp000066400000000000000000000060141224717101500171130ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger Copyright © 2011-2012 Nojan Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "AStarNode.h" AStarNode::AStarNode() : x(0) , y(0) , g(0) , h(0) , parent() { } AStarNode::AStarNode(const int a, const int b) : x(a) , y(b) , g(0) , h(0) , parent() { } AStarNode::AStarNode(const Point &p) : x(p.x) , y(p.y) , g(0) , h(0) , parent(Point()) { } AStarNode::AStarNode(const AStarNode& copy) : x(copy.x) , y(copy.y) , g(copy.g) , h(copy.h) , parent(copy.parent) { } int AStarNode::getX() const { return x; } int AStarNode::getY() const { return y; } float AStarNode::getH() const { return h; } Point AStarNode::getParent() const { return parent; } void AStarNode::setParent(const Point& p) { this->parent = p; } std::list AStarNode::getNeighbours(int limitX, int limitY) const { Point toAdd; std::list res; if (x>node_stride && y>node_stride) { toAdd.x = x-node_stride; toAdd.y = y-node_stride; res.push_back(toAdd); } if (x>node_stride && (limitY==0 || ynode_stride && (limitX==0 || xnode_stride) { toAdd.x = x-node_stride; toAdd.y = y; res.push_back(toAdd); } if (y>node_stride) { toAdd.x = x; toAdd.y = y-node_stride; res.push_back(toAdd); } if (limitX==0 || x #include "Utils.h" const int node_stride = 1; // minimal stride between nodes class AStarNode { protected: // position int x; int y; // exact cost from first Node float g; // cost to last node float h; // Parent is where this Node come from. Point parent; public: AStarNode(); AStarNode(const int a, const int b); AStarNode(const Point &p); AStarNode(const AStarNode& copy); int getX() const; int getY() const; float getH() const; Point getParent() const; void setParent(const Point& p); // return a list of coordinates of all neighbours std::list getNeighbours(int limitX=0, int limitY=0) const; float getActualCost() const; void setActualCost(const float G); void setEstimatedCost(const float H); float getFinalCost() const; bool operator<(const AStarNode& n) const; bool operator==(const AStarNode& n) const; bool operator==(const Point& p) const; bool operator!=(const Point& p) const; }; #endif // ASTARNODE_H flare-engine-0.19/src/Animation.cpp000066400000000000000000000156461224717101500172250ustar00rootroot00000000000000/* Copyright © 2011-2012 kitano Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class Animation * * The Animation class handles the logic of advancing frames based on the animation type * and returning a renderable frame. * * The intention with the class is to keep it as flexible as possible so that the animations * can be used not only for character animations but any animated in-game objects. */ #include "Animation.h" using namespace std; Animation::Animation(const std::string &_name, const std::string &_type, SDL_Surface *_sprite) : name(_name) , type( _type == "play_once" ? PLAY_ONCE : _type == "back_forth" ? BACK_FORTH : _type == "looped" ? LOOPED : NONE) , sprite(_sprite) , number_frames(0) , cur_frame(0) , cur_frame_index(0) , cur_frame_duration(0) , max_kinds(0) , additional_data(0) , times_played(0) , gfx() , render_offset() , duration() , active_frames() { if (type == NONE) fprintf(stderr, "Warning: animation type %s is unknown\n", _type.c_str()); } Animation::Animation(const Animation& a) : name(a.name) , type(a.type) , sprite(a.sprite) , number_frames(a.number_frames) , cur_frame(0) , cur_frame_index(a.cur_frame_index) , cur_frame_duration(a.cur_frame_duration) , max_kinds(a.max_kinds) , additional_data(a.additional_data) , times_played(0) , gfx(std::vector(a.gfx)) , render_offset(std::vector(a.render_offset)) , duration(std::vector(a.duration)) , active_frames(std::vector(a.active_frames)) { } void Animation::setupUncompressed(Point _render_size, Point _render_offset, int _position, int _frames, int _duration, unsigned short _maxkinds) { setup(_frames, _duration, _maxkinds); for (unsigned short i = 0 ; i < _frames; i++) { int base_index = max_kinds*i; for (unsigned short kind = 0 ; kind < max_kinds; kind++) { gfx[base_index + kind].x = _render_size.x * (_position + i); gfx[base_index + kind].y = _render_size.y * kind; gfx[base_index + kind].w = _render_size.x; gfx[base_index + kind].h = _render_size.y; render_offset[base_index + kind].x = _render_offset.x; render_offset[base_index + kind].y = _render_offset.y; } } } void Animation::setup(unsigned short _frames, unsigned short _duration, unsigned short _maxkinds) { if (type == PLAY_ONCE) { number_frames = _frames * _duration; additional_data = 0; } else if (type == LOOPED) { number_frames = _frames * _duration; additional_data = 0; } else if (type == BACK_FORTH) { number_frames = 2 * _frames * _duration; additional_data = 1; } cur_frame = 0; cur_frame_index = 0; cur_frame_duration = 0; max_kinds = _maxkinds; times_played = 0; active_frames.push_back(number_frames/2); gfx.resize(max_kinds*_frames); render_offset.resize(max_kinds*_frames); duration.resize(max_kinds*_frames); for (unsigned short i = 0; i < duration.size(); i++) duration[i] = _duration; } void Animation::addFrame( unsigned short index, unsigned short kind, SDL_Rect sdl_rect, Point _render_offset) { if (index > gfx.size()/max_kinds) { fprintf(stderr, "WARNING: Animation(%s) adding rect(%d, %d, %d, %d) to frame index(%u) out of bounds. must be in [0, %d]\n", name.c_str(), sdl_rect.x, sdl_rect.y, sdl_rect.w, sdl_rect.h, index, (int)gfx.size()/max_kinds); return; } if (kind > max_kinds-1) { fprintf(stderr, "WARNING: Animation(%s) adding rect(%d, %d, %d, %d) to frame(%u) kind(%u) out of bounds. must be in [0, %d]\n", name.c_str(), sdl_rect.x, sdl_rect.y, sdl_rect.w, sdl_rect.h, index, kind, max_kinds-1); return; } gfx[max_kinds*index+kind] = sdl_rect; render_offset[max_kinds*index+kind] = _render_offset; } void Animation::advanceFrame() { if (!this) return; cur_frame_duration++; // Some entity state changes are triggered when the current frame is the last frame. // Even if those state changes are not handled properly, do not permit current frame to exceed last frame. if (cur_frame < number_frames-1) cur_frame++; if (cur_frame_duration >= duration[cur_frame_index]) { cur_frame_duration = 0; unsigned short last_base_index = (gfx.size()/max_kinds)-1; switch(type) { case PLAY_ONCE: if (cur_frame_index < last_base_index) cur_frame_index++; else times_played = 1; break; case LOOPED: if (cur_frame_index < last_base_index) { cur_frame_index++; } else { cur_frame_index = 0; cur_frame = 0; times_played++; } break; case BACK_FORTH: if (additional_data == 1) { if (cur_frame_index < last_base_index) cur_frame_index++; else additional_data = -1; } else if (additional_data == -1) { if (cur_frame_index > 0) cur_frame_index--; else { additional_data = 1; cur_frame = 0; times_played++; } } break; case NONE: break; } } } Renderable Animation::getCurrentFrame(int kind) { Renderable r; if (this) { const int index = (max_kinds*cur_frame_index) + kind; r.src.x = gfx[index].x; r.src.y = gfx[index].y; r.src.w = gfx[index].w; r.src.h = gfx[index].h; r.offset.x = render_offset[index].x; r.offset.y = render_offset[index].y; r.sprite = sprite; } return r; } void Animation::reset() { cur_frame = 0; cur_frame_duration = 0; cur_frame_index = 0; times_played = 0; additional_data = 1; } void Animation::syncTo(const Animation *other) { cur_frame = other->cur_frame; cur_frame_duration = other->cur_frame_duration; cur_frame_index = other->cur_frame_index; times_played = other->times_played; additional_data = other->additional_data; } void Animation::setActiveFrames(const std::vector &_active_frames) { if (_active_frames.size() == 1 && _active_frames[0] == -1) { for (short i = 0; i < number_frames; ++i) active_frames.push_back(i); } else { active_frames = std::vector(_active_frames); } } bool Animation::isFirstFrame() { return cur_frame == 0; } bool Animation::isLastFrame() { return cur_frame == number_frames - 1; } bool Animation::isSecondLastFrame() { return cur_frame == number_frames - 2; } bool Animation::isActiveFrame() { return (std::find(active_frames.begin(), active_frames.end(), cur_frame) != active_frames.end()); } int Animation::getTimesPlayed() { return times_played; } std::string Animation::getName() { return name; } bool Animation::isCompleted() { return (type == PLAY_ONCE && times_played > 0); } flare-engine-0.19/src/Animation.h000066400000000000000000000112061224717101500166560ustar00rootroot00000000000000/* Copyright © 2011-2012 kitano Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class Animation * * The Animation class handles the logic of advancing frames based on the animation type * and returning a renderable frame. * * The intention with the class is to keep it as flexible as possible so that the animations * can be used not only for character animations but any animated in-game objects. */ #pragma once #ifndef ANIMATION_H #define ANIMATION_H #include "CommonIncludes.h" #include "Utils.h" enum animation_type { NONE = 0, PLAY_ONCE = 1, // just iterates over the images one time. it holds the final image when finished. LOOPED = 2, // going over the images again and again. BACK_FORTH = 3 // iterate from index=0 to maxframe and back again. keeps holding the first image afterwards. }; class Animation { protected: const std::string name; const animation_type type; SDL_Surface *sprite; unsigned short number_frames; // how many ticks this animation lasts. unsigned short cur_frame; // counts up until reaching number_frames. unsigned short cur_frame_index; // which frame in this animation is currently being displayed? range: 0..gfx.size()-1 unsigned short cur_frame_duration; // how many ticks is the current image being displayed yet? range: 0..duration[cur_frame]-1 unsigned short max_kinds; short additional_data; // additional state depending on type: // if type == BACK_FORTH then it is 1 for advancing, and -1 for going back, 0 at the end // if type == LOOPED, then it is the number of loops to be played. // if type == PLAY_ONCE or NONE, this has no meaning. short times_played; // how often this animation was played (loop counter for type LOOPED) // Frame data, all vectors must have the same length: // These are indexed as 8*cur_frame_index + direction. std::vector gfx; // position on the spritesheet to be used. std::vector render_offset; // "virtual point on the floor" std::vector duration; // duration of each individual image std::vector active_frames; // which of the visible diffferent frames are active? // This should contain indexes of the gfx vector. // Assume it is sorted, one index occurs at max once. public: Animation(const std::string &_name, const std::string &_type, SDL_Surface *_sprite); // returns a copy of this: Animation(const Animation&); // Traditional way to create an animation. // The frames are stored in a grid like fashion, so the individual frame // position can be calculated based on a few things. // The spritesheet has 8 rows, each containing the data of one direction. // Within a row starting at (_position) there will be (_frames) frames, // which all belong to this animation. // The render_offset is constant for all frames. The render_size is also // the grid size. void setupUncompressed(Point render_size, Point render_offset, int _position, int _frames, int _duration, unsigned short _maxkinds = 8); void setup(unsigned short _frames, unsigned short _duration, unsigned short _maxkinds = 8); // kind can be used for direction(enemies, hero) or randomness(powers) void addFrame(unsigned short index, unsigned short kind, SDL_Rect sdl_rect, Point _render_offset); // advance the animation one frame void advanceFrame(); // sets the frame counters to the same values as the given Animation. void syncTo(const Animation *other); bool isHoveredBy(const Point &); // return the Renderable of the current frame Renderable getCurrentFrame(int direction); bool isFirstFrame(); bool isLastFrame(); bool isSecondLastFrame(); bool isActiveFrame(); // in a looped animation returns how many times it's been played // in a play once animation returns 1 when the animation is finished int getTimesPlayed(); // resets to beginning of the animation void reset(); std::string getName(); // a vector of indexes of gfx passed into. // if { -1 } is passed, all frames are set to active. void setActiveFrames(const std::vector &_active_frames); bool isCompleted(); }; #endif flare-engine-0.19/src/AnimationManager.cpp000066400000000000000000000050311224717101500205030ustar00rootroot00000000000000/* Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "CommonIncludes.h" #include "SharedResources.h" #include using namespace std; AnimationSet *AnimationManager::getAnimationSet(const string& filename) { vector::iterator found = find(names.begin(), names.end(), filename); if (found != names.end()) { int index = distance(names.begin(), found); if (sets[index] == 0) { sets[index] = new AnimationSet(filename); } return sets[index]; } else { fprintf(stderr, "AnimationManager::getAnimationSet: %s not found\n", filename.c_str()); SDL_Quit(); exit(1); // return 0; } } AnimationManager::AnimationManager() { } AnimationManager::~AnimationManager() { cleanUp(); // NDEBUG is used by posix to disable assertions, so use the same MACRO. #ifndef NDEBUG if (!names.empty()) { fprintf(stderr, "AnimationManager still holding these animations:\n"); for (unsigned i = 0; i < names.size(); i++) fprintf(stderr, "%s %d\n", names[i].c_str(), counts[i]); } assert(names.size() == 0); #endif } void AnimationManager::increaseCount(const std::string &name) { vector::iterator found = find(names.begin(), names.end(), name); if (found != names.end()) { int index = distance(names.begin(), found); counts[index]++; } else { sets.push_back(0); names.push_back(name); counts.push_back(1); } } void AnimationManager::decreaseCount(const std::string &name) { vector::iterator found = find(names.begin(), names.end(), name); if (found != names.end()) { int index = distance(names.begin(), found); counts[index]--; } else { fprintf(stderr, "AnimationManager::decreaseCount: %s not found\n", name.c_str()); SDL_Quit(); exit(1); } } void AnimationManager::cleanUp() { int i = sets.size() - 1; while (i >= 0) { if (counts[i] <= 0) { delete sets[i]; counts.erase(counts.begin()+i); sets.erase(sets.begin()+i); names.erase(names.begin()+i); } --i; } imag->cleanUp(); } flare-engine-0.19/src/AnimationManager.h000066400000000000000000000023571224717101500201600ustar00rootroot00000000000000/* Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #pragma once #ifndef __ANIMATION_MANAGER__ #define __ANIMATION_MANAGER__ #include "AnimationSet.h" #include "CommonIncludes.h" class AnimationManager { private: std::vector sets; std::vector names; std::vector counts; public: AnimationManager(); ~AnimationManager(); /** * @param name: the filename of what to load starting below the animations folder. */ AnimationSet *getAnimationSet(const std::string &name); void decreaseCount(const std::string &name); void increaseCount(const std::string &name); void cleanUp(); }; #endif // __ANIMATION_MANAGER__ flare-engine-0.19/src/AnimationSet.cpp000066400000000000000000000132721224717101500176720ustar00rootroot00000000000000/* Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "Animation.h" #include "AnimationSet.h" #include "AnimationManager.h" #include "ImageManager.h" #include "FileParser.h" #include "SharedResources.h" #include "Settings.h" #include "UtilsParsing.h" #include using namespace std; Animation *AnimationSet::getAnimation(const std::string &_name) { if (!loaded) load(); for (size_t i = 0; i < animations.size(); i++) if (animations[i]->getName() == _name) return new Animation(*animations[i]); return new Animation(*defaultAnimation); } Animation *AnimationSet::getAnimation() { if (!loaded) load(); return new Animation(*defaultAnimation); } AnimationSet::AnimationSet(const std::string &animationname) : name(animationname) , loaded(false) , animations() , sprite(NULL) { defaultAnimation = new Animation("default", "play_once", NULL); defaultAnimation->setupUncompressed(Point(), Point(), 0, 1, 0); } void AnimationSet::load() { assert(!loaded); loaded = true; FileParser parser; if (!parser.open(name, true, true, "Error loading animation definition: " + name)) return; string _name = ""; int position = 0; int frames = 0; int duration = 0; Point render_size; Point render_offset; string type = ""; string starting_animation = ""; bool first_section=true; bool compressed_loading=false; // is reset every section to false, set by frame keyword Animation *newanim = NULL; vector active_frames; // Parse the file and on each new section create an animation object from the data parsed previously parser.next(); do { // create the animation if finished parsing a section if (parser.new_section) { if (!first_section && !compressed_loading) { Animation *a = new Animation(_name, type, sprite); a->setupUncompressed(render_size, render_offset, position, frames, duration); if (!active_frames.empty()) a->setActiveFrames(active_frames); active_frames.clear(); animations.push_back(a); } first_section = false; compressed_loading = false; } if (parser.key == "image") { if (sprite) { printf("multiple images specified in %s, dragons be here!\n", name.c_str()); SDL_Quit(); exit(128); } imagefile = parser.val; imag->increaseCount(imagefile); sprite = imag->getSurface(imagefile); } else if (parser.key == "position") { position = toInt(parser.val); } else if (parser.key == "frames") { frames = toInt(parser.val); } else if (parser.key == "duration") { duration = toInt(parser.val); // TEMP: if an animation is too fast, display one frame per fps anyway if (duration < 1) duration=1; } else if (parser.key == "type") type = parser.val; else if (parser.key == "render_size") { render_size.x = toInt(parser.nextValue()); render_size.y = toInt(parser.nextValue()); } else if (parser.key == "render_offset") { render_offset.x = toInt(parser.nextValue()); render_offset.y = toInt(parser.nextValue()); } else if (parser.key == "active_frame") { active_frames.clear(); string nv = parser.nextValue(); if (nv == "all") { active_frames.push_back(-1); } else { while (nv != "") { active_frames.push_back(toInt(nv)); nv = parser.nextValue(); } sort(active_frames.begin(), active_frames.end()); active_frames.erase(unique(active_frames.begin(), active_frames.end()), active_frames.end()); } } else if (parser.key == "frame") { if (compressed_loading == false) { // first frame statement in section newanim = new Animation(_name, type, sprite); newanim->setup(frames, duration); if (!active_frames.empty()) newanim->setActiveFrames(active_frames); active_frames.clear(); animations.push_back(newanim); compressed_loading = true; } // frame = index, direction, x, y, w, h, offsetx, offsety SDL_Rect r; Point offset; const int index = toInt(parser.nextValue()); const int direction = toInt(parser.nextValue()); r.x = toInt(parser.nextValue()); r.y = toInt(parser.nextValue()); r.w = toInt(parser.nextValue()); r.h = toInt(parser.nextValue()); offset.x = toInt(parser.nextValue()); offset.y = toInt(parser.nextValue()); newanim->addFrame(index, direction, r, offset); } else { fprintf(stderr, "animations definitions (%s): Key %s not supported!\n", parser.getFileName().c_str(), parser.key.c_str()); } if (_name == "") { // This is the first animation starting_animation = parser.section; } _name = parser.section; } while (parser.next()); if (!compressed_loading) { // add final animation Animation *a = new Animation(_name, type, sprite); a->setupUncompressed(render_size, render_offset, position, frames, duration); if (!active_frames.empty()) a->setActiveFrames(active_frames); active_frames.clear(); animations.push_back(a); } if (starting_animation != "") { Animation *a = getAnimation(starting_animation); delete defaultAnimation; defaultAnimation = a; } } AnimationSet::~AnimationSet() { if (imagefile != "") imag->decreaseCount(imagefile); for (unsigned i = 0; i < animations.size(); ++i) delete animations[i]; delete defaultAnimation; } flare-engine-0.19/src/AnimationSet.h000066400000000000000000000037631224717101500173430ustar00rootroot00000000000000/* Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #pragma once #ifndef __ANIMATION_SET__ #define __ANIMATION_SET__ #include "CommonIncludes.h" class Animation; /** * The animation set contains all animations of one entity, hence it * they are all using the same spritesheet. * * The animation set is responsible for the spritesheet to be freed. */ class AnimationSet { private: const std::string name; //i.e. animations/goblin_runner.txt, matches the animations filename. std::string imagefile; Animation *defaultAnimation; // has always a non-null animation, in case of successfull load it contains the first animation in the animation file. bool loaded; void load(); public: std::vector animations; SDL_Surface *sprite; AnimationSet(const std::string &animationname); AnimationSet(const AnimationSet &a); // copy constructor not implemented. ~AnimationSet(); /** * callee is responsible to free the returned animation. * Returns the animation specified by \a name. If that animation is not found * a default animation is returned. */ Animation *getAnimation(const std::string &name); /** * callee is responsible to free the returned animation. * returns the default animation. This is the animation, which is first defined * in the animation definition file. */ Animation *getAnimation(); const std::string &getName() { return name; } }; #endif // __ANIMATION_SET__ flare-engine-0.19/src/Avatar.cpp000066400000000000000000000630701224717101500165160ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class Avatar * * Contains logic and rendering routines for the player avatar. */ #include "Animation.h" #include "AnimationManager.h" #include "AnimationSet.h" #include "CommonIncludes.h" #include "EnemyManager.h" #include "FileParser.h" #include "Hazard.h" #include "MapRenderer.h" #include "SDL_gfxBlitFunc.h" #include "SharedResources.h" #include "Utils.h" #include "UtilsMath.h" #include "UtilsParsing.h" #include "SharedGameResources.h" using namespace std; Avatar::Avatar() : Entity() , lockAttack(false) , path() , path_frames_elapsed(0) , prev_target() , collided(false) , path_found(false) , hero_stats(NULL) , charmed_stats(NULL) , act_target() , attacking (false) , drag_walking(false) , respawn(false) , close_menus(false) , allow_movement(true) { init(); // default hero animation data stats.cooldown = 4; // load the hero's animations from hero definition file anim->increaseCount("animations/hero.txt"); animationSet = anim->getAnimationSet("animations/hero.txt"); activeAnimation = animationSet->getAnimation(); loadLayerDefinitions(); } void Avatar::init() { // name, base, look are set by GameStateNew so don't reset it here // other init sprites = 0; stats.cur_state = AVATAR_STANCE; stats.pos.x = mapr->spawn.x; stats.pos.y = mapr->spawn.y; stats.direction = mapr->spawn_dir; current_power = 0; newLevelNotification = false; lockAttack = false; stats.hero = true; stats.humanoid = true; stats.level = 1; stats.xp = 0; stats.physical_character = 1; stats.mental_character = 1; stats.defense_character = 1; stats.offense_character = 1; stats.physical_additional = 0; stats.mental_additional = 0; stats.offense_additional = 0; stats.defense_additional = 0; stats.speed = 0.2f; stats.recalc(); log_msg = ""; respawn = false; stats.cooldown_ticks = 0; haz = NULL; body = -1; transform_triggered = false; setPowers = false; revertPowers = false; last_transform = ""; untransform_power = getUntransformPower(); hero_cooldown = vector(powers->powers.size(), 0); for (int i=0; i<4; i++) { sound_steps[i] = 0; } sound_melee = 0; sound_mental = 0; sound_hit = 0; sound_die = 0; sound_block = 0; level_up = 0; } /** * Load avatar sprite layer definitions into vector. */ void Avatar::loadLayerDefinitions() { layer_def = vector >(8, vector()); layer_reference_order = vector(); FileParser infile; // @CLASS Avatar|Description of engine/hero_options.txt if (infile.open("engine/hero_options.txt", true, false)) { while(infile.next()) { infile.val = infile.val + ','; if (infile.key == "layer") { // @ATTR layer|direction (integer), string, ...]|Defines the hero avatar sprite layer unsigned dir = eatFirstInt(infile.val,','); if (dir>7) { fprintf(stderr, "direction must be in range [0,7]\n"); SDL_Quit(); exit(1); } string layer = eatFirstString(infile.val,','); while (layer != "") { // check if already in layer_reference: unsigned ref_pos; for (ref_pos = 0; ref_pos < layer_reference_order.size(); ++ref_pos) if (layer == layer_reference_order[ref_pos]) break; if (ref_pos == layer_reference_order.size()) layer_reference_order.push_back(layer); layer_def[dir].push_back(ref_pos); layer = eatFirstString(infile.val,','); } } } infile.close(); } // There are the positions of the items relative to layer_reference_order // so if layer_reference_order=main,body,head,off // and we got a layer=3,off,body,head,main // then the layer_def[3] looks like (3,1,2,0) } void Avatar::loadGraphics(std::vector _img_gfx) { for (unsigned int i=0; idecreaseCount(animsets[i]->getName()); delete anims[i]; } animsets.clear(); anims.clear(); for (unsigned int i=0; i<_img_gfx.size(); i++) { if (_img_gfx[i].gfx != "") { string name = "animations/avatar/"+stats.gfx_base+"/"+_img_gfx[i].gfx+".txt"; anim->increaseCount(name); animsets.push_back(anim->getAnimationSet(name)); anims.push_back(animsets.back()->getAnimation(activeAnimation->getName())); anims.back()->syncTo(activeAnimation); } else { animsets.push_back(NULL); anims.push_back(NULL); } } anim->cleanUp(); } void Avatar::loadSounds(const string& type_id) { // unload any sounds that are common between creatures and the hero snd->unload(sound_melee); snd->unload(sound_mental); snd->unload(sound_hit); snd->unload(sound_die); if (type_id != "none") { sound_melee = snd->load("soundfx/enemies/" + type_id + "_phys.ogg", "Avatar melee attack"); sound_mental = snd->load("soundfx/enemies/" + type_id + "_ment.ogg", "Avatar mental attack"); sound_hit = snd->load("soundfx/enemies/" + type_id + "_hit.ogg", "Avatar was hit"); sound_die = snd->load("soundfx/enemies/" + type_id + "_die.ogg", "Avatar death"); } else { sound_melee = snd->load("soundfx/melee_attack.ogg", "Avatar melee attack"); sound_mental = 0; // hero does not have this sound sound_hit = snd->load("soundfx/" + stats.gfx_base + "_hit.ogg", "Avatar was hit"); sound_die = snd->load("soundfx/" + stats.gfx_base + "_die.ogg", "Avatar death"); } sound_block = snd->load("soundfx/powers/block.ogg", "Avatar blocking"); level_up = snd->load("soundfx/level_up.ogg", "Avatar leveling up"); } /** * Walking/running steps sound depends on worn armor */ void Avatar::loadStepFX(const string& stepname) { string filename = stats.sfx_step; if (stepname != "") { filename = stepname; } // clear previous sounds for (int i=0; i<4; i++) { snd->unload(sound_steps[i]); } // A literal "NULL" means we don't want to load any new sounds // This is used when transforming, since creatures don't have step sound effects if (stepname == "NULL") return; // load new sounds sound_steps[0] = snd->load("soundfx/steps/step_" + filename + "1.ogg", "Avatar loading foot steps"); sound_steps[1] = snd->load("soundfx/steps/step_" + filename + "2.ogg", "Avatar loading foot steps"); sound_steps[2] = snd->load("soundfx/steps/step_" + filename + "3.ogg", "Avatar loading foot steps"); sound_steps[3] = snd->load("soundfx/steps/step_" + filename + "4.ogg", "Avatar loading foot steps"); } bool Avatar::pressing_move() { if (!allow_movement) { return false; } else if (MOUSE_MOVE) { return inpt->pressing[MAIN1]; } else { return (inpt->pressing[UP] && !inpt->lock[UP]) || (inpt->pressing[DOWN] && !inpt->lock[DOWN]) || (inpt->pressing[LEFT] && !inpt->lock[LEFT]) || (inpt->pressing[RIGHT] && !inpt->lock[RIGHT]); } } void Avatar::set_direction() { // handle direction changes if (MOUSE_MOVE) { FPoint target = screen_to_map(inpt->mouse.x, inpt->mouse.y, stats.pos.x, stats.pos.y); stats.direction = calcDirection(stats.pos, target); } else { if (inpt->pressing[UP] && !inpt->lock[UP] && inpt->pressing[LEFT] && !inpt->lock[LEFT]) stats.direction = 1; else if (inpt->pressing[UP] && !inpt->lock[UP] && inpt->pressing[RIGHT] && !inpt->lock[RIGHT]) stats.direction = 3; else if (inpt->pressing[DOWN] && !inpt->lock[DOWN] && inpt->pressing[RIGHT] && !inpt->lock[RIGHT]) stats.direction = 5; else if (inpt->pressing[DOWN] && !inpt->lock[DOWN] && inpt->pressing[LEFT] && !inpt->lock[LEFT]) stats.direction = 7; else if (inpt->pressing[LEFT] && !inpt->lock[LEFT]) stats.direction = 0; else if (inpt->pressing[UP] && !inpt->lock[UP]) stats.direction = 2; else if (inpt->pressing[RIGHT] && !inpt->lock[RIGHT]) stats.direction = 4; else if (inpt->pressing[DOWN] && !inpt->lock[DOWN]) stats.direction = 6; // Adjust for ORTHO tilesets if (TILESET_ORIENTATION == TILESET_ORTHOGONAL && ((inpt->pressing[UP] && !inpt->lock[UP]) || (inpt->pressing[DOWN] && !inpt->lock[UP]) || (inpt->pressing[LEFT] && !inpt->lock[LEFT]) || (inpt->pressing[RIGHT] && !inpt->lock[RIGHT]))) stats.direction = stats.direction == 7 ? 0 : stats.direction + 1; } } void Avatar::handlePower(int actionbar_power) { if (actionbar_power != 0 && stats.cooldown_ticks == 0) { const Power &power = powers->getPower(actionbar_power); FPoint target; if (MOUSE_AIM) { if (power.aim_assist) target = screen_to_map(inpt->mouse.x, inpt->mouse.y + AIM_ASSIST, stats.pos.x, stats.pos.y); else target = screen_to_map(inpt->mouse.x, inpt->mouse.y, stats.pos.x, stats.pos.y); } else { FPoint ftarget = calcVector(stats.pos, stats.direction, stats.melee_range); target.x = ftarget.x; target.y = ftarget.y; } // check requirements if (!stats.canUsePower(power, actionbar_power)) return; if (power.requires_los && !mapr->collider.line_of_sight(stats.pos.x, stats.pos.y, target.x, target.y)) return; if (power.requires_empty_target && !mapr->collider.is_empty(target.x, target.y)) return; if (hero_cooldown[actionbar_power] > 0) return; if (!powers->hasValidTarget(actionbar_power,&stats,target)) return; hero_cooldown[actionbar_power] = power.cooldown; //set the cooldown timer current_power = actionbar_power; act_target = target; // is this a power that requires changing direction? if (power.face) { stats.direction = calcDirection(stats.pos, target); } attack_anim = power.attack_anim; switch (power.new_state) { case POWSTATE_ATTACK: // handle attack powers stats.cur_state = AVATAR_ATTACK; break; case POWSTATE_BLOCK: // handle blocking stats.cur_state = AVATAR_BLOCK; stats.effects.triggered_block = true; break; case POWSTATE_INSTANT: // handle instant powers powers->activate(current_power, &stats, target); break; } } } /** * logic() * Handle a single frame. This includes: * - move the avatar based on buttons pressed * - calculate the next frame of animation * - calculate camera position based on avatar position * * @param actionbar_power The actionbar power activated. 0 means no power. * @param restrictPowerUse rather or not to allow power usage on mouse1 */ void Avatar::logic(int actionbar_power, bool restrictPowerUse) { // hazards are processed after Avatar and Enemy[] // so process and clear sound effects from previous frames // check sound effects if (AUDIO) { if (sfx_phys) snd->play(sound_melee, GLOBAL_VIRTUAL_CHANNEL, stats.pos, false); if (sfx_ment) snd->play(sound_mental, GLOBAL_VIRTUAL_CHANNEL, stats.pos, false); if (sfx_hit) snd->play(sound_hit, GLOBAL_VIRTUAL_CHANNEL, stats.pos, false); if (sfx_die) snd->play(sound_die, GLOBAL_VIRTUAL_CHANNEL, stats.pos, false); if (sfx_critdie) snd->play(sound_die, GLOBAL_VIRTUAL_CHANNEL, stats.pos, false); if(sfx_block) snd->play(sound_block, GLOBAL_VIRTUAL_CHANNEL, stats.pos, false); // clear sound flags sfx_hit = false; sfx_phys = false; sfx_ment = false; sfx_die = false; sfx_critdie = false; sfx_block = false; } // clear current space to allow correct movement mapr->collider.unblock(stats.pos.x, stats.pos.y); // turn on all passive powers if ((stats.hp > 0 || stats.effects.triggered_death) && !respawn && !transform_triggered) powers->activatePassives(&stats); if (transform_triggered) transform_triggered = false; int stepfx; stats.logic(); if (stats.effects.forced_move) { move(); // calc new cam position from player position // cam is focused at player position mapr->cam.x = stats.pos.x; mapr->cam.y = stats.pos.y; mapr->collider.block(stats.pos.x, stats.pos.y, false); return; } if (stats.effects.stun) { mapr->collider.block(stats.pos.x, stats.pos.y, false); return; } bool allowed_to_move; bool allowed_to_use_power; // check for revive if (stats.hp <= 0 && stats.effects.revive) { stats.hp = stats.get(STAT_HP_MAX); stats.alive = true; stats.corpse = false; stats.cur_state = AVATAR_STANCE; } // check level up if (stats.level < (int)stats.xp_table.size() && stats.xp >= stats.xp_table[stats.level]) { stats.level_up = true; stats.level++; stringstream ss; ss << msg->get("Congratulations, you have reached level %d!", stats.level); if (stats.level < stats.max_spendable_stat_points) { ss << " " << msg->get("You may increase one attribute through the Character Menu."); newLevelNotification = true; } log_msg = ss.str(); stats.recalc(); snd->play(level_up); // if the player managed to level up while dead (e.g. via a bleeding creature), restore to life if (stats.cur_state == AVATAR_DEAD) { stats.cur_state = AVATAR_STANCE; } } // check for bleeding spurt if (stats.effects.damage > 0 && stats.hp > 0) { comb->addMessage(stats.effects.damage, stats.pos, COMBAT_MESSAGE_TAKEDMG); } // check for bleeding to death if (stats.hp == 0 && !(stats.cur_state == AVATAR_DEAD)) { stats.effects.triggered_death = true; stats.cur_state = AVATAR_DEAD; } // assist mouse movement if (!inpt->pressing[MAIN1]) { drag_walking = false; attacking = false; } else { if(!inpt->lock[MAIN1]) { attacking = true; } } // handle animation activeAnimation->advanceFrame(); for (unsigned i=0; i < anims.size(); i++) if (anims[i] != NULL) anims[i]->advanceFrame(); // handle transformation if (stats.transform_type != "" && stats.transform_type != "untransform" && stats.transformed == false) transform(); if (stats.transform_type != "" && stats.transform_duration == 0) untransform(); switch(stats.cur_state) { case AVATAR_STANCE: setAnimation("stance"); // allowed to move or use powers? if (MOUSE_MOVE) { allowed_to_move = restrictPowerUse && (!inpt->lock[MAIN1] || drag_walking) && !lockAttack; allowed_to_use_power = !allowed_to_move; } else { allowed_to_move = true; allowed_to_use_power = true; } // handle transitions to RUN if (allowed_to_move) set_direction(); if (pressing_move() && allowed_to_move) { if (MOUSE_MOVE && inpt->pressing[MAIN1]) { inpt->lock[MAIN1] = true; drag_walking = true; } if (move()) { // no collision stats.cur_state = AVATAR_RUN; } else { collided = true; } } if (MOUSE_MOVE && !inpt->pressing[MAIN1]) { inpt->lock[MAIN1] = false; lockAttack = false; } // handle power usage if (allowed_to_use_power) handlePower(actionbar_power); break; case AVATAR_RUN: setAnimation("run"); stepfx = rand() % 4; if (activeAnimation->isFirstFrame() || activeAnimation->isActiveFrame()) snd->play(sound_steps[stepfx]); // allowed to move or use powers? if (MOUSE_MOVE) { allowed_to_use_power = !(restrictPowerUse && !inpt->lock[MAIN1]); } else { allowed_to_use_power = true; } // handle direction changes set_direction(); // handle transition to STANCE if (!pressing_move()) { stats.cur_state = AVATAR_STANCE; break; } else if (!move()) { // collide with wall collided = true; stats.cur_state = AVATAR_STANCE; break; } // handle power usage if (allowed_to_use_power) handlePower(actionbar_power); if (activeAnimation->getName() != "run") stats.cur_state = AVATAR_STANCE; break; case AVATAR_ATTACK: setAnimation(attack_anim); if (MOUSE_MOVE) lockAttack = true; if (activeAnimation->isFirstFrame() && attack_anim == "swing") snd->play(sound_melee); if (activeAnimation->isFirstFrame() && attack_anim == "cast") snd->play(sound_mental); // do power if (activeAnimation->isActiveFrame()) { powers->activate(current_power, &stats, act_target); } if (activeAnimation->getTimesPlayed() >= 1 || activeAnimation->getName() != attack_anim) { stats.cur_state = AVATAR_STANCE; stats.cooldown_ticks += stats.cooldown; } break; case AVATAR_BLOCK: setAnimation("block"); if (powers->powers[actionbar_power].new_state != POWSTATE_BLOCK || activeAnimation->getName() != "block") { stats.cur_state = AVATAR_STANCE; stats.effects.triggered_block = false; stats.effects.clearTriggerEffects(TRIGGER_BLOCK); } break; case AVATAR_HIT: setAnimation("hit"); if (activeAnimation->isFirstFrame()) { stats.effects.triggered_hit = true; } if (activeAnimation->getTimesPlayed() >= 1 || activeAnimation->getName() != "hit") { stats.cur_state = AVATAR_STANCE; } break; case AVATAR_DEAD: if (stats.effects.triggered_death) break; if (stats.transformed) { stats.transform_duration = 0; untransform(); } setAnimation("die"); if (!stats.corpse && activeAnimation->isFirstFrame() && activeAnimation->getTimesPlayed() < 1) { stats.effects.clearEffects(); // raise the death penalty flag. Another module will read this and reset. stats.death_penalty = true; // close menus in GameStatePlay close_menus = true; snd->play(sound_die); if (stats.permadeath) { log_msg = msg->get("You are defeated. Game over! Press Enter to exit to Title."); } else { log_msg = msg->get("You are defeated. Press Enter to continue."); } //once the player dies, kill off any remaining summons for (unsigned int i=0; i < enemies->enemies.size(); i++) { if(!enemies->enemies[i]->stats.corpse && enemies->enemies[i]->stats.hero_ally) enemies->enemies[i]->InstantDeath(); } } if (activeAnimation->getTimesPlayed() >= 1 || activeAnimation->getName() != "die") { stats.corpse = true; } // allow respawn with Accept if not permadeath if (inpt->pressing[ACCEPT]) { inpt->lock[ACCEPT] = true; mapr->teleportation = true; mapr->teleport_mapname = mapr->respawn_map; if (stats.permadeath) { // set these positions so it doesn't flash before jumping to Title mapr->teleport_destination.x = stats.pos.x; mapr->teleport_destination.y = stats.pos.y; } else { respawn = true; // set teleportation variables. GameEngine acts on these. mapr->teleport_destination.x = mapr->respawn_point.x; mapr->teleport_destination.y = mapr->respawn_point.y; } } break; default: break; } // calc new cam position from player position // cam is focused at player position mapr->cam.x = stats.pos.x; mapr->cam.y = stats.pos.y; // check for map events mapr->checkEvents(stats.pos); // decrement all cooldowns for (unsigned i = 0; i < hero_cooldown.size(); i++) { hero_cooldown[i]--; if (hero_cooldown[i] < 0) hero_cooldown[i] = 0; } // make the current square solid mapr->collider.block(stats.pos.x, stats.pos.y, false); } void Avatar::transform() { // calling a transform power locks the actionbar, so we unlock it here inpt->unlockActionBar(); transform_triggered = true; stats.transformed = true; setPowers = true; delete charmed_stats; charmed_stats = new StatBlock(); charmed_stats->load("enemies/" + stats.transform_type + ".txt"); // temporary save hero stats delete hero_stats; hero_stats = new StatBlock(); *hero_stats = stats; // replace some hero stats stats.speed = charmed_stats->speed; stats.flying = charmed_stats->flying; stats.humanoid = charmed_stats->humanoid; stats.animations = charmed_stats->animations; stats.powers_list = charmed_stats->powers_list; stats.powers_passive = charmed_stats->powers_passive; stats.effects.clearEffects(); anim->decreaseCount("animations/hero.txt"); anim->increaseCount(charmed_stats->animations); animationSet = anim->getAnimationSet(charmed_stats->animations); delete activeAnimation; activeAnimation = animationSet->getAnimation(); stats.cur_state = AVATAR_STANCE; // damage clampFloor(stats.starting[STAT_DMG_MELEE_MIN], charmed_stats->starting[STAT_DMG_MELEE_MIN]); clampFloor(stats.starting[STAT_DMG_MELEE_MAX], charmed_stats->starting[STAT_DMG_MELEE_MAX]); clampFloor(stats.starting[STAT_DMG_MENT_MIN], charmed_stats->starting[STAT_DMG_MENT_MIN]); clampFloor(stats.starting[STAT_DMG_MENT_MAX], charmed_stats->starting[STAT_DMG_MENT_MAX]); clampFloor(stats.starting[STAT_DMG_RANGED_MIN], charmed_stats->starting[STAT_DMG_RANGED_MIN]); clampFloor(stats.starting[STAT_DMG_RANGED_MAX], charmed_stats->starting[STAT_DMG_RANGED_MAX]); // dexterity clampFloor(stats.starting[STAT_ABS_MIN], charmed_stats->starting[STAT_ABS_MIN]); clampFloor(stats.starting[STAT_ABS_MAX], charmed_stats->starting[STAT_ABS_MAX]); clampFloor(stats.starting[STAT_AVOIDANCE], charmed_stats->starting[STAT_AVOIDANCE]); clampFloor(stats.starting[STAT_ACCURACY], charmed_stats->starting[STAT_ACCURACY]); clampFloor(stats.starting[STAT_CRIT], charmed_stats->starting[STAT_CRIT]); // resistances for (unsigned int i=0; ivulnerable[i]); loadSounds(charmed_stats->sfx_prefix); loadStepFX("NULL"); stats.applyEffects(); } void Avatar::untransform() { // calling a transform power locks the actionbar, so we unlock it here inpt->unlockActionBar(); // Only allow untransform when on a valid tile if (!mapr->collider.is_valid_position(stats.pos.x,stats.pos.y,MOVEMENT_NORMAL, true)) return; stats.transformed = false; transform_triggered = true; stats.transform_type = ""; revertPowers = true; stats.effects.clearEffects(); // revert some hero stats to last saved stats.speed = hero_stats->speed; stats.flying = hero_stats->flying; stats.humanoid = hero_stats->humanoid; stats.animations = hero_stats->animations; stats.effects = hero_stats->effects; stats.powers_list = hero_stats->powers_list; stats.powers_passive = hero_stats->powers_passive; anim->increaseCount("animations/hero.txt"); anim->decreaseCount(charmed_stats->animations); animationSet = anim->getAnimationSet("animations/hero.txt"); delete activeAnimation; activeAnimation = animationSet->getAnimation(); stats.cur_state = AVATAR_STANCE; // This is a bit of a hack. // In order to switch to the stance animation, we can't already be in a stance animation setAnimation("run"); stats.starting[STAT_DMG_MELEE_MIN] = hero_stats->starting[STAT_DMG_MELEE_MIN]; stats.starting[STAT_DMG_MELEE_MAX] = hero_stats->starting[STAT_DMG_MELEE_MAX]; stats.starting[STAT_DMG_MENT_MIN] = hero_stats->starting[STAT_DMG_MENT_MIN]; stats.starting[STAT_DMG_MENT_MAX] = hero_stats->starting[STAT_DMG_MENT_MAX]; stats.starting[STAT_DMG_RANGED_MIN] = hero_stats->starting[STAT_DMG_RANGED_MIN]; stats.starting[STAT_DMG_RANGED_MAX] = hero_stats->starting[STAT_DMG_RANGED_MAX]; stats.starting[STAT_ABS_MIN] = hero_stats->starting[STAT_ABS_MIN]; stats.starting[STAT_ABS_MAX] = hero_stats->starting[STAT_ABS_MAX]; stats.starting[STAT_AVOIDANCE] = hero_stats->starting[STAT_AVOIDANCE]; stats.starting[STAT_ACCURACY] = hero_stats->starting[STAT_ACCURACY]; stats.starting[STAT_CRIT] = hero_stats->starting[STAT_CRIT]; for (unsigned int i=0; ivulnerable[i]; } loadSounds(); loadStepFX(stats.sfx_step); delete charmed_stats; delete hero_stats; charmed_stats = NULL; hero_stats = NULL; stats.applyEffects(); } void Avatar::setAnimation(std::string name) { if (name == activeAnimation->getName()) return; Entity::setAnimation(name); for (unsigned i=0; i < animsets.size(); i++) { delete anims[i]; if (animsets[i]) anims[i] = animsets[i]->getAnimation(name); else anims[i] = 0; } } /** * Find untransform power index to use for manual untransfrom ability */ int Avatar::getUntransformPower() { for (unsigned id=0; idpowers.size(); id++) { if (powers->powers[id].spawn_type == "untransform" && powers->powers[id].requires_item == -1) return id; } return 0; } void Avatar::resetActiveAnimation() { activeAnimation->reset(); // shield stutter for (unsigned i=0; i < animsets.size(); i++) if (anims[i]) anims[i]->reset(); } void Avatar::addRenders(vector &r) { if (!stats.transformed) { for (unsigned i = 0; i < layer_def[stats.direction].size(); ++i) { unsigned index = layer_def[stats.direction][i]; if (anims[index]) { Renderable ren = anims[index]->getCurrentFrame(stats.direction); ren.map_pos = stats.pos; ren.prio = i+1; r.push_back(ren); } } } else { Renderable ren = activeAnimation->getCurrentFrame(stats.direction); ren.map_pos = stats.pos; r.push_back(ren); } // add effects for (unsigned i = 0; i < stats.effects.effect_list.size(); ++i) { if (stats.effects.effect_list[i].animation && !stats.effects.effect_list[i].animation->isCompleted()) { Renderable ren = stats.effects.effect_list[i].animation->getCurrentFrame(0); ren.map_pos = stats.pos; if (stats.effects.effect_list[i].render_above) ren.prio = layer_def[stats.direction].size()+1; else ren.prio = 0; r.push_back(ren); } } } Avatar::~Avatar() { if (stats.transformed && charmed_stats && charmed_stats->animations != "") { anim->decreaseCount(charmed_stats->animations); } else { anim->decreaseCount("animations/hero.txt"); } for (unsigned int i=0; idecreaseCount(animsets[i]->getName()); delete anims[i]; } anim->cleanUp(); delete charmed_stats; delete hero_stats; snd->unload(sound_melee); snd->unload(sound_mental); snd->unload(sound_hit); snd->unload(sound_die); snd->unload(sound_block); for (int i = 0; i < 4; i++) snd->unload(sound_steps[i]); snd->unload(level_up); delete haz; } flare-engine-0.19/src/Avatar.h000066400000000000000000000062151224717101500161610ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class Avatar * * Contains logic and rendering routines for the player avatar. */ #pragma once #ifndef AVATAR_H #define AVATAR_H #include "CommonIncludes.h" #include "Entity.h" #include "SharedResources.h" #include "SoundManager.h" #include "Utils.h" using namespace std; class Entity; class Hazard; class StatBlock; /** * Avatar State enum */ enum AvatarState { AVATAR_STANCE = 0, AVATAR_RUN = 1, AVATAR_BLOCK = 2, AVATAR_HIT = 3, AVATAR_DEAD = 4, AVATAR_ATTACK = 5, }; class Layer_gfx { public: std::string gfx; std::string type; Layer_gfx() : gfx("") , type("") {} }; class Avatar : public Entity { private: bool lockAttack; SoundManager::SoundID sound_melee; SoundManager::SoundID sound_mental; SoundManager::SoundID sound_hit; SoundManager::SoundID sound_die; SoundManager::SoundID sound_block; SoundManager::SoundID sound_steps[4]; SoundManager::SoundID level_up; void setAnimation(std::string name); std::vector animsets; // hold the animations for all equipped items in the right order of drawing. std::vector anims; // hold the animations for all equipped items in the right order of drawing. short body; bool transform_triggered; std::string last_transform; int getUntransformPower(); //variables for patfinding vector path; int path_frames_elapsed; FPoint prev_target; bool collided; bool path_found; void handlePower(int actionbar_power); public: Avatar(); ~Avatar(); void init(); void loadLayerDefinitions(); std::vector layer_reference_order; std::vector > layer_def; void loadGraphics(std::vector _img_gfx); void loadSounds(const std::string& type_id = "none"); void loadStepFX(const std::string& stepname); void logic(int actionbar_power, bool restrictPowerUse); bool pressing_move(); void set_direction(); std::string log_msg; std::string attack_anim; // transformation handling void transform(); void untransform(); bool setPowers; bool revertPowers; int untransform_power; StatBlock *hero_stats; StatBlock *charmed_stats; virtual void resetActiveAnimation(); virtual Renderable getRender() { return Renderable(); } void addRenders(std::vector &r); // vars Hazard *haz; int current_power; FPoint act_target; bool attacking; bool drag_walking; bool newLevelNotification; bool respawn; bool close_menus; bool allow_movement; std::vector hero_cooldown; }; #endif flare-engine-0.19/src/BehaviorAlly.cpp000066400000000000000000000125251224717101500176600ustar00rootroot00000000000000/* Copyright © 2013 Ryan Dansie This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "BehaviorAlly.h" #include "Enemy.h" #include "SharedGameResources.h" const float ALLY_FLEE_DISTANCE = 2; const float ALLY_FOLLOW_DISTANCE_WALK = 5.5; const float ALLY_FOLLOW_DISTANCE_STOP = 5; const float ALLY_TELEPORT_DISTANCE = 40; const unsigned short BLOCK_TICKS = 10; BehaviorAlly::BehaviorAlly(Enemy *_e) : BehaviorStandard(_e) { } BehaviorAlly::~BehaviorAlly() { } void BehaviorAlly::findTarget() { // stunned minions can't act if (e->stats.effects.stun) return; // check distance and line of sight between minion and hero if (pc->stats.alive) hero_dist = calcDist(e->stats.pos, pc->stats.pos); else hero_dist = 0; //if the minion gets too far, transport it to the player pos if(hero_dist > ALLY_TELEPORT_DISTANCE && !e->stats.in_combat) { mapr->collider.unblock(e->stats.pos.x, e->stats.pos.y); e->stats.pos.x = pc->stats.pos.x; e->stats.pos.y = pc->stats.pos.y; mapr->collider.block(e->stats.pos.x, e->stats.pos.y, true); hero_dist = 0; } bool enemies_in_combat = false; //enter combat because enemy is targeting the player or a summon for (unsigned int i=0; i < enemies->enemies.size(); i++) { if(enemies->enemies[i]->stats.in_combat && !enemies->enemies[i]->stats.hero_ally) { Enemy* enemy = enemies->enemies[i]; //now work out the distance to the enemy and compare it to the distance to the current targer (we want to target the closest enemy) if(enemies_in_combat) { float enemy_dist = calcDist(e->stats.pos, enemy->stats.pos); if (enemy_dist < target_dist) { pursue_pos.x = enemy->stats.pos.x; pursue_pos.y = enemy->stats.pos.y; target_dist = enemy_dist; } } else { //minion is not already chasig another enemy so chase this one pursue_pos.x = enemy->stats.pos.x; pursue_pos.y = enemy->stats.pos.y; target_dist = calcDist(e->stats.pos, enemy->stats.pos); } e->stats.in_combat = true; enemies_in_combat = true; } } //break combat if the player gets too far or all enemies die if(!enemies_in_combat) e->stats.in_combat = false; //the default target is the player if(!e->stats.in_combat) { pursue_pos.x = pc->stats.pos.x; pursue_pos.y = pc->stats.pos.y; target_dist = hero_dist; } // check line-of-sight if (target_dist < e->stats.threat_range && pc->stats.alive) los = mapr->collider.line_of_sight(e->stats.pos.x, e->stats.pos.y, pursue_pos.x, pursue_pos.y); else los = false; //if the player is blocked, all summons which the player is facing to move away for the specified frames //need to set the flag player_blocked so that other allies know to get out of the way as well //if hero is facing the summon if(ENABLE_ALLY_COLLISION_AI) { if(!enemies->player_blocked && hero_dist < ALLY_FLEE_DISTANCE && mapr->collider.is_facing(pc->stats.pos.x,pc->stats.pos.y,pc->stats.direction,e->stats.pos.x,e->stats.pos.y)) { enemies->player_blocked = true; enemies->player_blocked_ticks = BLOCK_TICKS; } if(enemies->player_blocked && !e->stats.in_combat && mapr->collider.is_facing(pc->stats.pos.x,pc->stats.pos.y,pc->stats.direction,e->stats.pos.x,e->stats.pos.y)) { fleeing = true; pursue_pos = pc->stats.pos; } } if(e->stats.effects.fear) fleeing = true; } void BehaviorAlly::checkMoveStateStance() { if(e->stats.in_combat && target_dist > e->stats.melee_range) e->newState(ENEMY_MOVE); if((!e->stats.in_combat && hero_dist > ALLY_FOLLOW_DISTANCE_WALK) || fleeing) { if (e->move()) { e->newState(ENEMY_MOVE); } else { collided = true; int prev_direction = e->stats.direction; // hit an obstacle, try the next best angle e->stats.direction = e->faceNextBest(pursue_pos.x, pursue_pos.y); if (e->move()) { e->newState(ENEMY_MOVE); } else e->stats.direction = prev_direction; } } } void BehaviorAlly::checkMoveStateMove() { //if close enough to hero, stop miving if((hero_dist < ALLY_FOLLOW_DISTANCE_STOP && !e->stats.in_combat && !fleeing) || (target_dist < e->stats.melee_range && e->stats.in_combat && !fleeing) || (move_to_safe_dist && target_dist >= e->stats.threat_range/2)) { e->newState(ENEMY_STANCE); move_to_safe_dist = false; } // try to continue moving else if (!e->move()) { collided = true; int prev_direction = e->stats.direction; // hit an obstacle. Try the next best angle e->stats.direction = e->faceNextBest(pursue_pos.x, pursue_pos.y); if (!e->move()) { //this prevents an ally trying to move perpendicular to a bridge if the player gets close to it in a certain position and gets blocked if(enemies->player_blocked && !e->stats.in_combat) { e->stats.direction = pc->stats.direction; if (!e->move()) { e->stats.direction = prev_direction; } } else { e->stats.direction = prev_direction; } } } } flare-engine-0.19/src/BehaviorAlly.h000066400000000000000000000020171224717101500173200ustar00rootroot00000000000000/* Copyright © 2013 Ryan Dansie This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #ifndef BEHAVIORALLY_H #define BEHAVIORALLY_H #include "BehaviorStandard.h" class BehaviorAlly : public BehaviorStandard { public: BehaviorAlly(Enemy *_e); virtual ~BehaviorAlly(); protected: private: virtual void findTarget(); virtual void checkMoveStateStance(); virtual void checkMoveStateMove(); }; #endif // BEHAVIORALLY_H flare-engine-0.19/src/BehaviorStandard.cpp000066400000000000000000000467261224717101500205310ustar00rootroot00000000000000/* Copyright © 2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "Animation.h" #include "BehaviorStandard.h" #include "CommonIncludes.h" #include "Enemy.h" #include "MapRenderer.h" #include "StatBlock.h" #include "UtilsMath.h" #include "SharedGameResources.h" BehaviorStandard::BehaviorStandard(Enemy *_e) : EnemyBehavior(_e) , path() , prev_target() , collided(false) , path_found(false) , chance_calc_path(0) { los = false; hero_dist = 0; target_dist = 0; pursue_pos.x = pursue_pos.y = -1; fleeing = false; move_to_safe_dist = false; } /** * One frame of logic for this behavior */ void BehaviorStandard::logic() { // skip all logic if the enemy is dead and no longer animating if (e->stats.corpse) { if (e->stats.corpse_ticks > 0) e->stats.corpse_ticks--; return; } doUpkeep(); findTarget(); checkPower(); checkMove(); updateState(); fleeing = false; } /** * Various upkeep on stats * TODO: some of these actions could be moved to StatBlock::logic() */ void BehaviorStandard::doUpkeep() { // activate all passive powers if (e->stats.hp > 0 || e->stats.effects.triggered_death) powers->activatePassives(&e->stats); e->stats.logic(); // heal rapidly while not in combat if (!e->stats.in_combat && !e->stats.hero_ally) { if (e->stats.alive && pc->stats.alive) { e->stats.hp++; if (e->stats.hp > e->stats.get(STAT_HP_MAX)) e->stats.hp = e->stats.get(STAT_HP_MAX); } } if (e->stats.effects.forced_move) { e->move(); } if (e->stats.waypoint_pause_ticks > 0) e->stats.waypoint_pause_ticks--; if (e->stats.wander_ticks > 0) e->stats.wander_ticks--; if (e->stats.wander_pause_ticks > 0) e->stats.wander_pause_ticks--; // check for revive if (e->stats.hp <= 0 && e->stats.effects.revive) { e->stats.hp = e->stats.get(STAT_HP_MAX); e->stats.alive = true; e->stats.corpse = false; e->stats.cur_state = ENEMY_STANCE; } // check for bleeding to death if (e->stats.hp <= 0 && !(e->stats.cur_state == ENEMY_DEAD || e->stats.cur_state == ENEMY_CRITDEAD)) { //work out who the kill is attributed to bool source_hero = false; bool source_ally = false; bool source_enemy = false; for (unsigned i=0; istats.effects.effect_list.size(); i++) { if (e->stats.effects.effect_list[i].type == "damage") { switch(e->stats.effects.effect_list[i].source_type) { case(SOURCE_TYPE_ALLY): source_ally = true; break; case(SOURCE_TYPE_ENEMY): source_enemy = true; break; case(SOURCE_TYPE_HERO): source_hero = true; break; } } } int bleed_source_type = source_hero ? SOURCE_TYPE_HERO : (source_ally ? SOURCE_TYPE_ALLY : (source_enemy ? SOURCE_TYPE_ENEMY : SOURCE_TYPE_NEUTRAL)); e->doRewards(bleed_source_type); e->stats.effects.triggered_death = true; e->stats.cur_state = ENEMY_DEAD; mapr->collider.unblock(e->stats.pos.x,e->stats.pos.y); } // TEMP: check for bleeding spurt if (e->stats.effects.damage > 0 && e->stats.hp > 0) { comb->addMessage(e->stats.effects.damage, e->stats.pos, COMBAT_MESSAGE_TAKEDMG); } // check for teleport powers if (e->stats.teleportation) { mapr->collider.unblock(e->stats.pos.x,e->stats.pos.y); e->stats.pos.x = e->stats.teleport_destination.x; e->stats.pos.y = e->stats.teleport_destination.y; mapr->collider.block(e->stats.pos.x,e->stats.pos.y, e->stats.hero_ally); e->stats.teleportation = false; } } /** * Locate the player and set various targeting info */ void BehaviorStandard::findTarget() { float stealth_threat_range = (e->stats.threat_range * (100 - e->stats.hero_stealth)) / 100; // stunned enemies can't act if (e->stats.effects.stun) return; // check distance and line of sight between enemy and hero if (pc->stats.alive) hero_dist = calcDist(e->stats.pos, pc->stats.pos); else hero_dist = 0; // check entering combat (because the player hit the enemy) if (e->stats.join_combat) { if (hero_dist <= (stealth_threat_range *2)) { e->stats.join_combat = false; } else { e->stats.in_combat = true; powers->activate(e->stats.power_index[BEACON], &e->stats, e->stats.pos); //emit beacon } } // check entering combat (because the player got too close) if (!e->stats.in_combat && los && hero_dist < stealth_threat_range && !e->stats.passive_attacker) { if (e->stats.in_combat) e->stats.join_combat = true; e->stats.in_combat = true; powers->activate(e->stats.power_index[BEACON], &e->stats, e->stats.pos); //emit beacon } // check exiting combat (player died or got too far away) if (e->stats.in_combat && hero_dist > (e->stats.threat_range *2) && !e->stats.join_combat) { e->stats.in_combat = false; } // check exiting combat (player or enemy died) if (!e->stats.alive || !pc->stats.alive) { e->stats.in_combat = false; } // if the creature is a wanderer, pick a random point within the wander area to travel to if (e->stats.wander && !e->stats.in_combat && e->stats.wander_area.w > 0 && e->stats.wander_area.h > 0) { if (e->stats.wander_ticks == 0) { pursue_pos.x = e->stats.wander_area.x + (rand() % (e->stats.wander_area.w)) + 0.5f; pursue_pos.y = e->stats.wander_area.y + (rand() % (e->stats.wander_area.h)) + 0.5f; e->stats.wander_ticks = (rand() % 150) + 150; } } else { // by default, the enemy pursues the hero directly pursue_pos.x = pc->stats.pos.x; pursue_pos.y = pc->stats.pos.y; target_dist = hero_dist; //if there are player allies closer than the hero, target an ally instead if(e->stats.in_combat) { for (unsigned int i=0; i < enemies->enemies.size(); i++) { if(!enemies->enemies[i]->stats.corpse && enemies->enemies[i]->stats.hero_ally) { //now work out the distance to the minion and compare it to the distance to the current targer (we want to target the closest ally) float ally_dist = calcDist(e->stats.pos, enemies->enemies[i]->stats.pos); if (ally_dist < target_dist) { pursue_pos.x = enemies->enemies[i]->stats.pos.x; pursue_pos.y = enemies->enemies[i]->stats.pos.y; target_dist = ally_dist; } } } } if (!(e->stats.in_combat || e->stats.waypoints.empty())) { FPoint waypoint = e->stats.waypoints.front(); pursue_pos.x = waypoint.x; pursue_pos.y = waypoint.y; } } // check line-of-sight if (target_dist < e->stats.threat_range && pc->stats.alive) los = mapr->collider.line_of_sight(e->stats.pos.x, e->stats.pos.y, pursue_pos.x, pursue_pos.y); else los = false; if(e->stats.effects.fear) fleeing = true; // If we have a successful chance_flee roll, try to move to a safe distance if (e->stats.cur_state == ENEMY_STANCE && !move_to_safe_dist && hero_dist < e->stats.threat_range/2 && hero_dist >= e->stats.melee_range && percentChance(e->stats.chance_flee)) move_to_safe_dist = true; if (move_to_safe_dist) fleeing = true; } /** * Begin using a power if idle, based on behavior % chances. * Activate a ready power, if the attack animation has followed through */ void BehaviorStandard::checkPower() { // stunned enemies can't act if (e->stats.effects.stun || fleeing) return; // currently all enemy power use happens during combat if (!e->stats.in_combat) return; // if the enemy is on global cooldown it cannot act if (e->stats.cooldown_ticks > 0) return; // Note there are two stages to activating a power. // First is the enemy choosing to use a power based on behavioral chance // Second is the power actually firing off once the related animation reaches the active frame. // (these are separate so that interruptions can take place) // Begin Power Animation: // standard enemies can begin a power-use animation if they're standing around or moving voluntarily. if (los && (e->stats.cur_state == ENEMY_STANCE || e->stats.cur_state == ENEMY_MOVE)) { // check half dead power use if (!e->stats.on_half_dead_casted && e->stats.hp <= e->stats.get(STAT_HP_MAX)/2) { if (percentChance(e->stats.power_chance[ON_HALF_DEAD])) { e->newState(ENEMY_POWER); e->stats.activated_powerslot = ON_HALF_DEAD; return; } } // check ranged power use if (target_dist > e->stats.melee_range) { if (percentChance(e->stats.power_chance[RANGED_PHYS]) && e->stats.power_ticks[RANGED_PHYS] == 0) { bool can_use = true; if(powers->powers[e->stats.power_index[RANGED_PHYS]].type == POWTYPE_SPAWN) if(e->stats.summonLimitReached(e->stats.power_index[RANGED_PHYS])) can_use = false; if(can_use) { e->newState(ENEMY_POWER); e->stats.activated_powerslot = RANGED_PHYS; return; } } if (percentChance(e->stats.power_chance[RANGED_MENT]) && e->stats.power_ticks[RANGED_MENT] == 0) { bool can_use = true; if(powers->powers[e->stats.power_index[RANGED_MENT]].type == POWTYPE_SPAWN) if(e->stats.summonLimitReached(e->stats.power_index[RANGED_MENT])) can_use = false; if(can_use) { e->newState(ENEMY_POWER); e->stats.activated_powerslot = RANGED_MENT; return; } } } else { // check melee power use if (percentChance(e->stats.power_chance[MELEE_PHYS]) && e->stats.power_ticks[MELEE_PHYS] == 0) { bool can_use = true; if(powers->powers[e->stats.power_index[MELEE_PHYS]].type == POWTYPE_SPAWN) if(e->stats.summonLimitReached(e->stats.power_index[MELEE_PHYS])) can_use = false; if(can_use) { e->newState(ENEMY_POWER); e->stats.activated_powerslot = MELEE_PHYS; return; } } if (percentChance(e->stats.power_chance[MELEE_MENT]) && e->stats.power_ticks[MELEE_MENT] == 0) { bool can_use = true; if(powers->powers[e->stats.power_index[MELEE_MENT]].type == POWTYPE_SPAWN) if(e->stats.summonLimitReached(e->stats.power_index[MELEE_MENT])) can_use = false; if(can_use) { e->newState(ENEMY_POWER); e->stats.activated_powerslot = MELEE_MENT; return; } } } } // Activate Power: // enemy has started the animation to use a power. Activate the power on the Active animation frame if (e->stats.cur_state == ENEMY_POWER) { // if we're at the active frame of a power animation, // activate the power and set the local and global cooldowns if (e->activeAnimation->isActiveFrame() || e->instant_power) { e->instant_power = false; int power_slot = e->stats.activated_powerslot; int power_id = e->stats.power_index[e->stats.activated_powerslot]; powers->activate(power_id, &e->stats, pursue_pos); e->stats.power_ticks[power_slot] = e->stats.power_cooldown[power_slot]; e->stats.cooldown_ticks = e->stats.cooldown; if (e->stats.activated_powerslot == ON_HALF_DEAD) { e->stats.on_half_dead_casted = true; } } } } /** * Check state changes related to movement */ void BehaviorStandard::checkMove() { // dying enemies can't move if (e->stats.cur_state == ENEMY_DEAD || e->stats.cur_state == ENEMY_CRITDEAD) return; // stunned enemies can't act if (e->stats.effects.stun) return; // handle not being in combat and (not patrolling waypoints or waiting at waypoint) if (!e->stats.hero_ally && !e->stats.in_combat && (e->stats.waypoints.empty() || e->stats.waypoint_pause_ticks > 0) && (!e->stats.wander || e->stats.wander_pause_ticks > 0)) { if (e->stats.cur_state == ENEMY_MOVE) { e->newState(ENEMY_STANCE); } // currently enemies only move while in combat or patrolling return; } // clear current space to allow correct movement mapr->collider.unblock(e->stats.pos.x, e->stats.pos.y); // update direction if (e->stats.facing) { if (++e->stats.turn_ticks > e->stats.turn_delay) { // if blocked, face in pathfinder direction instead if (!mapr->collider.line_of_movement(e->stats.pos.x, e->stats.pos.y, pc->stats.pos.x, pc->stats.pos.y, e->stats.movement_type)) { // if a path is returned, target first waypoint bool recalculate_path = false; //if theres no path, it needs to be calculated if(path.empty()) recalculate_path = true; //if the target moved more than 1 tile away, recalculate if(calcDist(map_to_collision(prev_target), map_to_collision(pursue_pos)) > 1) recalculate_path = true; //if a collision ocurred then recalculate if(collided) recalculate_path = true; //add a 5% chance to recalculate on every frame. This prevents reclaulating lots of entities in the same frame chance_calc_path += 5; if(percentChance(chance_calc_path)) recalculate_path = true; //dont recalculate if we were blocked and no path was found last time //this makes sure that pathfinding calculation is not spammed when the target is unreachable and the entity is as close as its going to get if(!path_found && collided && !percentChance(chance_calc_path)) recalculate_path = false; else//reset the collision flag only if we dont want the cooldown in place collided = false; prev_target = pursue_pos; // target first waypoint if(recalculate_path) { chance_calc_path = -100; path.clear(); path_found = mapr->collider.compute_path(e->stats.pos, pursue_pos, path, e->stats.movement_type); } if(!path.empty()) { pursue_pos = path.back(); //if distance to node is lower than a tile size, the node is going to be passed and can be removed if(calcDist(e->stats.pos, pursue_pos) <= 64) path.pop_back(); } } else { path.clear(); } if(fleeing) e->stats.direction = calcDirection(pursue_pos, e->stats.pos); else e->stats.direction = calcDirection(e->stats.pos, pursue_pos); e->stats.turn_ticks = 0; } } // try to start moving if (e->stats.cur_state == ENEMY_STANCE) { checkMoveStateStance(); } // already moving else if (e->stats.cur_state == ENEMY_MOVE) { checkMoveStateMove(); } // if patrolling waypoints and has reached a waypoint, cycle to the next one if (!e->stats.waypoints.empty()) { FPoint waypoint = e->stats.waypoints.front(); FPoint pos = e->stats.pos; // if the patroller is close to the waypoint if (fabs(waypoint.x - pos.x) < 0.5 && fabs(waypoint.y - pos.y) < 0.5) { e->stats.waypoints.pop(); e->stats.waypoints.push(waypoint); e->stats.waypoint_pause_ticks = e->stats.waypoint_pause; } } // if a wandering enemy reaches its destination early, reset wander_ticks if (e->stats.wander) { FPoint pos = e->stats.pos; if (fabs(pursue_pos.x - pos.x) < 0.5 && fabs(pursue_pos.y - pos.y) < 0.5) { e->stats.wander_ticks = 0; } if (e->stats.wander_ticks == 0 && e->stats.wander_pause_ticks == 0) { e->stats.wander_pause_ticks = rand() % 60; } } // re-block current space to allow correct movement mapr->collider.block(e->stats.pos.x, e->stats.pos.y, e->stats.hero_ally); } void BehaviorStandard::checkMoveStateStance() { // If the enemy is capable of fleeing and is at a safe distance, have it hold its position instead of moving if (hero_dist >= e->stats.threat_range/2 && e->stats.chance_flee > 0 && e->stats.waypoints.empty()) return; if ((hero_dist > e->stats.melee_range && percentChance(e->stats.chance_pursue)) || fleeing) { if (e->move()) { e->newState(ENEMY_MOVE); } else { collided = true; int prev_direction = e->stats.direction; // hit an obstacle, try the next best angle e->stats.direction = e->faceNextBest(pursue_pos.x, pursue_pos.y); if (e->move()) { e->newState(ENEMY_MOVE); } else e->stats.direction = prev_direction; } } } void BehaviorStandard::checkMoveStateMove() { // close enough to the hero or is at a safe distance if ((target_dist < e->stats.melee_range && !fleeing) || (move_to_safe_dist && target_dist >= e->stats.threat_range/2)) { e->newState(ENEMY_STANCE); move_to_safe_dist = false; } // try to continue moving else if (!e->move()) { collided = true; int prev_direction = e->stats.direction; // hit an obstacle. Try the next best angle e->stats.direction = e->faceNextBest(pursue_pos.x, pursue_pos.y); if (!e->move()) { e->newState(ENEMY_STANCE); e->stats.direction = prev_direction; } } } /** * Perform miscellaneous state-based actions. * 1) Set animations and sound effects * 2) Return to the default state (Stance) when actions are complete */ void BehaviorStandard::updateState() { // stunned enemies can't act if (e->stats.effects.stun) return; int power_id; int power_state; // continue current animations e->activeAnimation->advanceFrame(); switch (e->stats.cur_state) { case ENEMY_STANCE: e->setAnimation("stance"); break; case ENEMY_MOVE: e->setAnimation("run"); break; case ENEMY_POWER: power_id = e->stats.power_index[e->stats.activated_powerslot]; power_state = powers->powers[power_id].new_state; // animation based on power type if (power_state == POWSTATE_INSTANT) e->instant_power = true; else if (power_state == POWSTATE_ATTACK) e->setAnimation(powers->powers[power_id].attack_anim); // sound effect based on power type if (e->activeAnimation->isFirstFrame()) { if (powers->powers[power_id].attack_anim == "swing" || powers->powers[power_id].attack_anim == "shoot") e->sfx_phys = true; else if (powers->powers[power_id].attack_anim == "cast") e->sfx_ment = true; } if (e->activeAnimation->isLastFrame() || (power_state == POWSTATE_ATTACK && e->activeAnimation->getName() != powers->powers[power_id].attack_anim)) e->newState(ENEMY_STANCE); break; case ENEMY_SPAWN: e->setAnimation("spawn"); //the second check is needed in case the entity does not have a spawn animation if (e->activeAnimation->isLastFrame() || e->activeAnimation->getName() != "spawn") { e->newState(ENEMY_STANCE); } break; case ENEMY_BLOCK: e->setAnimation("block"); break; case ENEMY_HIT: e->setAnimation("hit"); if (e->activeAnimation->isFirstFrame()) { e->stats.effects.triggered_hit = true; } if (e->activeAnimation->isLastFrame() || e->activeAnimation->getName() != "hit") e->newState(ENEMY_STANCE); break; case ENEMY_DEAD: if (e->stats.effects.triggered_death) break; e->setAnimation("die"); if (e->activeAnimation->isFirstFrame()) { e->sfx_die = true; e->stats.corpse_ticks = CORPSE_TIMEOUT; e->stats.effects.clearEffects(); } if (e->activeAnimation->isSecondLastFrame()) { if (percentChance(e->stats.power_chance[ON_DEATH])) powers->activate(e->stats.power_index[ON_DEATH], &e->stats, e->stats.pos); } if (e->activeAnimation->isLastFrame() || e->activeAnimation->getName() != "die") { e->stats.corpse = true; // puts renderable under object layer //allow free movement over the corpse mapr->collider.unblock(e->stats.pos.x, e->stats.pos.y); } break; case ENEMY_CRITDEAD: e->setAnimation("critdie"); if (e->activeAnimation->isFirstFrame()) { e->sfx_critdie = true; e->stats.corpse_ticks = CORPSE_TIMEOUT; e->stats.effects.clearEffects(); } if (e->activeAnimation->isSecondLastFrame()) { if (percentChance(e->stats.power_chance[ON_DEATH])) powers->activate(e->stats.power_index[ON_DEATH], &e->stats, e->stats.pos); } if (e->activeAnimation->isLastFrame() || e->activeAnimation->getName() != "critdie") e->stats.corpse = true; // puts renderable under object layer break; default: break; } } flare-engine-0.19/src/BehaviorStandard.h000066400000000000000000000027031224717101500201610ustar00rootroot00000000000000/* Copyright © 2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #pragma once #ifndef BEHAVIOR_STANDARD_H #define BEHAVIOR_STANDARD_H #include "EnemyBehavior.h" #include "Utils.h" using namespace std; class Enemy; class Point; class BehaviorStandard : public EnemyBehavior { private: // logic steps void doUpkeep(); virtual void findTarget(); void checkPower(); void checkMove(); virtual void checkMoveStateStance(); virtual void checkMoveStateMove(); void updateState(); protected: //variables for patfinding vector path; FPoint prev_target; bool collided; bool path_found; int chance_calc_path; float hero_dist; float target_dist; FPoint pursue_pos; // targeting vars bool los; //when fleeing, the enemy moves away from the pursue_pos bool fleeing; bool move_to_safe_dist; public: BehaviorStandard(Enemy *_e); void logic(); }; #endif flare-engine-0.19/src/CampaignManager.cpp000066400000000000000000000121551224717101500203100ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class CampaignManager * * Contains data for story mode */ #include "CampaignManager.h" #include "CommonIncludes.h" #include "MenuItemStorage.h" #include "Settings.h" #include "SharedGameResources.h" #include "SharedResources.h" #include "StatBlock.h" #include "UtilsParsing.h" using namespace std; CampaignManager::CampaignManager() : status() , log_msg("") , drop_stack() , carried_items(NULL) , currency(NULL) , hero(NULL) , quest_update(true) , bonus_xp(0.0) { } void CampaignManager::clearAll() { // clear campaign data status.clear(); } /** * Take the savefile campaign= and convert to status array */ void CampaignManager::setAll(std::string s) { string str = s + ','; string token; while (str != "") { token = eatFirstString(str, ','); if (token != "") this->setStatus(token); } quest_update = true; } /** * Convert status array to savefile campaign= (status csv) */ std::string CampaignManager::getAll() { stringstream ss; ss.str(""); for (unsigned int i=0; i < status.size(); i++) { ss << status[i]; if (i < status.size()-1) ss << ','; } return ss.str(); } bool CampaignManager::checkStatus(std::string s) { // avoid searching empty statuses if (s == "") return false; for (unsigned int i=0; i < status.size(); i++) { if (status[i] == s) return true; } return false; } void CampaignManager::setStatus(std::string s) { // avoid adding empty statuses if (s == "") return; // if it's already set, don't add it again if (checkStatus(s)) return; status.push_back(s); quest_update = true; hero->check_title = true; } void CampaignManager::unsetStatus(std::string s) { // avoid searching empty statuses if (s == "") return; vector::iterator it; // see http://stackoverflow.com/a/223405 for (it = status.end(); it != status.begin();) { --it; if ((*it) == s) { it = status.erase(it); quest_update = true; return; } hero->check_title = true; } } bool CampaignManager::checkCurrency(int quantity) { return carried_items->contain(CURRENCY_ID, quantity); } bool CampaignManager::checkItem(int item_id) { return carried_items->contain(item_id); } void CampaignManager::removeCurrency(int quantity) { for (int i=0; iremove(CURRENCY_ID); } addMsg(msg->get("%d %s removed.", quantity, CURRENCY)); items->playSound(CURRENCY_ID); } void CampaignManager::removeItem(int item_id) { carried_items->remove(item_id); addMsg(msg->get("%s removed.", items->items[item_id].name)); items->playSound(item_id); } void CampaignManager::rewardItem(ItemStack istack) { if (carried_items->full(istack.item)) { drop_stack.item = istack.item; drop_stack.quantity = istack.quantity; } else { carried_items->add(istack); if (istack.item != CURRENCY_ID) { if (istack.quantity <= 1) addMsg(msg->get("You receive %s.", items->items[istack.item].name)); if (istack.quantity > 1) addMsg(msg->get("You receive %s x%d.", istack.quantity, items->items[istack.item].name)); items->playSound(istack.item); } } } void CampaignManager::rewardCurrency(int amount) { ItemStack stack; stack.item = CURRENCY_ID; stack.quantity = amount; if (!carried_items->full(stack.item)) addMsg(msg->get("You receive %d %s.", amount, CURRENCY)); rewardItem(stack); items->playSound(CURRENCY_ID); } void CampaignManager::rewardXP(int amount, bool show_message) { bonus_xp += (amount * (100.0f + hero->get(STAT_XP_GAIN))) / 100.0f; hero->xp += (int)bonus_xp; bonus_xp -= (int)bonus_xp; hero->refresh_stats = true; if (show_message) addMsg(msg->get("You receive %d XP.", amount)); } void CampaignManager::restoreHPMP(std::string s) { if (s == "hp") { hero->hp = hero->get(STAT_HP_MAX); addMsg(msg->get("HP restored.")); } else if (s == "mp") { hero->mp = hero->get(STAT_MP_MAX); addMsg(msg->get("MP restored.")); } else if (s == "hpmp") { hero->hp = hero->get(STAT_HP_MAX); hero->mp = hero->get(STAT_MP_MAX); addMsg(msg->get("HP and MP restored.")); } else if (s == "status") { hero->effects.clearNegativeEffects(); addMsg(msg->get("Negative effects removed.")); } else if (s == "all") { hero->hp = hero->get(STAT_HP_MAX); hero->mp = hero->get(STAT_MP_MAX); hero->effects.clearNegativeEffects(); addMsg(msg->get("HP and MP restored, negative effects removed")); } } void CampaignManager::addMsg(const string& new_msg) { if (log_msg != "") log_msg += " "; log_msg += new_msg; } CampaignManager::~CampaignManager() { } flare-engine-0.19/src/CampaignManager.h000066400000000000000000000034031224717101500177510ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class CampaignManager * * Contains data for story mode */ #pragma once #ifndef CAMPAIGN_MANAGER_H #define CAMPAIGN_MANAGER_H #include "CommonIncludes.h" #include "ItemManager.h" class StatBlock; class MenuItemStorage; class CampaignManager { public: CampaignManager(); ~CampaignManager(); void clearAll(); void setAll(std::string s); std::string getAll(); bool checkStatus(std::string s); void setStatus(std::string s); void unsetStatus(std::string s); bool checkCurrency(int quantity); bool checkItem(int item_id); void removeCurrency(int quantity); void removeItem(int item_id); void rewardItem(ItemStack istack); void rewardCurrency(int amount); void rewardXP(int amount, bool show_message); void restoreHPMP(std::string s); void addMsg(const std::string& msg); std::vector status; std::string log_msg; ItemStack drop_stack; // pointers to various info that can be changed MenuItemStorage *carried_items; int *currency; StatBlock *hero; bool quest_update; float bonus_xp; // Fractional XP points not yet awarded (e.g. killing 1 XP enemies with a +25% ring) }; #endif flare-engine-0.19/src/CombatText.cpp000066400000000000000000000061521224717101500173500ustar00rootroot00000000000000/* Copyright © 2011-2012 Thane Brimhall Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class CombatText * * The CombatText class displays floating damage numbers and miss messages * above the targets. * */ #include "CombatText.h" #include "CommonIncludes.h" #include "FileParser.h" #include "Settings.h" #include "SharedResources.h" #include "UtilsParsing.h" CombatText::CombatText() { msg_color[COMBAT_MESSAGE_GIVEDMG] = font->getColor("combat_givedmg"); msg_color[COMBAT_MESSAGE_TAKEDMG] = font->getColor("combat_takedmg"); msg_color[COMBAT_MESSAGE_CRIT] = font->getColor("combat_crit"); msg_color[COMBAT_MESSAGE_BUFF] = font->getColor("combat_buff"); msg_color[COMBAT_MESSAGE_MISS] = font->getColor("combat_miss"); duration = 30; speed = 1; // Load config settings FileParser infile; // @CLASS CombatText|Description of engine/combat_text.txt if(infile.open("engine/combat_text.txt")) { while(infile.next()) { if(infile.key == "duration") { // @ATTR duration|integer|Duration of the combat text. duration = toInt(infile.val); } else if(infile.key == "speed") { // @ATTR speed|integer|Motion speed of the combat text. speed = toInt(infile.val); } } infile.close(); } } void CombatText::setCam(FPoint location) { cam = location; } void CombatText::addMessage(std::string message, FPoint location, int displaytype) { if (COMBAT_TEXT) { Combat_Text_Item *c = new Combat_Text_Item(); WidgetLabel *label = new WidgetLabel(); c->pos.x = location.x; c->pos.y = location.y; c->floating_offset = COMBAT_TEXT_STARTING_OFFSET; c->label = label; c->text = message; c->lifespan = duration; c->displaytype = displaytype; combat_text.push_back(*c); delete c; } } void CombatText::addMessage(int num, FPoint location, int displaytype) { if (COMBAT_TEXT) { std::stringstream ss; ss << num; addMessage(ss.str(), location, displaytype); } } void CombatText::render() { for(std::vector::iterator it = combat_text.begin(); it != combat_text.end(); ++it) { it->lifespan--; it->floating_offset += speed; Point scr_pos; scr_pos = map_to_screen(it->pos.x, it->pos.y, cam.x, cam.y); scr_pos.y -= it->floating_offset; it->label->set(scr_pos.x, scr_pos.y, JUSTIFY_CENTER, VALIGN_BOTTOM, it->text, msg_color[it->displaytype]); if (it->lifespan > 0) it->label->render(); } // delete expired messages while (combat_text.size() && combat_text.begin()->lifespan <= 0) { delete combat_text.begin()->label; combat_text.erase(combat_text.begin()); } } flare-engine-0.19/src/CombatText.h000066400000000000000000000034521224717101500170150ustar00rootroot00000000000000/* Copyright © 2011-2012 Thane Brimhall This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class CombatText * * The CombatText class displays floating damage numbers and miss messages * above the targets. * */ #pragma once #ifndef COMBAT_TEXT_H #define COMBAT_TEXT_H #include "CommonIncludes.h" #include "Utils.h" #include "WidgetLabel.h" #define COMBAT_MESSAGE_GIVEDMG 0 #define COMBAT_MESSAGE_TAKEDMG 1 #define COMBAT_MESSAGE_CRIT 2 #define COMBAT_MESSAGE_MISS 3 #define COMBAT_MESSAGE_BUFF 4 // TODO: move this to the combat text engine file // Map positions are between the feet of the entity at the floor level. // This offset starts combat text "above" the common enemy height. #define COMBAT_TEXT_STARTING_OFFSET 48; class WidgetLabel; class Combat_Text_Item { public: WidgetLabel *label; int lifespan; FPoint pos; int floating_offset; std::string text; int displaytype; }; class CombatText { public: CombatText(); void render(); void addMessage(std::string message, FPoint location, int displaytype); void addMessage(int num, FPoint location, int displaytype); void setCam(FPoint location); private: FPoint cam; std::vector combat_text; SDL_Color msg_color[5]; int duration; int speed; }; #endif flare-engine-0.19/src/CommonIncludes.h000066400000000000000000000016501224717101500176600ustar00rootroot00000000000000/* Copyright © 2013 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #pragma once #ifndef SHARED_INCLUDES #define SHARED_INCLUDES #include #include #include #include #include #include #include #include #include #include #include #endif flare-engine-0.19/src/EffectManager.cpp000066400000000000000000000251201224717101500177610ustar00rootroot00000000000000/* Copyright © 2012 Justin Jacobs This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class EffectManager */ #include "Animation.h" #include "AnimationSet.h" #include "EffectManager.h" #include "Settings.h" EffectManager::EffectManager() : bonus() , bonus_resist(std::vector(ELEMENTS.size(), 0)) , triggered_others(false) , triggered_block(false) , triggered_hit(false) , triggered_halfdeath(false) , triggered_joincombat(false) , triggered_death(false) { clearStatus(); } EffectManager::~EffectManager() { for (unsigned i=0; iincreaseCount(effect_list[i].animation_name); effect_list[i].animation = loadAnimation(effect_list[i].animation_name); } } damage = emSource.damage; hpot = emSource.hpot; mpot = emSource.mpot; speed = emSource.speed; immunity = emSource.immunity; stun = emSource.stun; forced_speed = emSource.forced_speed; forced_move = emSource.forced_move; revive = emSource.revive; convert = emSource.convert; death_sentence = emSource.death_sentence; fear = emSource.fear; bonus_offense = emSource.bonus_offense; bonus_defense = emSource.bonus_defense; bonus_physical = emSource.bonus_physical; bonus_mental = emSource.bonus_mental; for (unsigned i=0; i= 0) { if (effect_list[i].type == "damage" && effect_list[i].ticks % MAX_FRAMES_PER_SEC == 1) damage += effect_list[i].magnitude; else if (effect_list[i].type == "hpot" && effect_list[i].ticks % MAX_FRAMES_PER_SEC == 1) hpot += effect_list[i].magnitude; else if (effect_list[i].type == "mpot" && effect_list[i].ticks % MAX_FRAMES_PER_SEC == 1) mpot += effect_list[i].magnitude; else if (effect_list[i].type == "speed") speed = (effect_list[i].magnitude * speed) / 100; else if (effect_list[i].type == "immunity") immunity = true; else if (effect_list[i].type == "stun") stun = true; else if (effect_list[i].type == "forced_move") { forced_move = true; forced_speed = (float)effect_list[i].magnitude; } else if (effect_list[i].type == "revive") revive = true; else if (effect_list[i].type == "convert") convert = true; else if (effect_list[i].type == "fear") fear = true; else if (effect_list[i].type == "offense") bonus_offense += effect_list[i].magnitude; else if (effect_list[i].type == "defense") bonus_defense += effect_list[i].magnitude; else if (effect_list[i].type == "physical") bonus_physical += effect_list[i].magnitude; else if (effect_list[i].type == "mental") bonus_mental += effect_list[i].magnitude; else { bool found_key = false; for (unsigned j=0; j 0) { if (effect_list[i].ticks > 0) effect_list[i].ticks--; if (effect_list[i].ticks == 0) { //death sentence is only applied at the end of the timer if (effect_list[i].type == "death_sentence") death_sentence = true; removeEffect(i); i--; continue; } } } // expire shield effects if (effect_list[i].magnitude_max > 0 && effect_list[i].magnitude == 0) { if (effect_list[i].type == "shield") { removeEffect(i); i--; continue; } } // expire effects based on animations if ((effect_list[i].animation && effect_list[i].animation->isLastFrame()) || !effect_list[i].animation) { if (effect_list[i].type == "heal") { removeEffect(i); i--; continue; } } // animate if (effect_list[i].animation) { if (!effect_list[i].animation->isCompleted()) effect_list[i].animation->advanceFrame(); } } } void EffectManager::addEffect(std::string id, int icon, int duration, int magnitude, std::string type, std::string animation, bool additive, bool item, int trigger, bool render_above, int passive_id, int source_type) { // if we're already immune, don't add negative effects if (immunity) { if (type == "damage") return; else if (type == "speed" && magnitude < 100) return; else if (type == "stun") return; } // only allow one forced_move effect // TODO remove this limitation if (forced_move) { if (type == "forced_move") return; } for (unsigned i=0; i -1 && effect_list[i].trigger == trigger) return; // trigger effects can only be cast once per trigger if (effect_list[i].duration <= duration && effect_list[i].type != "death_sentence") { effect_list[i].ticks = effect_list[i].duration = duration; if (effect_list[i].animation) effect_list[i].animation->reset(); } if (effect_list[i].duration > duration && effect_list[i].type == "death_sentence") { effect_list[i].ticks = effect_list[i].duration = duration; if (effect_list[i].animation) effect_list[i].animation->reset(); } if (additive) break; // this effect will stack if (effect_list[i].magnitude_max <= magnitude) { effect_list[i].magnitude = effect_list[i].magnitude_max = magnitude; if (effect_list[i].animation) effect_list[i].animation->reset(); } return; // we already have this effect } // if we're adding an immunity effect, remove all negative effects if (type == "immunity") { clearNegativeEffects(); } } Effect e; e.id = id; e.icon = icon; e.ticks = e.duration = duration; e.magnitude = e.magnitude_max = magnitude; e.type = type; e.item = item; e.trigger = trigger; e.render_above = render_above; e.passive_id = passive_id; e.source_type = source_type; if (animation != "") { anim->increaseCount(animation); e.animation = loadAnimation(animation); e.animation_name = animation; } effect_list.push_back(e); } void EffectManager::removeEffect(int id) { removeAnimation(id); effect_list.erase(effect_list.begin()+id); } void EffectManager::removeAnimation(int id) { if (effect_list[id].animation && effect_list[id].animation_name != "") { anim->decreaseCount(effect_list[id].animation_name); delete effect_list[id].animation; effect_list[id].animation = NULL; effect_list[id].animation_name = ""; } } void EffectManager::removeEffectType(std::string type) { for (unsigned i=effect_list.size(); i > 0; i--) { if (effect_list[i-1].type == type) removeEffect(i-1); } } void EffectManager::removeEffectPassive(int id) { for (unsigned i=effect_list.size(); i > 0; i--) { if (effect_list[i-1].passive_id == id) removeEffect(i-1); } } void EffectManager::clearEffects() { for (unsigned i=effect_list.size(); i > 0; i--) { removeEffect(i-1); } // clear triggers triggered_others = triggered_block = triggered_hit = triggered_halfdeath = triggered_joincombat = triggered_death = false; } void EffectManager::clearNegativeEffects() { for (unsigned i=effect_list.size(); i > 0; i--) { if (effect_list[i-1].type == "damage") removeEffect(i-1); else if (effect_list[i-1].type == "speed" && effect_list[i-1].magnitude_max < 100) removeEffect(i-1); else if (effect_list[i-1].type == "stun") removeEffect(i-1); } } void EffectManager::clearItemEffects() { for (unsigned i=effect_list.size(); i > 0; i--) { if (effect_list[i-1].item) removeEffect(i-1); } } void EffectManager::clearTriggerEffects(int trigger) { for (unsigned i=effect_list.size(); i > 0; i--) { if (effect_list[i-1].trigger > -1 && effect_list[i-1].trigger == trigger) removeEffect(i-1); } } int EffectManager::damageShields(int dmg) { int over_dmg = dmg; for (unsigned i=0; i 0 && effect_list[i].type == "shield") { effect_list[i].magnitude -= dmg; if (effect_list[i].magnitude < 0) { if (abs(effect_list[i].magnitude) < over_dmg) over_dmg = abs(effect_list[i].magnitude); effect_list[i].magnitude = 0; } else { over_dmg = 0; } } } return over_dmg; } Animation* EffectManager::loadAnimation(std::string &s) { if (s != "") { AnimationSet *animationSet = anim->getAnimationSet(s); return animationSet->getAnimation(); } return NULL; } flare-engine-0.19/src/EffectManager.h000066400000000000000000000053211224717101500174270ustar00rootroot00000000000000/* Copyright © 2012 Justin Jacobs This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class EffectManager * * Holds the collection of hazards (active attacks, spells, etc) and handles group operations */ #pragma once #ifndef EFFECT_MANAGER_H #define EFFECT_MANAGER_H #include "CommonIncludes.h" #include "Hazard.h" #include "SharedResources.h" #include "Stats.h" #include "Utils.h" class Animation; class Hazard; class Effect{ public: std::string id; int icon; int ticks; int duration; std::string type; int magnitude; int magnitude_max; std::string animation_name; Animation* animation; bool item; int trigger; bool render_above; int passive_id; int source_type; Effect() : id("") , icon(-1) , ticks(0) , duration(-1) , type("") , magnitude(0) , magnitude_max(0) , animation_name("") , animation(NULL) , item(false) , trigger(-1) , render_above(false) , passive_id(0) , source_type(SOURCE_TYPE_HERO) {} ~Effect() { } }; class EffectManager { private: Animation* loadAnimation(std::string &s); void removeEffect(int id); void removeAnimation(int id); public: EffectManager(); ~EffectManager(); EffectManager& operator= (const EffectManager &emSource); void clearStatus(); void logic(); void addEffect(std::string id, int icon, int duration, int magnitude, std::string type, std::string animation, bool additive, bool item, int trigger, bool render_above, int passive_id, int source_type); void removeEffectType(std::string type); void removeEffectPassive(int id); void clearEffects(); void clearNegativeEffects(); void clearItemEffects(); void clearTriggerEffects(int trigger); int damageShields(int dmg); std::vector effect_list; int damage; int hpot; int mpot; float speed; bool immunity; bool stun; float forced_speed; bool forced_move; bool revive; bool convert; bool death_sentence; bool fear; int bonus_offense; int bonus_defense; int bonus_physical; int bonus_mental; int bonus[STAT_COUNT]; std::vector bonus_resist; bool triggered_others; bool triggered_block; bool triggered_hit; bool triggered_halfdeath; bool triggered_joincombat; bool triggered_death; }; #endif flare-engine-0.19/src/Enemy.cpp000066400000000000000000000112741224717101500163540ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /* * class Enemy */ #include "Animation.h" #include "Avatar.h" #include "BehaviorAlly.h" #include "BehaviorStandard.h" #include "CampaignManager.h" #include "CommonIncludes.h" #include "EnemyBehavior.h" #include "Enemy.h" #include "Hazard.h" #include "SharedGameResources.h" #include "SharedResources.h" #include "UtilsMath.h" #include using namespace std; Enemy::Enemy() : Entity() { stats.cur_state = ENEMY_STANCE; stats.turn_ticks = MAX_FRAMES_PER_SEC; //stats.patrol_ticks = 0; //no longer needed due to A* stats.cooldown = 0; stats.in_combat = false; stats.join_combat = false; haz = NULL; reward_xp = false; instant_power = false; kill_source_type = SOURCE_TYPE_NEUTRAL; eb = NULL; } Enemy::Enemy(const Enemy& e) : Entity(e) , type(e.type) , haz(NULL) // do not copy hazard. This constructor is used during mapload, so no hazard should be active. , eb(new BehaviorStandard(this)) , reward_xp(e.reward_xp) , instant_power(e.instant_power) , kill_source_type(e.kill_source_type) { assert(e.haz == NULL); } /** * The current direction leads to a wall. Try the next best direction, if one is available. */ int Enemy::faceNextBest(float mapx, float mapy) { float dx = fabs(mapx - stats.pos.x); float dy = fabs(mapy - stats.pos.y); switch (stats.direction) { case 0: if (dy > dx) return 7; else return 1; case 1: if (mapy > stats.pos.y) return 0; else return 2; case 2: if (dx > dy) return 1; else return 3; case 3: if (mapx < stats.pos.x) return 2; else return 4; case 4: if (dy > dx) return 3; else return 5; case 5: if (mapy < stats.pos.y) return 4; else return 6; case 6: if (dx > dy) return 5; else return 7; case 7: if (mapx > stats.pos.x) return 6; else return 0; } return 0; } void Enemy::newState(int state) { stats.cur_state = state; } /** * logic() * Handle a single frame. This includes: * - move the enemy based on AI % chances * - calculate the next frame of animation */ void Enemy::logic() { eb->logic(); //need to check whether the enemy was converted here //cant do it in behaviour because the behaviour object would be replaced by this if(stats.effects.convert != stats.converted) { delete eb; eb = stats.hero_ally ? new BehaviorStandard(this) : new BehaviorAlly(this); stats.converted = !stats.converted; stats.hero_ally = !stats.hero_ally; if (stats.convert_status != "") { camp->setStatus(stats.convert_status); } } return; } /** * Upon enemy death, handle rewards (currency, xp, loot) */ void Enemy::doRewards(int source_type) { if(stats.hero_ally && !stats.converted) return; reward_xp = true; kill_source_type = source_type; // some creatures create special loot if we're on a quest if (stats.quest_loot_requires_status != "") { // the loot manager will check quest_loot_id // if set (not zero), the loot manager will 100% generate that loot. if (!(camp->checkStatus(stats.quest_loot_requires_status) && !camp->checkStatus(stats.quest_loot_requires_not_status))) { stats.quest_loot_id = 0; } } // some creatures drop special loot the first time they are defeated // this must be done in conjunction with defeat status if (stats.first_defeat_loot > 0) { if (!camp->checkStatus(stats.defeat_status)) { stats.quest_loot_id = stats.first_defeat_loot; } } // defeating some creatures (e.g. bosses) affects the story if (stats.defeat_status != "") { camp->setStatus(stats.defeat_status); } loot->addEnemyLoot(this); } void Enemy::InstantDeath() { stats.effects.triggered_death = true; stats.cur_state = ENEMY_DEAD; stats.hp = 0; sfx_die = true; stats.corpse_ticks = CORPSE_TIMEOUT; stats.effects.clearEffects(); } /** * getRender() * Map objects need to be drawn in Z order, so we allow a parent object (GameEngine) * to collect all mobile sprites each frame. */ Renderable Enemy::getRender() { Renderable r = activeAnimation->getCurrentFrame(stats.direction); r.map_pos.x = stats.pos.x; r.map_pos.y = stats.pos.y; return r; } Enemy::~Enemy() { delete haz; delete eb; } flare-engine-0.19/src/Enemy.h000066400000000000000000000024531224717101500160200ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /* * class Enemy */ #pragma once #ifndef ENEMY_H #define ENEMY_H #include "CommonIncludes.h" #include "Entity.h" #include "Utils.h" #include class EnemyBehavior; class Hazard; class Enemy : public Entity { public: Enemy(); Enemy(const Enemy& e); ~Enemy(); bool lineOfSight(); void logic(); int faceNextBest(float mapx, float mapy); void newState(int state); virtual void doRewards(int source_type); void InstantDeath(); std::string type; virtual Renderable getRender(); Hazard *haz; EnemyBehavior *eb; // other flags bool reward_xp; bool instant_power; int kill_source_type; }; #endif flare-engine-0.19/src/EnemyBehavior.cpp000066400000000000000000000017271224717101500200360ustar00rootroot00000000000000/* Copyright © 2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class EnemyBehavior * * Interface for enemy behaviors. * The behavior object is a component of Enemy. * Make AI decisions (movement, actions) for enemies. */ #include "EnemyBehavior.h" EnemyBehavior::EnemyBehavior(Enemy *_e) { e = _e; } void EnemyBehavior::logic() { } EnemyBehavior::~EnemyBehavior() { } flare-engine-0.19/src/EnemyBehavior.h000066400000000000000000000020641224717101500174760ustar00rootroot00000000000000/* Copyright © 2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class EnemyBehavior * * Interface for enemy behaviors. * The behavior object is a component of Enemy. * Make AI decisions (movement, actions) for enemies. */ #pragma once #ifndef ENEMY_BEHAVIOR_H #define ENEMY_BEHAVIOR_H #include "EnemyManager.h" class Enemy; class EnemyBehavior { protected: Enemy *e; public: EnemyBehavior(Enemy *_e); virtual ~EnemyBehavior(); virtual void logic(); }; #endif flare-engine-0.19/src/EnemyGroupManager.cpp000066400000000000000000000072241224717101500206640ustar00rootroot00000000000000/* Copyright © 2011-2012 Thane Brimhall Manuel A. Fernandez Montecelo This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "EnemyGroupManager.h" #include "FileParser.h" #include "Settings.h" #include "SharedGameResources.h" #include "SharedResources.h" #include "UtilsFileSystem.h" #include "UtilsParsing.h" #include using namespace std; EnemyGroupManager::EnemyGroupManager() { parseEnemyFilesAndStore(); } EnemyGroupManager::~EnemyGroupManager() { } void EnemyGroupManager::parseEnemyFilesAndStore() { FileParser infile; // @CLASS enemies|Describing enemies files in enemies/ if (!infile.open("enemies", true, false)) return; Enemy_Level new_enemy; infile.new_section = true; bool first = true; while (infile.next()) { if (infile.new_section || first) { const string fname = infile.getFileName(); const int firstpos = fname.rfind("/") + 1; const int len = fname.length() - firstpos - 4; //removes the ".txt" from the filename new_enemy.type = fname.substr(firstpos, len); first = false; } if (infile.key == "level") { // @ATTR level|integer|Level of the enemy new_enemy.level = toInt(infile.val); } else if (infile.key == "rarity") { // @ATTR rarity|[common,uncommon,rare]|Enemy rarity new_enemy.rarity = infile.val; } else if (infile.key == "categories") { // @ATTR categories|string,...|Comma separated list of enemy categories string cat; while ( (cat = infile.nextValue()) != "") { _categories[cat].push_back(new_enemy); } } } infile.close(); } Enemy_Level EnemyGroupManager::getRandomEnemy(const std::string& category, int minlevel, int maxlevel) const { vector enemyCategory; std::map >::const_iterator it = _categories.find(category); if (it != _categories.end()) { enemyCategory = it->second; } else { fprintf(stderr, "Could not find enemy category %s, returning empty enemy\n", category.c_str()); return Enemy_Level(); } // load only the data that fit the criteria vector enemyCandidates; for (size_t i = 0; i < enemyCategory.size(); ++i) { Enemy_Level new_enemy = enemyCategory[i]; if ((new_enemy.level >= minlevel) && (new_enemy.level <= maxlevel)) { // add more than one time to increase chance of getting // this enemy as result, "rarity" property int add_times = 0; if (new_enemy.rarity == "common") { add_times = 6; } else if (new_enemy.rarity == "uncommon") { add_times = 3; } else if (new_enemy.rarity == "rare") { add_times = 1; } else { fprintf(stderr, "ERROR: 'rarity' property for enemy '%s' not valid (common|uncommon|rare): %s\n", new_enemy.type.c_str(), new_enemy.rarity.c_str()); } // do add, the given number of times for (int j = 0; j < add_times; ++j) { enemyCandidates.push_back(new_enemy); } } } if (enemyCandidates.empty()) { fprintf(stderr, "Could not find a suitable enemy category for (%s, %d, %d)\n", category.c_str(), minlevel, maxlevel); return Enemy_Level(); } else { return enemyCandidates[rand() % enemyCandidates.size()]; } } flare-engine-0.19/src/EnemyGroupManager.h000066400000000000000000000033341224717101500203270ustar00rootroot00000000000000/* Copyright © 2011-2012 Thane Brimhall Manuel A. Fernandez Montecelo This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #pragma once #ifndef ENEMYGROUPMANAGER_H #define ENEMYGROUPMANAGER_H #include "CommonIncludes.h" class Enemy_Level { public: std::string type; int level; std::string rarity; Enemy_Level() : level(0), rarity("common") {} }; /** * class EnemyGroupManager * * Loads Enemies into category lists and manages spawning randomized groups of * enemies. */ class EnemyGroupManager { public: EnemyGroupManager(); ~EnemyGroupManager(); /** To get a random enemy with the given characteristics * * @param category Enemy of the desired category * @param minlevel Enemy of the desired level (minimum) * @param maxlevel Enemy of the desired level (maximum) * * @return A random enemy level description if a suitable was found. * Null if none was found. */ Enemy_Level getRandomEnemy(const std::string& category, int minlevel, int maxlevel) const; private: /** Container to store enemy data */ std::map > _categories; void parseEnemyFilesAndStore(); }; #endif flare-engine-0.19/src/EnemyManager.cpp000066400000000000000000000373751224717101500176610ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "EnemyManager.h" #include "AnimationManager.h" #include "AnimationSet.h" #include "Animation.h" #include "SharedResources.h" #include "EnemyBehavior.h" #include "BehaviorStandard.h" #include "BehaviorAlly.h" #include "SharedGameResources.h" #include using namespace std; EnemyManager::EnemyManager() : enemies() , hero_stealth(0) , player_blocked(false) , player_blocked_ticks(0) { handleNewMap(); } void EnemyManager::loadSounds(const string& type_id) { // first check to make sure the sfx isn't already loaded if (find(sfx_prefixes.begin(), sfx_prefixes.end(), type_id) != sfx_prefixes.end()) return; if (type_id != "none") { sound_phys.push_back(snd->load("soundfx/enemies/" + type_id + "_phys.ogg", "EnemyManager physical attack sound")); sound_ment.push_back(snd->load("soundfx/enemies/" + type_id + "_ment.ogg", "EnemyManager mental attack sound")); sound_hit.push_back(snd->load("soundfx/enemies/" + type_id + "_hit.ogg", "EnemyManager physical hit sound")); sound_die.push_back(snd->load("soundfx/enemies/" + type_id + "_die.ogg", "EnemyManager die sound")); sound_critdie.push_back(snd->load("soundfx/enemies/" + type_id + "_critdie.ogg", "EnemyManager critdeath sound")); } else { sound_phys.push_back(0); sound_ment.push_back(0); sound_hit.push_back(0); sound_die.push_back(0); sound_critdie.push_back(0); } sfx_prefixes.push_back(type_id); } void EnemyManager::loadAnimations(Enemy *e) { anim->increaseCount(e->stats.animations); e->animationSet = anim->getAnimationSet(e->stats.animations); e->activeAnimation = e->animationSet->getAnimation(); } Enemy *EnemyManager::getEnemyPrototype(const string& type_id) { for (size_t i = 0; i < prototypes.size(); i++) if (prototypes[i].type == type_id) { anim->increaseCount(prototypes[i].stats.animations); return new Enemy(prototypes[i]); } Enemy e = Enemy(); e.eb = new BehaviorStandard(&e); e.stats.load("enemies/" + type_id + ".txt"); e.type = type_id; if (e.stats.animations == "") fprintf(stderr, "Warning: no animation file specified for entity: %s\n", type_id.c_str()); if (e.stats.sfx_prefix == "") fprintf(stderr, "Warning: no sfx_prefix specified for entity: %s\n", type_id.c_str()); loadAnimations(&e); loadSounds(e.stats.sfx_prefix); prototypes.push_back(e); return new Enemy(prototypes.back()); } /** * When loading a new map, we eliminate existing enemies and load the new ones. * The map will have loaded Entity blocks into an array; retrieve the Enemies and init them */ void EnemyManager::handleNewMap () { Map_Enemy me; std::queue allies; // delete existing enemies for (unsigned int i=0; i < enemies.size(); i++) { anim->decreaseCount(enemies[i]->animationSet->getName()); if(enemies[i]->stats.hero_ally && !enemies[i]->stats.corpse && enemies[i]->stats.cur_state != ENEMY_DEAD && enemies[i]->stats.cur_state != ENEMY_CRITDEAD) allies.push(enemies[i]); else { delete enemies[i]; } } enemies.clear(); for (unsigned j=0; junload(sound_phys[j]); snd->unload(sound_ment[j]); snd->unload(sound_hit[j]); snd->unload(sound_die[j]); snd->unload(sound_critdie[j]); } sfx_prefixes.clear(); sound_phys.clear(); sound_ment.clear(); sound_hit.clear(); sound_die.clear(); sound_critdie.clear(); prototypes.clear(); // load new enemies while (!mapr->enemies.empty()) { me = mapr->enemies.front(); mapr->enemies.pop(); if (me.type.empty()) { fprintf(stderr, "Enemy(%f, %f) doesn't have type attribute set, skipping\n", me.pos.x, me.pos.y); continue; } bool status_reqs_met = true; //if the status requirements arent met, dont load the enemy for(unsigned int i = 0; i < me.requires_status.size(); i++){ if (!camp->checkStatus(me.requires_status[i])) status_reqs_met = false; } for(unsigned int i = 0; i < me.requires_not_status.size(); i++){ if (camp->checkStatus(me.requires_not_status[i])) status_reqs_met = false; } if(!status_reqs_met) continue; Enemy *e = getEnemyPrototype(me.type); e->stats.waypoints = me.waypoints; e->stats.pos.x = me.pos.x; e->stats.pos.y = me.pos.y; e->stats.direction = me.direction; e->stats.wander = me.wander; e->stats.wander_area = me.wander_area; enemies.push_back(e); mapr->collider.block(me.pos.x, me.pos.y, false); } while (!allies.empty()) { Enemy *e = allies.front(); allies.pop(); //dont need the result of this. its only called to handle animation and sound getEnemyPrototype(e->type); e->stats.pos.x = pc->stats.pos.x; e->stats.pos.y = pc->stats.pos.y; e->stats.direction = pc->stats.direction; enemies.push_back(e); mapr->collider.block(e->stats.pos.x, e->stats.pos.y, true); } anim->cleanUp(); } /** * Powers can cause new enemies to spawn * Check PowerManager for any new queued enemies */ void EnemyManager::handleSpawn() { Map_Enemy espawn; while (!powers->enemies.empty()) { espawn = powers->enemies.front(); powers->enemies.pop(); Enemy *e = new Enemy(); // factory if(espawn.hero_ally) e->eb = new BehaviorAlly(e); else e->eb = new BehaviorStandard(e); e->stats.hero_ally = espawn.hero_ally; e->stats.summoned = true; e->stats.summoned_power_index = espawn.summon_power_index; if(espawn.summoner != NULL) { e->stats.summoner = espawn.summoner; espawn.summoner->summons.push_back(&(e->stats)); } e->type = espawn.type; e->stats.direction = espawn.direction; e->stats.load("enemies/" + espawn.type + ".txt"); if (e->stats.animations != "") { // load the animation file if specified anim->increaseCount(e->stats.animations); e->animationSet = anim->getAnimationSet(e->stats.animations); if (e->animationSet) e->activeAnimation = e->animationSet->getAnimation(); else fprintf(stderr, "Warning: animations file could not be loaded for %s\n", espawn.type.c_str()); } else { fprintf(stderr, "Warning: no animation file specified for entity: %s\n", espawn.type.c_str()); } loadSounds(e->stats.sfx_prefix); //Set level if(e->stats.summoned_power_index != 0) { if(powers->powers[e->stats.summoned_power_index].spawn_level_mode == SPAWN_LEVEL_MODE_FIXED) e->stats.level = powers->powers[e->stats.summoned_power_index].spawn_level_qty; if(powers->powers[e->stats.summoned_power_index].spawn_level_mode == SPAWN_LEVEL_MODE_LEVEL) { if(e->stats.summoner != NULL && powers->powers[e->stats.summoned_power_index].spawn_level_every != 0) { e->stats.level = powers->powers[e->stats.summoned_power_index].spawn_level_qty * (e->stats.summoner->level / powers->powers[e->stats.summoned_power_index].spawn_level_every); } } if(powers->powers[e->stats.summoned_power_index].spawn_level_mode == SPAWN_LEVEL_MODE_STAT) { if(e->stats.summoner != NULL && powers->powers[e->stats.summoned_power_index].spawn_level_every != 0) { int stat_val = 0; if(powers->powers[e->stats.summoned_power_index].spawn_level_stat == SPAWN_LEVEL_STAT_DEFENSE) stat_val = e->stats.summoner->get_defense(); if(powers->powers[e->stats.summoned_power_index].spawn_level_stat == SPAWN_LEVEL_STAT_OFFENSE) stat_val = e->stats.summoner->get_offense(); if(powers->powers[e->stats.summoned_power_index].spawn_level_stat == SPAWN_LEVEL_STAT_MENTAL) stat_val = e->stats.summoner->get_mental(); if(powers->powers[e->stats.summoned_power_index].spawn_level_stat == SPAWN_LEVEL_STAT_PHYSICAL) stat_val = e->stats.summoner->get_physical(); e->stats.level = powers->powers[e->stats.summoned_power_index].spawn_level_qty * (stat_val / powers->powers[e->stats.summoned_power_index].spawn_level_every); } } if(e->stats.level < 1) e->stats.level = 1; e->stats.applyEffects(); } if (mapr->collider.is_valid_position(espawn.pos.x + 0.5f, espawn.pos.y + 0.5f, e->stats.movement_type, false) || !e->stats.hero_ally) { e->stats.pos.x = espawn.pos.x + 0.5f; e->stats.pos.y = espawn.pos.y + 0.5f; } else { e->stats.pos.x = pc->stats.pos.x; e->stats.pos.y = pc->stats.pos.y; } // special animation state for spawning enemies e->stats.cur_state = ENEMY_SPAWN; //now apply post effects to the spawned enemy if(e->stats.summoned_power_index > 0) powers->effect(&e->stats, (espawn.summoner != NULL ? espawn.summoner : &e->stats), e->stats.summoned_power_index, e->stats.hero_ally ? SOURCE_TYPE_HERO : SOURCE_TYPE_ENEMY); //apply party passives //synchronise tha party passives in the pc stat block with the passives in the allies stat blocks //at the time the summon is spawned, it takes the passives available at that time. if the passives change later, the changes wont affect summons retrospectively. could be exploited with equipment switching for (unsigned i=0; i< pc->stats.powers_passive.size(); i++) { if (powers->powers[pc->stats.powers_passive[i]].passive && powers->powers[pc->stats.powers_passive[i]].buff_party && e->stats.hero_ally && (powers->powers[pc->stats.powers_passive[i]].buff_party_power_id == 0 || powers->powers[pc->stats.powers_passive[i]].buff_party_power_id == e->stats.summoned_power_index)) { e->stats.powers_passive.push_back(pc->stats.powers_passive[i]); } } for (unsigned i=0; istats.powers_list_items.size(); i++) { if (powers->powers[pc->stats.powers_list_items[i]].passive && powers->powers[pc->stats.powers_list_items[i]].buff_party && e->stats.hero_ally && (powers->powers[pc->stats.powers_passive[i]].buff_party_power_id == 0 || powers->powers[pc->stats.powers_passive[i]].buff_party_power_id == e->stats.summoned_power_index)) { e->stats.powers_passive.push_back(pc->stats.powers_list_items[i]); } } enemies.push_back(e); mapr->collider.block(espawn.pos.x, espawn.pos.y, e->stats.hero_ally); } } void EnemyManager::handlePartyBuff() { while (!powers->party_buffs.empty()) { int power_index = powers->party_buffs.front(); powers->party_buffs.pop(); Power *buff_power = &powers->powers[power_index]; for (unsigned int i=0; i < enemies.size(); i++) { if(enemies[i]->stats.hero_ally && enemies[i]->stats.hp > 0 && (buff_power->buff_party_power_id == 0 || buff_power->buff_party_power_id == enemies[i]->stats.summoned_power_index)) { powers->effect(&enemies[i]->stats, &pc->stats, power_index,SOURCE_TYPE_HERO); } } } } /** * perform logic() for all enemies */ void EnemyManager::logic() { if(player_blocked) { player_blocked_ticks--; if(player_blocked_ticks <= 0) player_blocked = false; } handleSpawn(); handlePartyBuff(); vector::iterator it; for (it = enemies.begin(); it != enemies.end(); ++it) { // hazards are processed after Avatar and Enemy[] // so process and clear sound effects from previous frames // check sound effects if (AUDIO) { vector::iterator found = find (sfx_prefixes.begin(), sfx_prefixes.end(), (*it)->stats.sfx_prefix); unsigned pref_id = distance(sfx_prefixes.begin(), found); if (pref_id >= sfx_prefixes.size()) { fprintf(stderr, "ERROR: enemy sfx_prefix doesn't match registered prefixes (enemy: '%s', sfx_prefix: '%s')\n", (*it)->stats.name.c_str(), (*it)->stats.sfx_prefix.c_str()); } else { if ((*it)->sfx_phys) snd->play(sound_phys[pref_id], GLOBAL_VIRTUAL_CHANNEL, (*it)->stats.pos, false); if ((*it)->sfx_ment) snd->play(sound_ment[pref_id], GLOBAL_VIRTUAL_CHANNEL, (*it)->stats.pos, false); if ((*it)->sfx_hit) snd->play(sound_hit[pref_id], GLOBAL_VIRTUAL_CHANNEL, (*it)->stats.pos, false); if ((*it)->sfx_die) snd->play(sound_die[pref_id], GLOBAL_VIRTUAL_CHANNEL, (*it)->stats.pos, false); if ((*it)->sfx_critdie) snd->play(sound_critdie[pref_id], GLOBAL_VIRTUAL_CHANNEL, (*it)->stats.pos, false); } // clear sound flags (*it)->sfx_hit = false; (*it)->sfx_phys = false; (*it)->sfx_ment = false; (*it)->sfx_die = false; (*it)->sfx_critdie = false; } // new actions this round (*it)->stats.hero_stealth = hero_stealth; (*it)->logic(); } } Enemy* EnemyManager::enemyFocus(Point mouse, FPoint cam, bool alive_only) { Point p; SDL_Rect r; for(unsigned int i = 0; i < enemies.size(); i++) { if(alive_only && (enemies[i]->stats.cur_state == ENEMY_DEAD || enemies[i]->stats.cur_state == ENEMY_CRITDEAD)) { continue; } p = map_to_screen(enemies[i]->stats.pos.x, enemies[i]->stats.pos.y, cam.x, cam.y); r.w = enemies[i]->getRender().src.w; r.h = enemies[i]->getRender().src.h; r.x = p.x - enemies[i]->getRender().offset.x; r.y = p.y - enemies[i]->getRender().offset.y; if (isWithin(r, mouse)) { Enemy *enemy = enemies[i]; return enemy; } } return NULL; } Enemy* EnemyManager::getNearestEnemy(FPoint pos) { Enemy* nearest = NULL; float best_distance = std::numeric_limits::max(); for (unsigned i=0; istats.cur_state == ENEMY_DEAD || enemies[i]->stats.cur_state == ENEMY_CRITDEAD) { continue; } float distance = calcDist(pos, enemies[i]->stats.pos); if (distance < best_distance) { best_distance = distance; nearest = enemies[i]; } } if (best_distance > INTERACT_RANGE) nearest = NULL; return nearest; } /** * If an enemy has died, reward the hero with experience points */ void EnemyManager::checkEnemiesforXP() { for (unsigned int i=0; i < enemies.size(); i++) { if (enemies[i]->reward_xp) { //adjust for party exp if necessary float xp_multiplier = 1; if(enemies[i]->kill_source_type == SOURCE_TYPE_ALLY) xp_multiplier = (float)PARTY_EXP_PERCENTAGE / 100.0f; camp->rewardXP((int)(enemies[i]->stats.xp * xp_multiplier), false); enemies[i]->reward_xp = false; // clear flag } } } bool EnemyManager::isCleared() { if (enemies.empty()) return true; for (unsigned int i=0; i < enemies.size(); i++) { if (enemies[i]->stats.alive) return false; } return true; } /** * addRenders() * Map objects need to be drawn in Z order, so we allow a parent object (GameEngine) * to collect all mobile sprites each frame. */ void EnemyManager::addRenders(vector &r, vector &r_dead) { vector::iterator it; for (it = enemies.begin(); it != enemies.end(); ++it) { bool dead = (*it)->stats.corpse; if (!dead || (dead && (*it)->stats.corpse_ticks > 0)) { Renderable re = (*it)->getRender(); re.prio = 1; // draw corpses below objects so that floor loot is more visible (dead ? r_dead : r).push_back(re); // add effects for (unsigned i = 0; i < (*it)->stats.effects.effect_list.size(); ++i) { if ((*it)->stats.effects.effect_list[i].animation) { Renderable ren = (*it)->stats.effects.effect_list[i].animation->getCurrentFrame(0); ren.map_pos = (*it)->stats.pos; if ((*it)->stats.effects.effect_list[i].render_above) ren.prio = 2; else ren.prio = 0; r.push_back(ren); } } } } } EnemyManager::~EnemyManager() { for (unsigned int i=0; i < enemies.size(); i++) { anim->decreaseCount(enemies[i]->animationSet->getName()); delete enemies[i]; } for (unsigned i=0; iunload(sound_phys[i]); snd->unload(sound_ment[i]); snd->unload(sound_hit[i]); snd->unload(sound_die[i]); snd->unload(sound_critdie[i]); } } flare-engine-0.19/src/EnemyManager.h000066400000000000000000000037611224717101500173160ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /* * class EnemyManager */ #pragma once #ifndef ENEMY_MANAGER_H #define ENEMY_MANAGER_H #include "Settings.h" #include "Enemy.h" #include "Utils.h" #include "CampaignManager.h" class EnemyManager { private: void loadSounds(const std::string& type_id); void loadAnimations(Enemy *e); std::vector sfx_prefixes; std::vector sound_phys; std::vector sound_ment; std::vector sound_hit; std::vector sound_die; std::vector sound_critdie; std::vector anim_prefixes; std::vector > anim_entities; /** * callee is responsible for deleting returned enemy object */ Enemy *getEnemyPrototype(const std::string& type_id); std::vector prototypes; public: EnemyManager(); ~EnemyManager(); void handleNewMap(); void handleSpawn(); void handlePartyBuff(); void logic(); void addRenders(std::vector &r, std::vector &r_dead); void checkEnemiesforXP(); bool isCleared(); Enemy *enemyFocus(Point mouse, FPoint cam, bool alive_only); Enemy *getNearestEnemy(FPoint pos); // vars std::vector enemies; int hero_stealth; bool player_blocked; int player_blocked_ticks; }; #endif flare-engine-0.19/src/Entity.cpp000066400000000000000000000271701224717101500165550ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger and kitano Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class Entity * * An Entity represents any character in the game - the player, allies, enemies * This base class handles logic common to all of these child classes */ #include "Animation.h" #include "AnimationManager.h" #include "AnimationSet.h" #include "CommonIncludes.h" #include "Entity.h" #include "SharedResources.h" #include "UtilsMath.h" #include "SharedGameResources.h" #include #ifdef _MSC_VER #define M_SQRT2 sqrt(2.0) #endif const int directionDeltaX[8] = {-1, -1, -1, 0, 1, 1, 1, 0}; const int directionDeltaY[8] = { 1, 0, -1, -1, -1, 0, 1, 1}; const float speedMultiplyer[8] = { (float)(1.0/M_SQRT2), 1.0f, (float)(1.0/M_SQRT2), 1.0f, (float)(1.0/M_SQRT2), 1.0f, (float)(1.0/M_SQRT2), 1.0f}; using namespace std; Entity::Entity() : sprites(NULL) , sfx_phys(false) , sfx_ment(false) , sfx_hit(false) , sfx_die(false) , sfx_critdie(false) , sfx_block(false) , activeAnimation(NULL) , animationSet(NULL) { } Entity::Entity(const Entity &e) : sprites(e.sprites) , sfx_phys(e.sfx_phys) , sfx_ment(e.sfx_ment) , sfx_hit(e.sfx_hit) , sfx_die(e.sfx_die) , sfx_critdie(e.sfx_critdie) , sfx_block(e.sfx_block) , activeAnimation(new Animation(*e.activeAnimation)) , animationSet(e.animationSet) , stats(StatBlock(e.stats)) { } /** * move() * Apply speed to the direction faced. * * @return Returns false if wall collision, otherwise true. */ bool Entity::move() { if (stats.effects.forced_move) return mapr->collider.move(stats.pos.x, stats.pos.y, stats.forced_speed.x, stats.forced_speed.y, stats.movement_type, stats.hero); if (stats.effects.speed == 0) return false; float speed = stats.speed * speedMultiplyer[stats.direction] * stats.effects.speed / 100; float dx = speed * directionDeltaX[stats.direction]; float dy = speed * directionDeltaY[stats.direction]; bool full_move = mapr->collider.move(stats.pos.x, stats.pos.y, dx, dy, stats.movement_type, stats.hero); return full_move; } /** * Whenever a hazard collides with an entity, this function resolves the effect * Called by HazardManager * * Returns false on miss */ bool Entity::takeHit(const Hazard &h) { //check if this enemy should be affected by this hazard based on the category if(!powers->powers[h.power_index].target_categories.empty() && !stats.hero) { //the power has a target category requirement, so if it doesnt match, dont continue bool match_found = false; for (unsigned int i=0; ipowers[h.power_index].target_categories.begin(), powers->powers[h.power_index].target_categories.end(), stats.categories[i]) != powers->powers[h.power_index].target_categories.end()) { match_found = true; } } if(!match_found) return false; } //if the target is already dead, they cannot be hit if ((stats.cur_state == ENEMY_DEAD || stats.cur_state == ENEMY_CRITDEAD) && !stats.hero) return false; if(stats.cur_state == AVATAR_DEAD && stats.hero) return false; //if the target is an enemy and they are not already in combat, activate a beacon to draw other enemies into battle if (!stats.in_combat && !stats.hero && !stats.hero_ally) { stats.join_combat = true; stats.in_combat = true; powers->activate(stats.power_index[BEACON], &stats, stats.pos); //emit beacon } // exit if it was a beacon (to prevent stats.targeted from being set) if (powers->powers[h.power_index].beacon) return false; // prepare the combat text CombatText *combat_text = comb; // if it's a miss, do nothing int accuracy = h.accuracy; if(powers->powers[h.power_index].mod_accuracy_mode == STAT_MODIFIER_MODE_MULTIPLY) accuracy = accuracy * powers->powers[h.power_index].mod_accuracy_value / 100; else if(powers->powers[h.power_index].mod_accuracy_mode == STAT_MODIFIER_MODE_ADD) accuracy += powers->powers[h.power_index].mod_accuracy_value; else if(powers->powers[h.power_index].mod_accuracy_mode == STAT_MODIFIER_MODE_ABSOLUTE) accuracy = powers->powers[h.power_index].mod_accuracy_value; int avoidance = 0; if(!powers->powers[h.power_index].trait_avoidance_ignore) { avoidance = stats.get(STAT_AVOIDANCE); if (stats.effects.triggered_block) avoidance *= 2; } int true_avoidance = 100 - (accuracy + 25 - avoidance); //if we are using an absolute accuracy, offset the constant 25 added to the accuracy if(powers->powers[h.power_index].mod_accuracy_mode == STAT_MODIFIER_MODE_ABSOLUTE) true_avoidance += 25; clampFloor(true_avoidance, MIN_AVOIDANCE); clampCeil(true_avoidance, MAX_AVOIDANCE); if (percentChance(true_avoidance)) { combat_text->addMessage(msg->get("miss"), stats.pos, COMBAT_MESSAGE_MISS); return false; } // calculate base damage int dmg = randBetween(h.dmg_min, h.dmg_max); if(powers->powers[h.power_index].mod_damage_mode == STAT_MODIFIER_MODE_MULTIPLY) dmg = dmg * powers->powers[h.power_index].mod_damage_value_min / 100; else if(powers->powers[h.power_index].mod_damage_mode == STAT_MODIFIER_MODE_ADD) dmg += powers->powers[h.power_index].mod_damage_value_min; else if(powers->powers[h.power_index].mod_damage_mode == STAT_MODIFIER_MODE_ABSOLUTE) dmg = randBetween(powers->powers[h.power_index].mod_damage_value_min, powers->powers[h.power_index].mod_damage_value_max); // apply elemental resistance if (h.trait_elemental >= 0 && unsigned(h.trait_elemental) < stats.vulnerable.size()) { unsigned i = h.trait_elemental; int vulnerable = stats.vulnerable[i]; clampFloor(vulnerable,MIN_RESIST); if (stats.vulnerable[i] < 100) clampCeil(vulnerable,MAX_RESIST); dmg = (dmg * vulnerable) / 100; } if (!h.trait_armor_penetration) { // armor penetration ignores all absorption // substract absorption from armor int absorption = randBetween(stats.get(STAT_ABS_MIN), stats.get(STAT_ABS_MAX)); if (stats.effects.triggered_block) { absorption += absorption + stats.get(STAT_ABS_MAX); // blocking doubles your absorb amount } if (absorption > 0 && dmg > 0) { int abs = absorption; if ((abs*100)/dmg < MIN_BLOCK) absorption = (dmg * MIN_BLOCK) /100; if ((abs*100)/dmg > MAX_BLOCK) absorption = (dmg * MAX_BLOCK) /100; if ((abs*100)/dmg < MIN_ABSORB && !stats.effects.triggered_block) absorption = (dmg * MIN_ABSORB) /100; if ((abs*100)/dmg > MAX_ABSORB && !stats.effects.triggered_block) absorption = (dmg * MAX_ABSORB) /100; // Sometimes, the absorb limits cause absorbtion to drop to 1 // This could be confusing to a player that has something with an absorb of 1 equipped // So we round absorption up in this case if (absorption == 0) absorption = 1; } dmg = dmg - absorption; if (dmg <= 0) { dmg = 0; if (h.trait_elemental < 0) { if (stats.effects.triggered_block && MAX_BLOCK < 100) dmg = 1; else if (!stats.effects.triggered_block && MAX_ABSORB < 100) dmg = 1; } else { if (MAX_RESIST < 100) dmg = 1; } sfx_block = true; if (activeAnimation->getName() == "block") resetActiveAnimation(); } } // check for crits int true_crit_chance = h.crit_chance; if(powers->powers[h.power_index].mod_crit_mode == STAT_MODIFIER_MODE_MULTIPLY) true_crit_chance = true_crit_chance * powers->powers[h.power_index].mod_crit_value / 100; else if(powers->powers[h.power_index].mod_crit_mode == STAT_MODIFIER_MODE_ADD) true_crit_chance += powers->powers[h.power_index].mod_crit_value; else if(powers->powers[h.power_index].mod_crit_mode == STAT_MODIFIER_MODE_ABSOLUTE) true_crit_chance = powers->powers[h.power_index].mod_crit_value; if (stats.effects.stun || stats.effects.speed < 100) true_crit_chance += h.trait_crits_impaired; bool crit = percentChance(true_crit_chance); if (crit) { dmg = dmg + h.dmg_max; if(!stats.hero) mapr->shaky_cam_ticks = MAX_FRAMES_PER_SEC/2; } if(stats.hero) combat_text->addMessage(dmg, stats.pos, COMBAT_MESSAGE_TAKEDMG); else { if(crit) combat_text->addMessage(dmg, stats.pos, COMBAT_MESSAGE_CRIT); else combat_text->addMessage(dmg, stats.pos, COMBAT_MESSAGE_GIVEDMG); } // temporarily save the current HP for calculating HP/MP steal on final blow int prev_hp = stats.hp; // apply damage stats.takeDamage(dmg); // after effects if (dmg > 0) { // damage always breaks stun stats.effects.removeEffectType("stun"); if (stats.hp > 0) { if (h.mod_power > 0) powers->effect(&stats, h.src_stats, h.mod_power,h.source_type); powers->effect(&stats, h.src_stats, h.power_index,h.source_type); } if (!stats.effects.immunity) { if (stats.effects.forced_move && stats.hp > 0) { float theta = calcTheta(h.src_stats->pos.x, h.src_stats->pos.y, stats.pos.x, stats.pos.y); stats.forced_speed.x = stats.effects.forced_speed * cos(theta); stats.forced_speed.y = stats.effects.forced_speed * sin(theta); } if (h.hp_steal != 0) { int steal_amt = (min(dmg, prev_hp) * h.hp_steal) / 100; if (steal_amt == 0) steal_amt = 1; combat_text->addMessage(msg->get("+%d HP",steal_amt), h.src_stats->pos, COMBAT_MESSAGE_BUFF); h.src_stats->hp = min(h.src_stats->hp + steal_amt, h.src_stats->get(STAT_HP_MAX)); } if (h.mp_steal != 0) { int steal_amt = (min(dmg, prev_hp) * h.mp_steal) / 100; if (steal_amt == 0) steal_amt = 1; combat_text->addMessage(msg->get("+%d MP",steal_amt), h.src_stats->pos, COMBAT_MESSAGE_BUFF); h.src_stats->mp = min(h.src_stats->mp + steal_amt, h.src_stats->get(STAT_MP_MAX)); } } } // post effect power if (h.post_power > 0 && dmg > 0) { powers->activate(h.post_power, h.src_stats, stats.pos); } // interrupted to new state if (dmg > 0) { bool chance_poise = percentChance(stats.get(STAT_POISE)); if(stats.hp <= 0) { stats.effects.triggered_death = true; if(stats.hero) stats.cur_state = AVATAR_DEAD; else { doRewards(h.source_type); if (crit) stats.cur_state = ENEMY_CRITDEAD; else stats.cur_state = ENEMY_DEAD; mapr->collider.unblock(stats.pos.x,stats.pos.y); } } // don't go through a hit animation if stunned else if (!stats.effects.stun && !chance_poise) { sfx_hit = true; if(!chance_poise && stats.cooldown_hit_ticks == 0) { if(stats.hero) stats.cur_state = AVATAR_HIT; else stats.cur_state = ENEMY_HIT; stats.cooldown_hit_ticks = stats.cooldown_hit; } // roll to see if the enemy's ON_HIT power is casted if (percentChance(stats.power_chance[ON_HIT])) { powers->activate(stats.power_index[ON_HIT], &stats, stats.pos); } } // just play the hit sound else sfx_hit = true; } return true; } void Entity::resetActiveAnimation() { activeAnimation->reset(); } /** * Set the entity's current animation by name */ bool Entity::setAnimation(const string& animationName) { // if the animation is already the requested one do nothing if (activeAnimation != NULL && activeAnimation->getName() == animationName) return true; delete activeAnimation; activeAnimation = animationSet->getAnimation(animationName); if (activeAnimation == NULL) fprintf(stderr, "Entity::setAnimation(%s): not found\n", animationName.c_str()); return activeAnimation == NULL; } Entity::~Entity () { delete activeAnimation; } flare-engine-0.19/src/Entity.h000066400000000000000000000032341224717101500162150ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger and kitano This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class Entity * * An Entity represents any character in the game - the player, allies, enemies * This base class handles logic common to all of these child classes */ #pragma once #ifndef ENTITY_H #define ENTITY_H #include "CommonIncludes.h" #include "StatBlock.h" class Animation; class AnimationSet; class Entity { protected: SDL_Surface *sprites; public: Entity(); Entity(const Entity&); virtual ~Entity(); bool move(); bool takeHit(const Hazard &h); virtual void resetActiveAnimation(); virtual void doRewards(int){} // sound effects flags bool sfx_phys; bool sfx_ment; bool sfx_hit; bool sfx_die; bool sfx_critdie; bool sfx_block; // Each child of Entity defines its own rendering method virtual Renderable getRender() = 0; bool setAnimation(const std::string& animation); Animation *activeAnimation; AnimationSet *animationSet; StatBlock stats; }; extern const int directionDeltaX[]; extern const int directionDeltaY[]; extern const float speedMultiplyer[]; #endif flare-engine-0.19/src/EventManager.cpp000066400000000000000000000444011224717101500176510ustar00rootroot00000000000000/* Copyright © 2013 Igor Paliychuk This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "EventManager.h" #include "UtilsParsing.h" #include "SharedGameResources.h" #include "UtilsFileSystem.h" #include "UtilsMath.h" using namespace std; EventManager::EventManager() { } EventManager::~EventManager() { } void EventManager::loadEvent(FileParser &infile, Event* evnt) { if (!evnt) return; if (infile.key == "type") { // @ATTR event.type|[on_trigger:on_mapexit:on_leave:on_load:on_clear]|Type of map event. std::string type = infile.val; evnt->type = type; if (type == "on_trigger"); else if (type == "on_mapexit"); // no need to set keep_after_trigger to false correctly, it's ignored anyway else if (type == "on_leave"); else if (type == "on_load") { evnt->keep_after_trigger = false; } else if (type == "on_clear") { evnt->keep_after_trigger = false; } else { fprintf(stderr, "EventManager: Loading event in file %s\nEvent type %s unknown, change to \"on_trigger\" to suppress this warning.\n", infile.getFileName().c_str(), type.c_str()); } } else if (infile.key == "location") { // @ATTR event.location|[x,y,w,h]|Defines the location area for the event. evnt->location.x = toInt(infile.nextValue()); evnt->location.y = toInt(infile.nextValue()); evnt->location.w = toInt(infile.nextValue()); evnt->location.h = toInt(infile.nextValue()); evnt->center.x = evnt->location.x + (float)evnt->location.w/2; evnt->center.y = evnt->location.y + (float)evnt->location.h/2; } else if (infile.key == "hotspot") { // @ATTR event.hotspot|[ [x, y, w, h] : location ]|Event uses location as hotspot or defined by rect. if (infile.val == "location") { evnt->hotspot.x = evnt->location.x; evnt->hotspot.y = evnt->location.y; evnt->hotspot.w = evnt->location.w; evnt->hotspot.h = evnt->location.h; } else { evnt->hotspot.x = toInt(infile.nextValue()); evnt->hotspot.y = toInt(infile.nextValue()); evnt->hotspot.w = toInt(infile.nextValue()); evnt->hotspot.h = toInt(infile.nextValue()); } } else if (infile.key == "cooldown") { // @ATTR event.cooldown|duration|Duration for event cooldown. evnt->cooldown = parse_duration(infile.val); } else if (infile.key == "reachable_from") { // @ATTR event.reachable_from|[x,y,w,h]|If the hero is inside this rectangle, they can activate the event. evnt->reachable_from.x = toInt(infile.nextValue()); evnt->reachable_from.y = toInt(infile.nextValue()); evnt->reachable_from.w = toInt(infile.nextValue()); evnt->reachable_from.h = toInt(infile.nextValue()); } else { loadEventComponent(infile, evnt, NULL); } } void EventManager::loadEventComponent(FileParser &infile, Event* evnt, Event_Component* ec) { Event_Component *e = NULL; if (evnt) { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); } else if (ec) { e = ec; } if (!e) return; e->type = infile.key; if (infile.key == "tooltip") { // @ATTR event.tooltip|string|Tooltip for event e->s = msg->get(infile.val); } else if (infile.key == "power_path") { // @ATTR event.power_path|[hero:[x,y]]|Event power path // x,y are src, if s=="hero" we target the hero, // else we'll use values in a,b as coordinates e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); std::string dest = infile.nextValue(); if (dest == "hero") { e->s = "hero"; } else { e->a = toInt(dest); e->b = toInt(infile.nextValue()); } } else if (infile.key == "power_damage") { // @ATTR event.power_damage|min(integer), max(integer)|Range of power damage e->a = toInt(infile.nextValue()); e->b = toInt(infile.nextValue()); } else if (infile.key == "intermap") { // @ATTR event.intermap|[map(string),x(integer),y(integer)]|Jump to specific map at location specified. e->s = infile.nextValue(); e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); } else if (infile.key == "intramap") { // @ATTR event.intramap|[x(integer),y(integer)]|Jump to specific position within current map. e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); } else if (infile.key == "mapmod") { // @ATTR event.mapmod|[string,int,int,int],..|Modify map tiles e->s = infile.nextValue(); e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); e->z = toInt(infile.nextValue()); // add repeating mapmods if (evnt) { std::string repeat_val = infile.nextValue(); while (repeat_val != "") { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); e->type = infile.key; e->s = repeat_val; e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); e->z = toInt(infile.nextValue()); repeat_val = infile.nextValue(); } } } else if (infile.key == "soundfx") { // @ATTR event.soundfx|[soundfile(string),x(integer),y(integer)]|Play a sound at optional location e->s = infile.nextValue(); e->x = e->y = -1; std::string s = infile.nextValue(); if (s != "") e->x = toInt(s); s = infile.nextValue(); if (s != "") e->y = toInt(s); } else if (infile.key == "loot") { // @ATTR event.loot|[string,x(integer),y(integer),drop_chance([fixed:chance(integer)]),quantity_min(integer),quantity_max(integer)],...|Add loot to the event e->s = infile.nextValue(); e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); // drop chance std::string chance = infile.nextValue(); if (chance == "fixed") e->z = 0; else e->z = toInt(chance); // quantity min/max e->a = toInt(infile.nextValue()); if (e->a < 1) e->a = 1; e->b = toInt(infile.nextValue()); if (e->b < e->a) e->b = e->a; // add repeating loot if (evnt) { std::string repeat_val = infile.nextValue(); while (repeat_val != "") { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); e->type = infile.key; e->s = repeat_val; e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); chance = infile.nextValue(); if (chance == "fixed") e->z = 0; else e->z = toInt(chance); e->a = toInt(infile.nextValue()); if (e->a < 1) e->a = 1; e->b = toInt(infile.nextValue()); if (e->b < e->a) e->b = e->a; repeat_val = infile.nextValue(); } } } else if (infile.key == "msg") { // @ATTR event.msg|string|Adds a message to be displayed for the event. e->s = msg->get(infile.val); } else if (infile.key == "shakycam") { // @ATTR event.shakycam|integer| e->x = toInt(infile.val); } else if (infile.key == "requires_status") { // @ATTR event.requires_status|string,...|Event requires list of statuses e->s = infile.nextValue(); // add repeating requires_status if (evnt) { std::string repeat_val = infile.nextValue(); while (repeat_val != "") { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); e->type = infile.key; e->s = repeat_val; repeat_val = infile.nextValue(); } } } else if (infile.key == "requires_not_status") { // @ATTR event.requires_not|string,...|Event requires not list of statuses e->s = infile.nextValue(); // add repeating requires_not if (evnt) { std::string repeat_val = infile.nextValue(); while (repeat_val != "") { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); e->type = infile.key; e->s = repeat_val; repeat_val = infile.nextValue(); } } } else if (infile.key == "requires_level") { // @ATTR event.requires_level|integer|Event requires hero level e->x = toInt(infile.nextValue()); } else if (infile.key == "requires_not_level") { // @ATTR event.requires_not_level|integer|Event requires not hero level e->x = toInt(infile.nextValue()); } else if (infile.key == "requires_currency") { // @ATTR event.requires_currency|integer|Event requires atleast this much currency e->x = toInt(infile.nextValue()); } else if (infile.key == "requires_item") { // @ATTR event.requires_item|integer,...|Event requires specific item e->x = toInt(infile.nextValue()); // add repeating requires_item if (evnt) { std::string repeat_val = infile.nextValue(); while (repeat_val != "") { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); e->type = infile.key; e->x = toInt(repeat_val); repeat_val = infile.nextValue(); } } } else if (infile.key == "set_status") { // @ATTR event.set_status|string,...|Sets specified statuses e->s = infile.nextValue(); // add repeating set_status if (evnt) { std::string repeat_val = infile.nextValue(); while (repeat_val != "") { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); e->type = infile.key; e->s = repeat_val; repeat_val = infile.nextValue(); } } } else if (infile.key == "unset_status") { // @ATTR event.unset_status|string,...|Unsets specified statuses e->s = infile.nextValue(); // add repeating unset_status if (evnt) { std::string repeat_val = infile.nextValue(); while (repeat_val != "") { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); e->type = infile.key; e->s = repeat_val; repeat_val = infile.nextValue(); } } } else if (infile.key == "remove_currency") { // @ATTR event.remove_currency|integer|Removes specified amount of currency from hero inventory e->x = toInt(infile.val); clampFloor(e->x, 0); } else if (infile.key == "remove_item") { // @ATTR event.remove_item|integer,...|Removes specified item from hero inventory e->x = toInt(infile.nextValue()); // add repeating remove_item if (evnt) { std::string repeat_val = infile.nextValue(); while (repeat_val != "") { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); e->type = infile.key; e->x = toInt(repeat_val); repeat_val = infile.nextValue(); } } } else if (infile.key == "reward_xp") { // @ATTR event.reward_xp|integer|Reward hero with specified amount of experience points. e->x = toInt(infile.val); clampFloor(e->x, 0); } else if (infile.key == "reward_currency") { // @ATTR event.reward_currency|integer|Reward hero with specified amount of currency. e->x = toInt(infile.val); clampFloor(e->x, 0); } else if (infile.key == "reward_item") { // @ATTR event.reward_item|x(integer),y(integer)|Reward hero with y number of item x. e->x = toInt(infile.nextValue()); e->y = toInt(infile.val); clampFloor(e->y, 0); } else if (infile.key == "restore") { // @ATTR event.restore|string|Restore the hero's HP, MP, and/or status. e->s = infile.val; } else if (infile.key == "power") { // @ATTR event.power|power_id|Specify power coupled with event. e->x = toInt(infile.val); } else if (infile.key == "spawn") { // @ATTR event.spawn|[string,x(integer),y(integer)], ...|Spawn specified enemies at location e->s = infile.nextValue(); e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); // add repeating spawn if (evnt) { std::string repeat_val = infile.nextValue(); while (repeat_val != "") { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); e->type = infile.key; e->s = repeat_val; e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); repeat_val = infile.nextValue(); } } } else if (infile.key == "stash") { // @ATTR event.stash|string| e->s = infile.val; } else if (infile.key == "npc") { // @ATTR event.npc|string| e->s = infile.val; } else if (infile.key == "music") { // @ATTR event.music|string|Change background music to specified file. e->s = infile.val; } else if (infile.key == "cutscene") { // @ATTR event.cutscene|string|Show specified cutscene. e->s = infile.val; } else if (infile.key == "repeat") { // @ATTR event.repeat|string| e->s = infile.val; } else { fprintf(stderr, "EventManager: Unknown key value: %s in file %s in section %s\n", infile.key.c_str(), infile.getFileName().c_str(), infile.section.c_str()); } } /** * A particular event has been triggered. * Process all of this events components. * * @param The triggered event * @return Returns true if the event shall not be run again. */ bool EventManager::executeEvent(Event &ev) { if(&ev == NULL) return false; // skip executing events that are on cooldown if (ev.cooldown_ticks > 0) return false; // set cooldown ev.cooldown_ticks = ev.cooldown; const Event_Component *ec; for (unsigned i = 0; i < ev.components.size(); ++i) { ec = &ev.components[i]; if (ec->type == "set_status") { camp->setStatus(ec->s); } else if (ec->type == "unset_status") { camp->unsetStatus(ec->s); } else if (ec->type == "intermap") { if (fileExists(mods->locate("maps/" + ec->s))) { mapr->teleportation = true; mapr->teleport_mapname = ec->s; mapr->teleport_destination.x = ec->x + 0.5f; mapr->teleport_destination.y = ec->y + 0.5f; } else { ev.keep_after_trigger = false; mapr->log_msg = msg->get("Unknown destination"); } } else if (ec->type == "intramap") { mapr->teleportation = true; mapr->teleport_mapname = ""; mapr->teleport_destination.x = ec->x + 0.5f; mapr->teleport_destination.y = ec->y + 0.5f; } else if (ec->type == "mapmod") { if (ec->s == "collision") { mapr->collider.colmap[ec->x][ec->y] = ec->z; } else { int index = distance(mapr->layernames.begin(), find(mapr->layernames.begin(), mapr->layernames.end(), ec->s)); mapr->layers[index][ec->x][ec->y] = ec->z; if (ec->a < (int)(mapr->index_objectlayer)) mapr->repaint_background = true; } mapr->map_change = true; } else if (ec->type == "soundfx") { FPoint pos(0,0); bool loop = false; if (ec->x != -1 && ec->y != -1) { if (ec->x != 0 && ec->y != 0) { pos.x = ec->x + 0.5f; pos.y = ec->y + 0.5f; } } else if (ev.location.x != 0 && ev.location.y != 0) { pos.x = ev.location.x + 0.5f; pos.y = ev.location.y + 0.5f; } if (ev.type == "on_load") loop = true; SoundManager::SoundID sid = snd->load(ec->s, "MapRenderer background soundfx"); snd->play(sid, GLOBAL_VIRTUAL_CHANNEL, pos, loop); mapr->sids.push_back(sid); } else if (ec->type == "loot") { mapr->loot.push_back(*ec); } else if (ec->type == "msg") { mapr->log_msg = ec->s; } else if (ec->type == "shakycam") { mapr->shaky_cam_ticks = ec->x; } else if (ec->type == "remove_currency") { camp->removeCurrency(ec->x); } else if (ec->type == "remove_item") { camp->removeItem(ec->x); } else if (ec->type == "reward_xp") { camp->rewardXP(ec->x, true); } else if (ec->type == "reward_currency") { camp->rewardCurrency(ec->x); } else if (ec->type == "reward_item") { ItemStack istack; istack.item = ec->x; istack.quantity = ec->y; camp->rewardItem(istack); } else if (ec->type == "restore") { camp->restoreHPMP(ec->s); } else if (ec->type == "spawn") { Point spawn_pos; spawn_pos.x = ec->x; spawn_pos.y = ec->y; powers->spawn(ec->s, spawn_pos); } else if (ec->type == "power") { int power_index = ec->x; Event_Component *ec_path = ev.getComponent("power_path"); if (ev.stats == NULL) { ev.stats = new StatBlock(); ev.stats->current[STAT_ACCURACY] = 1000; //always hits its target // if a power path was specified, place the source position there if (ec_path) { ev.stats->pos.x = ec_path->x + 0.5f; ev.stats->pos.y = ec_path->y + 0.5f; } // otherwise the source position is the event position else { ev.stats->pos.x = ev.location.x + 0.5f; ev.stats->pos.y = ev.location.y + 0.5f; } Event_Component *ec_damage = ev.getComponent("power_damage"); if (ec_damage) { ev.stats->current[STAT_DMG_MELEE_MIN] = ev.stats->current[STAT_DMG_RANGED_MIN] = ev.stats->current[STAT_DMG_MENT_MIN] = ec_damage->a; ev.stats->current[STAT_DMG_MELEE_MAX] = ev.stats->current[STAT_DMG_RANGED_MAX] = ev.stats->current[STAT_DMG_MENT_MAX] = ec_damage->b; } } FPoint target; if (ec_path) { // targets hero option if (ec_path->s == "hero") { target.x = mapr->cam.x; target.y = mapr->cam.y; } // targets fixed path option else { target.x = ec_path->a + 0.5f; target.y = ec_path->b + 0.5f; } } // no path specified, targets self location else { target.x = ev.stats->pos.x; target.y = ev.stats->pos.y; } powers->activate(power_index, ev.stats, target); } else if (ec->type == "stash") { mapr->stash = true; mapr->stash_pos.x = ev.location.x + 0.5f; mapr->stash_pos.y = ev.location.y + 0.5f; } else if (ec->type == "npc") { mapr->event_npc = ec->s; } else if (ec->type == "music") { mapr->music_filename = ec->s; mapr->loadMusic(); } else if (ec->type == "cutscene") { mapr->cutscene = true; mapr->cutscene_file = ec->s; } else if (ec->type == "repeat") { ev.keep_after_trigger = toBool(ec->s); } } return !ev.keep_after_trigger; } bool EventManager::isActive(const Event &e) { for (unsigned i=0; i < e.components.size(); i++) { if (e.components[i].type == "requires_not_status") { if (camp->checkStatus(e.components[i].s)) { return false; } } else if (e.components[i].type == "requires_status") { if (!camp->checkStatus(e.components[i].s)) { return false; } } else if (e.components[i].type == "requires_currency") { if (!camp->checkCurrency(e.components[i].x)) { return false; } } else if (e.components[i].type == "requires_item") { if (!camp->checkItem(e.components[i].x)) { return false; } } else if (e.components[i].type == "requires_level") { if (camp->hero->level < e.components[i].x) { return false; } } else if (e.components[i].type == "requires_not_level") { if (camp->hero->level >= e.components[i].x) { return false; } } } return true; } flare-engine-0.19/src/EventManager.h000066400000000000000000000050761224717101500173230ustar00rootroot00000000000000/* Copyright © 2013 Igor Paliychuk This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /* * class EventManager */ #pragma once #ifndef EVENT_MANAGER_H #define EVENT_MANAGER_H #include "FileParser.h" #include "Utils.h" #include "StatBlock.h" class Event { public: std::string type; std::vector components; SDL_Rect location; SDL_Rect hotspot; int cooldown; // events that run multiple times pause this long in frames int cooldown_ticks; StatBlock *stats; bool keep_after_trigger; // if this event has been triggered once, should this event be kept? If so, this event can be triggered multiple times. FPoint center; SDL_Rect reachable_from; Event() : type("") , components(std::vector()) , cooldown(0) , cooldown_ticks(0) , stats(NULL) , keep_after_trigger(true) , center(FPoint()) { location.x = location.y = location.w = location.h = 0; hotspot.x = hotspot.y = hotspot.w = hotspot.h = 0; reachable_from.x = reachable_from.y = reachable_from.w = reachable_from.h = 0; } // returns a pointer to the event component within the components list // no need to free the pointer by caller // NULL will be returned if no such event is found Event_Component *getComponent(const std::string &_type) { std::vector::iterator it; for (it = components.begin(); it != components.end(); ++it) if (it->type == _type) return &(*it); return NULL; } void deleteAllComponents(const std::string &_type) { std::vector::iterator it; for (it = components.begin(); it != components.end(); ++it) if (it->type == _type) it = components.erase(it); } ~Event() { delete stats; // may be NULL, but delete can deal with null pointers. } }; class EventManager { public: EventManager(); ~EventManager(); static void loadEvent(FileParser &infile, Event* evnt); static void loadEventComponent(FileParser &infile, Event* evnt, Event_Component* ec); static bool executeEvent(Event &e); static bool isActive(const Event &e); }; #endif flare-engine-0.19/src/FileParser.cpp000066400000000000000000000103631224717101500173310ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "FileParser.h" #include "UtilsParsing.h" #include "UtilsFileSystem.h" #include "SharedResources.h" using namespace std; bool new_section; std::string section; std::string key; std::string val; FileParser::FileParser() : current_index(0) , line("") , new_section(false) , section("") , key("") , val("") { } bool FileParser::open(const string& _filename, bool locateFileName, bool stopAfterFirstFile, const string &_errormessage) { filenames.clear(); if (locateFileName) { if (stopAfterFirstFile) { filenames.push_back(mods->locate(_filename)); } else { filenames = mods->list(_filename); } } else { if (!stopAfterFirstFile && isDirectory(_filename)) { getFileList(_filename, "txt", filenames); } else { filenames.push_back(_filename); } } current_index = 0; this->errormessage = _errormessage; // This should never happen, because when stopAfterFirstFile is set, we // expect to have only one file added above. if (stopAfterFirstFile) if (filenames.size() > 1) fprintf(stderr, "Error in FileParser::open logic. More files detected, although stopAfterFirstFile was set\n"); if (filenames.size() == 0 && !errormessage.empty()) { fprintf(stderr, "%s: %s: No such file or directory!\n", _filename.c_str(), errormessage.c_str()); return false; } const string current_filename = filenames[0]; infile.open(current_filename.c_str(), ios::in); bool ret = infile.is_open(); if (!ret && !errormessage.empty()) fprintf(stderr, "%s: %s\n", errormessage.c_str(), current_filename.c_str()); return ret; } void FileParser::close() { if (infile.is_open()) infile.close(); } /** * Advance to the next key pair * Take note if a new section header is encountered * * @return false if EOF, otherwise true */ bool FileParser::next() { string starts_with; new_section = false; while (current_index < filenames.size()) { while (infile.good()) { line = trim(getLine(infile)); // skip ahead if this line is empty if (line.length() == 0) continue; starts_with = line.at(0); // skip ahead if this line is a comment if (starts_with == "#") continue; // set new section if this line is a section declaration if (starts_with == "[") { new_section = true; section = parse_section_title(line); // keep searching for a key-pair continue; } // this is a keypair. Perform basic parsing and return parse_key_pair(line, key, val); return true; } infile.close(); current_index++; if (current_index == filenames.size()) return false; const string current_filename = filenames[current_index]; infile.clear(); infile.open(current_filename.c_str(), ios::in); if (!infile.is_open()) { if (!errormessage.empty()) fprintf(stderr, "%s: %s\n", errormessage.c_str(), current_filename.c_str()); return false; } // a new file starts a new section new_section = true; } // hit the end of file return false; } /** * Get an unparsed, unfiltered line from the input file */ string FileParser::getRawLine() { line = ""; if (infile.good()) { line = getLine(infile); } return line; } string FileParser::nextValue() { if (val == "") { return ""; // not found } string s; size_t seppos = val.find_first_of(','); size_t alt_seppos = val.find_first_of(';'); if (alt_seppos != string::npos && alt_seppos < seppos) seppos = alt_seppos; // return the first ',' or ';' if (seppos == string::npos) { s = val; val = ""; } else { s = val.substr(0, seppos); val = val.substr(seppos+1); } return s; } std::string FileParser::getFileName() { return filenames[current_index]; } FileParser::~FileParser() { close(); } flare-engine-0.19/src/FileParser.h000066400000000000000000000054051224717101500167770ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * FileParser * * Abstract the generic key-value pair ini-style file format */ #pragma once #ifndef FILE_PARSER_H #define FILE_PARSER_H #include "CommonIncludes.h" class FileParser { private: std::vector filenames; unsigned current_index; std::string errormessage; std::ifstream infile; std::string line; public: FileParser(); ~FileParser(); /** * @brief open * @param filename * The generic filename to be opened. This generic filename will be located * by the ModManager. * If this is a directory, all files in this directory will be opened. * * @param errormessage * Optional parameter, will be printed to stderr together with the filename * if an error occurs. If errormessage is empty, there will be no output to * stderr in any case. * * @param locateFileName * If this parameter is set to true, the filename will not be interpreted as * a generic locatable filename and the ModManager is used to locate the * actual filename before opening the file. It is true by default. * If this is set to false, then the filename is interpreted as is. * * @param stopAfterFirstFile * If this is set, the newest file is being read. This is the default. * If it is set to false, all possible files are parsed and delivered as * one big stream. Also if using direct directory pathes, these will be * expanded and parsed. * * @return true if file could be opened successfully for reading. */ bool open(const std::string& filename, bool locateFileName = true, bool stopAfterFirstFile = true, const std::string &errormessage = "Could not open text file"); void close(); bool next(); std::string nextValue(); // next value inside one line. std::string getRawLine(); std::string getFileName(); /** * @brief new_section is set to true whenever a new [section] starts. If opening * multiple files it is also true whenever a new file is opened. Note: This * applies to only the second and any subsequent file. The first file doesn't * set new_section to true for the first line. */ bool new_section; std::string section; std::string key; std::string val; }; #endif flare-engine-0.19/src/Flare.rc000066400000000000000000000023151224717101500161460ustar00rootroot00000000000000// // The resource header (defines the icon). // #include "resource.h" // // Version information requires inclusion of either or // #include // ------------------------------- // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. IDI_FLARE_APP_ICON ICON "..\\distribution\\Flare.ico" // ------------------------------- // // Version information // VS_VERSION_INFO VERSIONINFO FILEVERSION 0,15,0,0 PRODUCTVERSION 0,15,0,0 BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "Comments", "Flare Alpha\0" VALUE "FileDescription", "Free Libre Action Roleplaying Engine\0" VALUE "FileVersion", "0, 15, 0\0" VALUE "InternalName", "Flare\0" VALUE "LegalCopyright", "Clint Bellanger and Contributors - 2011\0" VALUE "OriginalFilename", "flare.exe\0" VALUE "ProductName", "Flare\0" VALUE "ProductVersion", "0, 15, 0\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x000, 1200 END END flare-engine-0.19/src/FontEngine.cpp000066400000000000000000000173771224717101500173450ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger and Thane Brimhall This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /* * class FontEngine */ #include "CommonIncludes.h" #include "SDL_gfxBlitFunc.h" #include "FontEngine.h" #include "FileParser.h" #include "SharedResources.h" #include "Settings.h" #include "UtilsParsing.h" using namespace std; FontStyle::FontStyle() : name(""), path(""), ptsize(0), blend(true), ttfont(NULL), line_height(0), font_height(0) { } FontEngine::FontEngine() : ttf(NULL) , active_font(NULL) , cursor_y(0) { // Initiate SDL_ttf if(!TTF_WasInit() && TTF_Init()==-1) { printf("TTF_Init: %s\n", TTF_GetError()); exit(2); } // load the fonts FileParser infile; if (infile.open("engine/font_settings.txt")) { while (infile.next()) { infile.val = infile.val + ','; if (infile.new_section) { FontStyle f; f.name = infile.section; font_styles.push_back(f); } if (font_styles.empty()) continue; FontStyle *style = &(font_styles.back()); if ((infile.key == "default" && style->path == "") || infile.key == LANGUAGE) { style->path = eatFirstString(infile.val,','); style->ptsize = eatFirstInt(infile.val,','); int blend = eatFirstInt(infile.val,','); if (blend == 1) style->blend = true; else style->blend = false; style->ttfont = TTF_OpenFont(mods->locate("fonts/" + style->path).c_str(), style->ptsize); if(style->ttfont == NULL) { printf("TTF_OpenFont: %s\n", TTF_GetError()); } else { style->line_height = TTF_FontLineSkip(style->ttfont); style->font_height = TTF_FontLineSkip(style->ttfont); } } } infile.close(); } // set the font colors // RGB values, the last value is 'unused'. For info, // see http://www.libsdl.org/cgi/docwiki.cgi/SDL_Color SDL_Color color; if (infile.open("engine/font_colors.txt")) { while (infile.next()) { infile.val = infile.val + ','; color.r = eatFirstInt(infile.val,','); color.g = eatFirstInt(infile.val,','); color.b = eatFirstInt(infile.val,','); color_map[infile.key] = color; } infile.close(); } // Attempt to set the default active font setFont("font_regular"); if (!active_font) { fprintf(stderr, "Unable to determine default font!\n"); SDL_Quit(); exit(1); } } SDL_Color FontEngine::getColor(string _color) { map::iterator it,end; for (it=color_map.begin(), end=color_map.end(); it!=end; ++it) { if (_color.compare(it->first) == 0) return it->second; } // If all else fails, return white; return FONT_WHITE; } void FontEngine::setFont(string _font) { for (unsigned int i=0; ittfont, text.c_str(), &w, &h); return w; } /** * Using the given wrap width, calculate the width and height necessary to display this text */ Point FontEngine::calc_size(const std::string& text_with_newlines, int width) { char newline = 10; string text = text_with_newlines; // if this contains newlines, recurse size_t check_newline = text.find_first_of(newline); if (check_newline != string::npos) { Point p1 = calc_size(text.substr(0, check_newline), width); Point p2 = calc_size(text.substr(check_newline+1, text.length()), width); Point p3; if (p1.x > p2.x) p3.x = p1.x; else p3.x = p2.x; p3.y = p1.y + p2.y; return p3; } int height = 0; int max_width = 0; string next_word; stringstream builder; stringstream builder_prev; char space = 32; size_t cursor = 0; string fulltext = text + " "; builder.str(""); builder_prev.str(""); next_word = getNextToken(fulltext, cursor, space); while(cursor != string::npos) { builder << next_word; if (calc_width(builder.str()) > width) { // this word can't fit on this line, so word wrap height = height + getLineHeight(); if (calc_width(builder_prev.str()) > max_width) { max_width = calc_width(builder_prev.str()); } builder_prev.str(""); builder.str(""); builder << next_word << " "; } else { builder << " "; builder_prev.str(builder.str()); } next_word = getNextToken(fulltext, cursor, space); // get next word } height = height + getLineHeight(); builder.str(trim(builder.str())); //removes whitespace that shouldn't be included in the size if (calc_width(builder.str()) > max_width) max_width = calc_width(builder.str()); Point size; size.x = max_width; size.y = height; return size; } /** * Render the given text at (x,y) on the target image. * Justify is left, right, or center */ void FontEngine::render(const std::string& text, int x, int y, int justify, SDL_Surface *target, SDL_Color color) { SDL_Rect dest_rect; // calculate actual starting x,y based on justify if (justify == JUSTIFY_LEFT) { dest_rect.x = x; dest_rect.y = y; } else if (justify == JUSTIFY_RIGHT) { dest_rect.x = x - calc_width(text); dest_rect.y = y; } else if (justify == JUSTIFY_CENTER) { dest_rect.x = x - calc_width(text)/2; dest_rect.y = y; } else { printf("ERROR: FontEngine::render() given unhandled 'justify=%d', assuming left\n",justify); dest_rect.x = x; dest_rect.y = y; } // render and blit the text if (active_font->blend && target != screen) { ttf = TTF_RenderUTF8_Blended(active_font->ttfont, text.c_str(), color); // preserve alpha transparency of text buffers if (ttf != NULL) SDL_gfxBlitRGBA(ttf, NULL, target, &dest_rect); } else { ttf = TTF_RenderUTF8_Solid(active_font->ttfont, text.c_str(), color); if (ttf != NULL) SDL_BlitSurface(ttf, NULL, target, &dest_rect); } SDL_FreeSurface(ttf); ttf = NULL; } /** * Word wrap to width */ void FontEngine::render(const std::string& text, int x, int y, int justify, SDL_Surface *target, int width, SDL_Color color) { string fulltext = text + " "; cursor_y = y; string next_word; stringstream builder; stringstream builder_prev; char space = 32; size_t cursor = 0; builder.str(""); builder_prev.str(""); next_word = getNextToken(fulltext, cursor, space); while(cursor != string::npos) { builder << next_word; if (calc_width(builder.str()) > width) { render(builder_prev.str(), x, cursor_y, justify, target, color); cursor_y += getLineHeight(); builder_prev.str(""); builder.str(""); builder << next_word << " "; } else { builder << " "; builder_prev.str(builder.str()); } next_word = getNextToken(fulltext, cursor, space); // next word } render(builder.str(), x, cursor_y, justify, target, color); cursor_y += getLineHeight(); } void FontEngine::renderShadowed(const std::string& text, int x, int y, int justify, SDL_Surface *target, SDL_Color color) { render(text, x+1, y+1, justify, target, FONT_BLACK); render(text, x, y, justify, target, color); } void FontEngine::renderShadowed(const std::string& text, int x, int y, int justify, SDL_Surface *target, int width, SDL_Color color) { render(text, x+1, y+1, justify, target, width, FONT_BLACK); render(text, x, y, justify, target, width, color); } FontEngine::~FontEngine() { SDL_FreeSurface(ttf); for (unsigned int i=0; i const int JUSTIFY_LEFT = 0; const int JUSTIFY_RIGHT = 1; const int JUSTIFY_CENTER = 2; const SDL_Color FONT_WHITE = {255,255,255,0}; const SDL_Color FONT_BLACK = {0,0,0,0}; class FontStyle { public: std::string name; std::string path; int ptsize; bool blend; TTF_Font *ttfont; int line_height; int font_height; FontStyle(); }; /** * class FontEngine * * Handles rendering a bitmap font. */ class FontEngine { private: SDL_Surface *ttf; std::map color_map; std::vector font_styles; FontStyle *active_font; public: FontEngine(); ~FontEngine(); int getLineHeight() { return active_font->line_height; } int getFontHeight() { return active_font->font_height; } SDL_Color getColor(std::string _color); void setFont(std::string _font); int calc_width(const std::string& text); Point calc_size(const std::string& text_with_newlines, int width); void render(const std::string& text, int x, int y, int justify, SDL_Surface *target, SDL_Color color); void render(const std::string& text, int x, int y, int justify, SDL_Surface *target, int width, SDL_Color color); void renderShadowed(const std::string& text, int x, int y, int justify, SDL_Surface *target, SDL_Color color); void renderShadowed(const std::string& text, int x, int y, int justify, SDL_Surface *target, int width, SDL_Color color); int cursor_y; }; #endif flare-engine-0.19/src/GameState.cpp000066400000000000000000000017111224717101500171440ustar00rootroot00000000000000/* Copyright © 2011-2012 kitano This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "GameState.h" GameState::GameState() { requestedGameState = NULL; exitRequested = false; hasMusic = false; reload_music = false; } GameState* GameState::getRequestedGameState() { return requestedGameState; } void GameState::logic() { } void GameState::render() { } GameState::~GameState() { } flare-engine-0.19/src/GameState.h000066400000000000000000000020341224717101500166100ustar00rootroot00000000000000/* Copyright © 2011-2012 kitano This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #pragma once #ifndef GAMESTATE_H #define GAMESTATE_H #include "CommonIncludes.h" class GameState { public: GameState(); virtual ~GameState(); virtual void logic(); virtual void render(); GameState* getRequestedGameState(); bool isExitRequested() { return exitRequested; } bool hasMusic; bool reload_music; protected: GameState* requestedGameState; bool exitRequested; }; #endif flare-engine-0.19/src/GameStateConfig.cpp000066400000000000000000001263261224717101500203040ustar00rootroot00000000000000/* Copyright © 2012 Clint Bellanger Copyright © 2012 davidriod Copyright © 2012 Igor Paliychuk Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * GameStateConfig * * Handle game Settings Menu */ #include "CommonIncludes.h" #include "FileParser.h" #include "GameStateConfig.h" #include "GameStateTitle.h" #include "MenuConfirm.h" #include "Settings.h" #include "SharedResources.h" #include "UtilsFileSystem.h" #include "UtilsParsing.h" #include "WidgetButton.h" #include "WidgetCheckBox.h" #include "WidgetListBox.h" #include "WidgetScrollBox.h" #include "WidgetSlider.h" #include "WidgetTabControl.h" #include "WidgetTooltip.h" using namespace std; bool rescompare(const SDL_Rect &r1, const SDL_Rect &r2) { if (r1.w == r2.w) return r1.h > r2.h; return r1.w > r2.w; } GameStateConfig::GameStateConfig () : GameState() , child_widget() , ok_button(NULL) , defaults_button(NULL) , cancel_button(NULL) , tip_buf() , input_key(0) , check_resolution(true) { background = loadGraphicSurface("images/menus/config.png"); init(); update(); } void GameStateConfig::init() { tip = new WidgetTooltip(); ok_button = new WidgetButton("images/menus/buttons/button_default.png"); defaults_button = new WidgetButton("images/menus/buttons/button_default.png"); cancel_button = new WidgetButton("images/menus/buttons/button_default.png"); ok_button->label = msg->get("OK"); ok_button->pos.x = VIEW_W_HALF - ok_button->pos.w/2; ok_button->pos.y = VIEW_H - (cancel_button->pos.h*3); ok_button->refresh(); defaults_button->label = msg->get("Defaults"); defaults_button->pos.x = VIEW_W_HALF - defaults_button->pos.w/2; defaults_button->pos.y = VIEW_H - (cancel_button->pos.h*2); defaults_button->refresh(); cancel_button->label = msg->get("Cancel"); cancel_button->pos.x = VIEW_W_HALF - cancel_button->pos.w/2; cancel_button->pos.y = VIEW_H - (cancel_button->pos.h); cancel_button->refresh(); mods_total = mods->mod_dirs.size(); // Remove active mods from the available mods list for (unsigned int i = 0; imod_list.size(); i++) { for (unsigned int j = 0; jmod_dirs.size(); j++) { if (mods->mod_list[i] == mods->mod_dirs[j] || FALLBACK_MOD == mods->mod_dirs[j]) mods->mod_dirs[j].erase(); } } fullscreen_cb = new WidgetCheckBox("images/menus/buttons/checkbox_default.png"); fullscreen_lb = new WidgetLabel(); mouse_move_cb = new WidgetCheckBox("images/menus/buttons/checkbox_default.png"); mouse_move_lb = new WidgetLabel(); combat_text_cb = new WidgetCheckBox("images/menus/buttons/checkbox_default.png"); combat_text_lb = new WidgetLabel(); hwsurface_cb = new WidgetCheckBox("images/menus/buttons/checkbox_default.png"); hwsurface_lb = new WidgetLabel(); doublebuf_cb = new WidgetCheckBox("images/menus/buttons/checkbox_default.png"); doublebuf_lb = new WidgetLabel(); enable_joystick_cb = new WidgetCheckBox("images/menus/buttons/checkbox_default.png"); enable_joystick_lb = new WidgetLabel(); texture_quality_cb = new WidgetCheckBox("images/menus/buttons/checkbox_default.png"); texture_quality_lb = new WidgetLabel(); change_gamma_cb = new WidgetCheckBox("images/menus/buttons/checkbox_default.png"); change_gamma_lb = new WidgetLabel(); animated_tiles_cb = new WidgetCheckBox("images/menus/buttons/checkbox_default.png"); animated_tiles_lb = new WidgetLabel(); mouse_aim_cb = new WidgetCheckBox("images/menus/buttons/checkbox_default.png"); mouse_aim_lb = new WidgetLabel(); no_mouse_cb = new WidgetCheckBox("images/menus/buttons/checkbox_default.png"); no_mouse_lb = new WidgetLabel(); show_fps_cb = new WidgetCheckBox("images/menus/buttons/checkbox_default.png"); show_fps_lb = new WidgetLabel(); show_hotkeys_cb = new WidgetCheckBox("images/menus/buttons/checkbox_default.png"); show_hotkeys_lb = new WidgetLabel(); colorblind_cb = new WidgetCheckBox("images/menus/buttons/checkbox_default.png"); colorblind_lb = new WidgetLabel(); music_volume_sl = new WidgetSlider("images/menus/buttons/slider_default.png"); music_volume_lb = new WidgetLabel(); sound_volume_sl = new WidgetSlider("images/menus/buttons/slider_default.png"); sound_volume_lb = new WidgetLabel(); gamma_sl = new WidgetSlider("images/menus/buttons/slider_default.png"); gamma_lb = new WidgetLabel(); resolution_lb = new WidgetLabel(); activemods_lstb = new WidgetListBox(mods_total, 10, "images/menus/buttons/listbox_default.png"); activemods_lb = new WidgetLabel(); inactivemods_lstb = new WidgetListBox(mods_total, 10, "images/menus/buttons/listbox_default.png"); inactivemods_lb = new WidgetLabel(); joystick_device_lstb = new WidgetListBox(SDL_NumJoysticks(), 10, "images/menus/buttons/listbox_default.png"); joystick_device_lb = new WidgetLabel(); language_lb = new WidgetLabel(); hws_note_lb = new WidgetLabel(); dbuf_note_lb = new WidgetLabel(); anim_tiles_note_lb = new WidgetLabel(); test_note_lb = new WidgetLabel(); handheld_note_lb = new WidgetLabel(); activemods_shiftup_btn = new WidgetButton("images/menus/buttons/up.png"); activemods_shiftdown_btn = new WidgetButton("images/menus/buttons/down.png"); activemods_deactivate_btn = new WidgetButton("images/menus/buttons/button_default.png"); inactivemods_activate_btn = new WidgetButton("images/menus/buttons/button_default.png"); joystick_deadzone_sl = new WidgetSlider("images/menus/buttons/slider_default.png"); joystick_deadzone_lb = new WidgetLabel(); tabControl = new WidgetTabControl(6); tabControl->setMainArea(((VIEW_W - FRAME_W)/2)+3, (VIEW_H - FRAME_H)/2, FRAME_W, FRAME_H); frame = tabControl->getContentArea(); // Define the header. tabControl->setTabTitle(0, msg->get("Video")); tabControl->setTabTitle(1, msg->get("Audio")); tabControl->setTabTitle(2, msg->get("Interface")); tabControl->setTabTitle(3, msg->get("Input")); tabControl->setTabTitle(4, msg->get("Keybindings")); tabControl->setTabTitle(5, msg->get("Mods")); tabControl->updateHeader(); input_confirm = new MenuConfirm("",msg->get("Assign: ")); defaults_confirm = new MenuConfirm(msg->get("Defaults"),msg->get("Reset ALL settings?")); resolution_confirm = new MenuConfirm(msg->get("OK"),msg->get("Use this resolution?")); // Allocate KeyBindings for (unsigned int i = 0; i < 29; i++) { settings_lb[i] = new WidgetLabel(); settings_lb[i]->set(inpt->binding_name[i]); settings_lb[i]->setJustify(JUSTIFY_RIGHT); } for (unsigned int i = 0; i < 58; i++) { settings_key[i] = new WidgetButton("images/menus/buttons/button_default.png"); } // Allocate resolution list box int resolutions = getVideoModes(); if (resolutions < 1) fprintf(stderr, "Unable to get resolutions list!\n"); resolution_lstb = new WidgetListBox(resolutions, 10, "images/menus/buttons/listbox_default.png"); resolution_lstb->can_deselect = false; // Allocate Languages ListBox int langCount = getLanguagesNumber(); language_ISO = std::vector(); language_full = std::vector(); language_ISO.resize(langCount); language_full.resize(langCount); language_lstb = new WidgetListBox(langCount, 10, "images/menus/buttons/listbox_default.png"); language_lstb->can_deselect = false; readConfig(); // Finish Mods ListBoxes setup activemods_lstb->multi_select = true; for (unsigned int i = 0; i < mods->mod_list.size() ; i++) { if (mods->mod_list[i] != FALLBACK_MOD) activemods_lstb->append(mods->mod_list[i],""); } child_widget.push_back(activemods_lstb); optiontab[child_widget.size()-1] = 5; inactivemods_lstb->multi_select = true; for (unsigned int i = 0; i < mods->mod_dirs.size(); i++) { inactivemods_lstb->append(mods->mod_dirs[i],""); } child_widget.push_back(inactivemods_lstb); optiontab[child_widget.size()-1] = 5; // Save the current resolution in case we want to revert back to it old_view_w = VIEW_W; old_view_h = VIEW_H; resolution_confirm_ticks = 0; input_confirm_ticks = 0; // Set up tab list tablist.add(ok_button); tablist.add(defaults_button); tablist.add(cancel_button); tablist.add(fullscreen_cb); tablist.add(hwsurface_cb); tablist.add(doublebuf_cb); tablist.add(change_gamma_cb); tablist.add(gamma_sl); tablist.add(texture_quality_cb); tablist.add(animated_tiles_cb); tablist.add(resolution_lstb); tablist.add(music_volume_sl); tablist.add(sound_volume_sl); tablist.add(combat_text_cb); tablist.add(show_fps_cb); tablist.add(show_hotkeys_cb); tablist.add(colorblind_cb); tablist.add(language_lstb); tablist.add(enable_joystick_cb); tablist.add(mouse_move_cb); tablist.add(mouse_aim_cb); tablist.add(no_mouse_cb); tablist.add(joystick_deadzone_sl); tablist.add(joystick_device_lstb); tablist.add(input_scrollbox); tablist.add(inactivemods_lstb); tablist.add(activemods_lstb); tablist.add(inactivemods_activate_btn); tablist.add(activemods_deactivate_btn); tablist.add(activemods_shiftup_btn); tablist.add(activemods_shiftdown_btn); for (unsigned int i = 0; i < 58; i++) { input_scrollbox->addChildWidget(settings_key[i]); } } void GameStateConfig::readConfig () { //Load the menu configuration from file int offset_x = 0; int offset_y = 0; FileParser infile; if (infile.open("menus/config.txt")) { while (infile.next()) { infile.val = infile.val + ','; int x1 = eatFirstInt(infile.val, ','); int y1 = eatFirstInt(infile.val, ','); int x2 = eatFirstInt(infile.val, ','); int y2 = eatFirstInt(infile.val, ','); int setting_num = -1; if (infile.key == "listbox_scrollbar_offset") { activemods_lstb->scrollbar_offset = x1; inactivemods_lstb->scrollbar_offset = x1; joystick_device_lstb->scrollbar_offset = x1; resolution_lstb->scrollbar_offset = x1; language_lstb->scrollbar_offset = x1; } //checkboxes else if (infile.key == "fullscreen") { placeLabeledCheckbox( fullscreen_lb, fullscreen_cb, x1, y1, x2, y2, msg->get("Full Screen Mode"), 0); } else if (infile.key == "mouse_move") { placeLabeledCheckbox( mouse_move_lb, mouse_move_cb, x1, y1, x2, y2, msg->get("Move hero using mouse"), 3); } else if (infile.key == "combat_text") { placeLabeledCheckbox( combat_text_lb, combat_text_cb, x1, y1, x2, y2, msg->get("Show combat text"), 2); } else if (infile.key == "hwsurface") { placeLabeledCheckbox( hwsurface_lb, hwsurface_cb, x1, y1, x2, y2, msg->get("Hardware surfaces"), 0); } else if (infile.key == "doublebuf") { placeLabeledCheckbox( doublebuf_lb, doublebuf_cb, x1, y1, x2, y2, msg->get("Double buffering"), 0); } else if (infile.key == "enable_joystick") { placeLabeledCheckbox( enable_joystick_lb, enable_joystick_cb, x1, y1, x2, y2, msg->get("Use joystick"), 3); } else if (infile.key == "texture_quality") { placeLabeledCheckbox( texture_quality_lb, texture_quality_cb, x1, y1, x2, y2, msg->get("High Quality Textures"), 0); } else if (infile.key == "change_gamma") { placeLabeledCheckbox( change_gamma_lb, change_gamma_cb, x1, y1, x2, y2, msg->get("Allow changing gamma"), 0); } else if (infile.key == "animated_tiles") { placeLabeledCheckbox( animated_tiles_lb, animated_tiles_cb, x1, y1, x2, y2, msg->get("Animated tiles"), 0); } else if (infile.key == "mouse_aim") { placeLabeledCheckbox( mouse_aim_lb, mouse_aim_cb, x1, y1, x2, y2, msg->get("Mouse aim"), 3); } else if (infile.key == "no_mouse") { placeLabeledCheckbox( no_mouse_lb, no_mouse_cb, x1, y1, x2, y2, msg->get("Do not use mouse"), 3); } else if (infile.key == "show_fps") { placeLabeledCheckbox( show_fps_lb, show_fps_cb, x1, y1, x2, y2, msg->get("Show FPS"), 2); } else if (infile.key == "show_hotkeys") { placeLabeledCheckbox( show_hotkeys_lb, show_hotkeys_cb, x1, y1, x2, y2, msg->get("Show Hotkeys Labels"), 2); } else if (infile.key == "colorblind") { placeLabeledCheckbox( colorblind_lb, colorblind_cb, x1, y1, x2, y2, msg->get("Colorblind Mode"), 2); } //sliders else if (infile.key == "music_volume") { music_volume_sl->pos.x = frame.x + x2; music_volume_sl->pos.y = frame.y + y2; child_widget.push_back(music_volume_sl); optiontab[child_widget.size()-1] = 1; music_volume_lb->setX(frame.x + x1); music_volume_lb->setY(frame.y + y1); music_volume_lb->set(msg->get("Music Volume")); music_volume_lb->setJustify(JUSTIFY_RIGHT); child_widget.push_back(music_volume_lb); optiontab[child_widget.size()-1] = 1; } else if (infile.key == "sound_volume") { sound_volume_sl->pos.x = frame.x + x2; sound_volume_sl->pos.y = frame.y + y2; child_widget.push_back(sound_volume_sl); optiontab[child_widget.size()-1] = 1; sound_volume_lb->setX(frame.x + x1); sound_volume_lb->setY(frame.y + y1); sound_volume_lb->set(msg->get("Sound Volume")); sound_volume_lb->setJustify(JUSTIFY_RIGHT); child_widget.push_back(sound_volume_lb); optiontab[child_widget.size()-1] = 1; } else if (infile.key == "gamma") { gamma_sl->pos.x = frame.x + x2; gamma_sl->pos.y = frame.y + y2; child_widget.push_back(gamma_sl); optiontab[child_widget.size()-1] = 0; gamma_lb->setX(frame.x + x1); gamma_lb->setY(frame.y + y1); gamma_lb->set(msg->get("Gamma")); gamma_lb->setJustify(JUSTIFY_RIGHT); child_widget.push_back(gamma_lb); optiontab[child_widget.size()-1] = 0; } else if (infile.key == "joystick_deadzone") { joystick_deadzone_sl->pos.x = frame.x + x2; joystick_deadzone_sl->pos.y = frame.y + y2; child_widget.push_back(joystick_deadzone_sl); optiontab[child_widget.size()-1] = 3; joystick_deadzone_lb->setX(frame.x + x1); joystick_deadzone_lb->setY(frame.y + y1); joystick_deadzone_lb->set(msg->get("Joystick Deadzone")); joystick_deadzone_lb->setJustify(JUSTIFY_RIGHT); child_widget.push_back(joystick_deadzone_lb); optiontab[child_widget.size()-1] = 3; } //listboxes else if (infile.key == "resolution") { resolution_lstb->pos.x = frame.x + x2; resolution_lstb->pos.y = frame.y + y2; child_widget.push_back(resolution_lstb); optiontab[child_widget.size()-1] = 0; resolution_lb->setX(frame.x + x1); resolution_lb->setY(frame.y + y1); resolution_lb->set(msg->get("Resolution")); child_widget.push_back(resolution_lb); optiontab[child_widget.size()-1] = 0; } else if (infile.key == "activemods") { activemods_lstb->pos.x = frame.x + x2; activemods_lstb->pos.y = frame.y + y2; activemods_lb->setX(frame.x + x1); activemods_lb->setY(frame.y + y1); activemods_lb->set(msg->get("Active Mods")); child_widget.push_back(activemods_lb); optiontab[child_widget.size()-1] = 5; } else if (infile.key == "inactivemods") { inactivemods_lstb->pos.x = frame.x + x2; inactivemods_lstb->pos.y = frame.y + y2; inactivemods_lb->setX(frame.x + x1); inactivemods_lb->setY(frame.y + y1); inactivemods_lb->set(msg->get("Available Mods")); child_widget.push_back(inactivemods_lb); optiontab[child_widget.size()-1] = 5; } else if (infile.key == "joystick_device") { joystick_device_lstb->pos.x = frame.x + x2; joystick_device_lstb->pos.y = frame.y + y2; for(int i = 0; i < SDL_NumJoysticks(); i++) { if (SDL_JoystickName(i) != NULL) joystick_device_lstb->append(SDL_JoystickName(i),SDL_JoystickName(i)); } child_widget.push_back(joystick_device_lstb); optiontab[child_widget.size()-1] = 3; joystick_device_lb->setX(frame.x + x1); joystick_device_lb->setY(frame.y + y1); joystick_device_lb->set(msg->get("Joystick")); child_widget.push_back(joystick_device_lb); optiontab[child_widget.size()-1] = 3; } else if (infile.key == "language") { language_lstb->pos.x = frame.x + x2; language_lstb->pos.y = frame.y + y2; child_widget.push_back(language_lstb); optiontab[child_widget.size()-1] = 2; language_lb->setX(frame.x + x1); language_lb->setY(frame.y + y1); language_lb->set(msg->get("Language")); child_widget.push_back(language_lb); optiontab[child_widget.size()-1] = 2; } // buttons begin else if (infile.key == "cancel") setting_num = CANCEL; else if (infile.key == "accept") setting_num = ACCEPT; else if (infile.key == "up") setting_num = UP; else if (infile.key == "down") setting_num = DOWN; else if (infile.key == "left") setting_num = LEFT; else if (infile.key == "right") setting_num = RIGHT; else if (infile.key == "bar1") setting_num = BAR_1; else if (infile.key == "bar2") setting_num = BAR_2; else if (infile.key == "bar3") setting_num = BAR_3; else if (infile.key == "bar4") setting_num = BAR_4; else if (infile.key == "bar5") setting_num = BAR_5; else if (infile.key == "bar6") setting_num = BAR_6; else if (infile.key == "bar7") setting_num = BAR_7; else if (infile.key == "bar8") setting_num = BAR_8; else if (infile.key == "bar9") setting_num = BAR_9; else if (infile.key == "bar0") setting_num = BAR_0; else if (infile.key == "main1") setting_num = MAIN1; else if (infile.key == "main2") setting_num = MAIN2; else if (infile.key == "character") setting_num = CHARACTER; else if (infile.key == "inventory") setting_num = INVENTORY; else if (infile.key == "powers") setting_num = POWERS; else if (infile.key == "log") setting_num = LOG; else if (infile.key == "ctrl") setting_num = CTRL; else if (infile.key == "shift") setting_num = SHIFT; else if (infile.key == "delete") setting_num = DEL; else if (infile.key == "actionbar") setting_num = ACTIONBAR; else if (infile.key == "actionbar_back") setting_num = ACTIONBAR_BACK; else if (infile.key == "actionbar_forward") setting_num = ACTIONBAR_FORWARD; else if (infile.key == "actionbar_use") setting_num = ACTIONBAR_USE; // buttons end else if (infile.key == "hws_note") { hws_note_lb->setX(frame.x + x1); hws_note_lb->setY(frame.y + y1); hws_note_lb->set(msg->get("Disable for performance")); child_widget.push_back(hws_note_lb); optiontab[child_widget.size()-1] = 0; } else if (infile.key == "dbuf_note") { dbuf_note_lb->setX(frame.x + x1); dbuf_note_lb->setY(frame.y + y1); dbuf_note_lb->set(msg->get("Disable for performance")); child_widget.push_back(dbuf_note_lb); optiontab[child_widget.size()-1] = 0; } else if (infile.key == "anim_tiles_note") { anim_tiles_note_lb->setX(frame.x + x1); anim_tiles_note_lb->setY(frame.y + y1); anim_tiles_note_lb->set(msg->get("Disable for performance")); child_widget.push_back(anim_tiles_note_lb); optiontab[child_widget.size()-1] = 0; } else if (infile.key == "test_note") { test_note_lb->setX(frame.x + x1); test_note_lb->setY(frame.y + y1); test_note_lb->set(msg->get("Experimental")); child_widget.push_back(test_note_lb); optiontab[child_widget.size()-1] = 0; } else if (infile.key == "handheld_note") { handheld_note_lb->setX(frame.x + x1); handheld_note_lb->setY(frame.y + y1); handheld_note_lb->set(msg->get("For handheld devices")); child_widget.push_back(handheld_note_lb); optiontab[child_widget.size()-1] = 3; } //buttons else if (infile.key == "activemods_shiftup") { activemods_shiftup_btn->pos.x = frame.x + x1; activemods_shiftup_btn->pos.y = frame.y + y1; activemods_shiftup_btn->refresh(); child_widget.push_back(activemods_shiftup_btn); optiontab[child_widget.size()-1] = 5; } else if (infile.key == "activemods_shiftdown") { activemods_shiftdown_btn->pos.x = frame.x + x1; activemods_shiftdown_btn->pos.y = frame.y + y1; activemods_shiftdown_btn->refresh(); child_widget.push_back(activemods_shiftdown_btn); optiontab[child_widget.size()-1] = 5; } else if (infile.key == "activemods_deactivate") { activemods_deactivate_btn->label = msg->get("<< Disable"); activemods_deactivate_btn->pos.x = frame.x + x1; activemods_deactivate_btn->pos.y = frame.y + y1; activemods_deactivate_btn->refresh(); child_widget.push_back(activemods_deactivate_btn); optiontab[child_widget.size()-1] = 5; } else if (infile.key == "inactivemods_activate") { inactivemods_activate_btn->label = msg->get("Enable >>"); inactivemods_activate_btn->pos.x = frame.x + x1; inactivemods_activate_btn->pos.y = frame.y + y1; inactivemods_activate_btn->refresh(); child_widget.push_back(inactivemods_activate_btn); optiontab[child_widget.size()-1] = 5; } else if (infile.key == "secondary_offset") { offset_x = x1; offset_y = y1; } else if (infile.key == "keybinds_bg_color") { // background color for keybinds scrollbox scrollpane_color.r = x1; scrollpane_color.g = y1; scrollpane_color.b = x2; } else if (infile.key == "scrollpane") { scrollpane.x = x1; scrollpane.y = y1; scrollpane.w = x2; scrollpane.h = y2; } else if (infile.key == "scrollpane_contents") { scrollpane_contents = x1; } if (setting_num > -1 && setting_num < 29) { //keybindings settings_lb[setting_num]->setX(x1); settings_lb[setting_num]->setY(y1); settings_key[setting_num]->pos.x = x2; settings_key[setting_num]->pos.y = y2; } } infile.close(); } // Load the MenuConfirm positions and alignments from menus/menus.txt if (infile.open("menus/menus.txt")) { int menu_index = -1; while (infile.next()) { if (infile.key == "id") { if (infile.val == "confirm") menu_index = 0; else menu_index = -1; } if (menu_index == -1) continue; if (infile.key == "layout") { infile.val = infile.val + ','; menuConfirm_area.x = eatFirstInt(infile.val, ','); menuConfirm_area.y = eatFirstInt(infile.val, ','); menuConfirm_area.w = eatFirstInt(infile.val, ','); menuConfirm_area.h = eatFirstInt(infile.val, ','); } if (infile.key == "align") { menuConfirm_align = infile.val; } } infile.close(); } defaults_confirm->window_area = menuConfirm_area; defaults_confirm->alignment = menuConfirm_align; defaults_confirm->align(); defaults_confirm->update(); resolution_confirm->window_area = menuConfirm_area; resolution_confirm->alignment = menuConfirm_align; resolution_confirm->align(); resolution_confirm->update(); // Allocate KeyBindings ScrollBox input_scrollbox = new WidgetScrollBox(scrollpane.w, scrollpane.h); input_scrollbox->pos.x = scrollpane.x + frame.x; input_scrollbox->pos.y = scrollpane.y + frame.y; input_scrollbox->bg.r = scrollpane_color.r; input_scrollbox->bg.g = scrollpane_color.g; input_scrollbox->bg.b = scrollpane_color.b; input_scrollbox->transparent = false; input_scrollbox->resize(scrollpane_contents); // Set positions of secondary key bindings for (unsigned int i = 29; i < 58; i++) { settings_key[i]->pos.x = settings_key[i-29]->pos.x + offset_x; settings_key[i]->pos.y = settings_key[i-29]->pos.y + offset_y; } } void GameStateConfig::update () { if (FULLSCREEN) fullscreen_cb->Check(); else fullscreen_cb->unCheck(); if (AUDIO) { music_volume_sl->set(0,128,MUSIC_VOLUME); Mix_VolumeMusic(MUSIC_VOLUME); sound_volume_sl->set(0,128,SOUND_VOLUME); Mix_Volume(-1, SOUND_VOLUME); } else { music_volume_sl->set(0,128,0); sound_volume_sl->set(0,128,0); } if (MOUSE_MOVE) mouse_move_cb->Check(); else mouse_move_cb->unCheck(); if (COMBAT_TEXT) combat_text_cb->Check(); else combat_text_cb->unCheck(); if (HWSURFACE) hwsurface_cb->Check(); else hwsurface_cb->unCheck(); if (DOUBLEBUF) doublebuf_cb->Check(); else doublebuf_cb->unCheck(); if (ENABLE_JOYSTICK) enable_joystick_cb->Check(); else enable_joystick_cb->unCheck(); if (TEXTURE_QUALITY) texture_quality_cb->Check(); else texture_quality_cb->unCheck(); if (CHANGE_GAMMA) change_gamma_cb->Check(); else { change_gamma_cb->unCheck(); GAMMA = 1.0; gamma_sl->enabled = false; } gamma_sl->set(5,20,(int)(GAMMA*10.0)); SDL_SetGamma(GAMMA,GAMMA,GAMMA); if (ANIMATED_TILES) animated_tiles_cb->Check(); else animated_tiles_cb->unCheck(); if (MOUSE_AIM) mouse_aim_cb->Check(); else mouse_aim_cb->unCheck(); if (NO_MOUSE) no_mouse_cb->Check(); else no_mouse_cb->unCheck(); if (SHOW_FPS) show_fps_cb->Check(); else show_fps_cb->unCheck(); if (SHOW_HOTKEYS) show_hotkeys_cb->Check(); else show_hotkeys_cb->unCheck(); if (COLORBLIND) colorblind_cb->Check(); else colorblind_cb->unCheck(); std::stringstream list_mode; unsigned int resolutions = getVideoModes(); for (unsigned int i=0; iappend(list_mode.str(),""); if (video_modes[i].w == VIEW_W && video_modes[i].h == VIEW_H) resolution_lstb->selected[i] = true; else resolution_lstb->selected[i] = false; list_mode.str(""); } resolution_lstb->refresh(); SDL_Init(SDL_INIT_JOYSTICK); if (ENABLE_JOYSTICK && SDL_NumJoysticks() > 0) { SDL_JoystickClose(joy); joy = SDL_JoystickOpen(JOYSTICK_DEVICE); joystick_device_lstb->selected[JOYSTICK_DEVICE] = true; } joystick_device_lstb->refresh(); joystick_deadzone_sl->set(0,32768,JOY_DEADZONE); if (!getLanguagesList()) fprintf(stderr, "Unable to get languages list!\n"); for (int i=0; i < getLanguagesNumber(); i++) { language_lstb->append(language_full[i],""); if (language_ISO[i] == LANGUAGE) language_lstb->selected[i] = true; } language_lstb->refresh(); activemods_lstb->refresh(); inactivemods_lstb->refresh(); for (unsigned int i = 0; i < 29; i++) { if (inpt->binding[i] < 8) { settings_key[i]->label = inpt->mouse_button[inpt->binding[i]-1]; } else { settings_key[i]->label = SDL_GetKeyName((SDLKey)inpt->binding[i]); } settings_key[i]->refresh(); } for (unsigned int i = 29; i < 58; i++) { if (inpt->binding_alt[i-29] < 8) { settings_key[i]->label = inpt->mouse_button[inpt->binding_alt[i-29]-1]; } else { settings_key[i]->label = SDL_GetKeyName((SDLKey)inpt->binding_alt[i-29]); } settings_key[i]->refresh(); } input_scrollbox->refresh(); } void GameStateConfig::logic () { for (unsigned int i = 0; i < child_widget.size(); i++) { if (input_scrollbox->in_focus && !input_confirm->visible) { tabControl->setActiveTab(4); break; } else if (child_widget[i]->in_focus) { tabControl->setActiveTab(optiontab[i]); break; } } check_resolution = true; std::string resolution_value; resolution_value = resolution_lstb->getValue() + 'x'; // add x to have last element readable int width = eatFirstInt(resolution_value, 'x'); int height = eatFirstInt(resolution_value, 'x'); // In case of a custom resolution, the listbox might have nothing selected // So we just use whatever the current view area is if (width == 0 || height == 0) { width = VIEW_W; height = VIEW_H; } if (defaults_confirm->visible) { defaults_confirm->logic(); if (defaults_confirm->confirmClicked) { check_resolution = false; FULLSCREEN = 0; loadDefaults(); loadMiscSettings(); inpt->defaultQwertyKeyBindings(); inpt->defaultJoystickBindings(); delete msg; msg = new MessageEngine(); update(); defaults_confirm->visible = false; defaults_confirm->confirmClicked = false; } } if (resolution_confirm->visible || resolution_confirm->cancelClicked) { resolution_confirm->logic(); resolution_confirm_ticks--; if (resolution_confirm->confirmClicked) { saveSettings(); delete requestedGameState; requestedGameState = new GameStateTitle(); } else if (resolution_confirm->cancelClicked || resolution_confirm_ticks == 0) { applyVideoSettings(old_view_w, old_view_h); saveSettings(); delete requestedGameState; requestedGameState = new GameStateConfig(); } } if (!input_confirm->visible && !defaults_confirm->visible && !resolution_confirm->visible) { tabControl->logic(); tablist.logic(); // Ok/Cancel Buttons if (ok_button->checkClick()) { inpt->saveKeyBindings(); inpt->setKeybindNames(); if (setMods()) { reload_music = true; delete mods; mods = new ModManager(); loadTilesetSettings(); } loadMiscSettings(); refreshFont(); if ((ENABLE_JOYSTICK) && (SDL_NumJoysticks() > 0)) { SDL_JoystickClose(joy); joy = SDL_JoystickOpen(JOYSTICK_DEVICE); } applyVideoSettings(width, height); if (width != old_view_w || height != old_view_h) { resolution_confirm->window_area = menuConfirm_area; resolution_confirm->align(); resolution_confirm->update(); resolution_confirm_ticks = MAX_FRAMES_PER_SEC * 10; // 10 seconds } else { saveSettings(); delete requestedGameState; requestedGameState = new GameStateTitle(); } } else if (defaults_button->checkClick()) { defaults_confirm->visible = true; } else if (cancel_button->checkClick() || (inpt->pressing[CANCEL] && !inpt->lock[CANCEL])) { inpt->lock[CANCEL] = true; check_resolution = false; loadSettings(); loadMiscSettings(); inpt->loadKeyBindings(); delete msg; msg = new MessageEngine(); update(); delete requestedGameState; requestedGameState = new GameStateTitle(); } } int active_tab = tabControl->getActiveTab(); // tab 0 (video) if (active_tab == 0 && !defaults_confirm->visible) { if (fullscreen_cb->checkClick()) { if (fullscreen_cb->isChecked()) FULLSCREEN=true; else FULLSCREEN=false; } else if (hwsurface_cb->checkClick()) { if (hwsurface_cb->isChecked()) HWSURFACE=true; else HWSURFACE=false; } else if (doublebuf_cb->checkClick()) { if (doublebuf_cb->isChecked()) DOUBLEBUF=true; else DOUBLEBUF=false; } else if (texture_quality_cb->checkClick()) { if (texture_quality_cb->isChecked()) TEXTURE_QUALITY=true; else TEXTURE_QUALITY=false; } else if (change_gamma_cb->checkClick()) { if (change_gamma_cb->isChecked()) { CHANGE_GAMMA=true; gamma_sl->enabled = true; } else { CHANGE_GAMMA=false; GAMMA = 1.0; gamma_sl->enabled = false; gamma_sl->set(5,20,(int)(GAMMA*10.0)); SDL_SetGamma(GAMMA,GAMMA,GAMMA); } } else if (animated_tiles_cb->checkClick()) { if (animated_tiles_cb->isChecked()) ANIMATED_TILES=true; else ANIMATED_TILES=false; } else if (resolution_lstb->checkClick()) { ; // nothing to do here: resolution value changes next frame. } else if (CHANGE_GAMMA) { gamma_sl->enabled = true; if (gamma_sl->checkClick()) { GAMMA=(gamma_sl->getValue())*0.1f; SDL_SetGamma(GAMMA,GAMMA,GAMMA); } } } // tab 1 (audio) else if (active_tab == 1 && !defaults_confirm->visible) { if (AUDIO) { if (music_volume_sl->checkClick()) { if (MUSIC_VOLUME == 0) reload_music = true; MUSIC_VOLUME=music_volume_sl->getValue(); Mix_VolumeMusic(MUSIC_VOLUME); } else if (sound_volume_sl->checkClick()) { SOUND_VOLUME=sound_volume_sl->getValue(); Mix_Volume(-1, SOUND_VOLUME); } } } // tab 2 (interface) else if (active_tab == 2 && !defaults_confirm->visible) { if (combat_text_cb->checkClick()) { if (combat_text_cb->isChecked()) COMBAT_TEXT=true; else COMBAT_TEXT=false; } else if (language_lstb->checkClick()) { LANGUAGE = language_ISO[language_lstb->getSelected()]; delete msg; msg = new MessageEngine(); } else if (show_fps_cb->checkClick()) { if (show_fps_cb->isChecked()) SHOW_FPS=true; else SHOW_FPS=false; } else if (show_hotkeys_cb->checkClick()) { if (show_hotkeys_cb->isChecked()) SHOW_HOTKEYS=true; else SHOW_HOTKEYS=false; } else if (colorblind_cb->checkClick()) { if (colorblind_cb->isChecked()) COLORBLIND=true; else COLORBLIND=false; } } // tab 3 (input) else if (active_tab == 3 && !defaults_confirm->visible) { if (mouse_move_cb->checkClick()) { if (mouse_move_cb->isChecked()) { MOUSE_MOVE=true; no_mouse_cb->unCheck(); NO_MOUSE=false; } else MOUSE_MOVE=false; } else if (mouse_aim_cb->checkClick()) { if (mouse_aim_cb->isChecked()) { MOUSE_AIM=true; no_mouse_cb->unCheck(); NO_MOUSE=false; } else MOUSE_AIM=false; } else if (no_mouse_cb->checkClick()) { if (no_mouse_cb->isChecked()) { NO_MOUSE=true; mouse_aim_cb->unCheck(); MOUSE_AIM=false; mouse_move_cb->unCheck(); MOUSE_MOVE=false; } else NO_MOUSE=false; } else if (enable_joystick_cb->checkClick()) { if (enable_joystick_cb->isChecked()) { ENABLE_JOYSTICK=true; if (SDL_NumJoysticks() > 0) { JOYSTICK_DEVICE = 0; SDL_JoystickClose(joy); joy = SDL_JoystickOpen(JOYSTICK_DEVICE); joystick_device_lstb->selected[JOYSTICK_DEVICE] = true; } } else { ENABLE_JOYSTICK=false; for (int i=0; igetSize(); i++) joystick_device_lstb->selected[i] = false; } if (SDL_NumJoysticks() > 0) joystick_device_lstb->refresh(); } else if (joystick_deadzone_sl->checkClick()) { JOY_DEADZONE = joystick_deadzone_sl->getValue(); } else if (joystick_device_lstb->checkClick()) { JOYSTICK_DEVICE = joystick_device_lstb->getSelected(); if (JOYSTICK_DEVICE != -1) { enable_joystick_cb->Check(); ENABLE_JOYSTICK=true; if (SDL_NumJoysticks() > 0) { SDL_JoystickClose(joy); joy = SDL_JoystickOpen(JOYSTICK_DEVICE); } } else { enable_joystick_cb->unCheck(); ENABLE_JOYSTICK = false; } } } // tab 4 (keybindings) else if (active_tab == 4 && !defaults_confirm->visible) { if (input_confirm->visible) { input_confirm->logic(); scanKey(input_key); input_confirm_ticks--; if (input_confirm_ticks == 0) input_confirm->visible = false; } else { input_scrollbox->logic(); for (unsigned int i = 0; i < 58; i++) { if (settings_key[i]->pressed || settings_key[i]->hover) input_scrollbox->update = true; Point mouse = input_scrollbox->input_assist(inpt->mouse); if (settings_key[i]->checkClick(mouse.x,mouse.y)) { std::string confirm_msg; if (i < 29) confirm_msg = msg->get("Assign: ") + inpt->binding_name[i]; else confirm_msg = msg->get("Assign: ") + inpt->binding_name[i-29]; delete input_confirm; input_confirm = new MenuConfirm("",confirm_msg); input_confirm->window_area = menuConfirm_area; input_confirm->alignment = menuConfirm_align; input_confirm->align(); input_confirm->update(); input_confirm_ticks = MAX_FRAMES_PER_SEC * 10; // 10 seconds input_confirm->visible = true; input_key = i; inpt->last_button = -1; inpt->last_key = -1; } } } } // tab 5 (mods) else if (active_tab == 5 && !defaults_confirm->visible) { if (activemods_lstb->checkClick()) { //do nothing } else if (inactivemods_lstb->checkClick()) { //do nothing } else if (activemods_shiftup_btn->checkClick()) { activemods_lstb->shiftUp(); } else if (activemods_shiftdown_btn->checkClick()) { activemods_lstb->shiftDown(); } else if (activemods_deactivate_btn->checkClick()) { disableMods(); } else if (inactivemods_activate_btn->checkClick()) { enableMods(); } } } void GameStateConfig::render () { if (resolution_confirm->visible) { resolution_confirm->render(); return; } int tabheight = tabControl->getTabHeight(); SDL_Rect pos; pos.x = (VIEW_W-FRAME_W)/2; pos.y = (VIEW_H-FRAME_H)/2 + tabheight - tabheight/16; SDL_BlitSurface(background,NULL,screen,&pos); tabControl->render(); // render OK/Defaults/Cancel buttons ok_button->render(); cancel_button->render(); defaults_button->render(); int active_tab = tabControl->getActiveTab(); // render keybindings tab if (active_tab == 4) { if (input_scrollbox->update) { input_scrollbox->refresh(); for (unsigned int i = 0; i < 29; i++) { settings_lb[i]->render(input_scrollbox->contents); } } input_scrollbox->render(); } for (unsigned int i = 0; i < child_widget.size(); i++) { if (optiontab[i] == active_tab) child_widget[i]->render(); } if (input_confirm->visible) input_confirm->render(); if (defaults_confirm->visible) defaults_confirm->render(); // Get tooltips for listboxes // This isn't very elegant right now // In the future, we'll want to get tooltips for all widget types TooltipData tip_new; if (active_tab == 0 && tip_new.isEmpty()) tip_new = resolution_lstb->checkTooltip(inpt->mouse); if (active_tab == 2 && tip_new.isEmpty()) tip_new = language_lstb->checkTooltip(inpt->mouse); if (active_tab == 3 && tip_new.isEmpty()) tip_new = joystick_device_lstb->checkTooltip(inpt->mouse); if (active_tab == 5 && tip_new.isEmpty()) tip_new = activemods_lstb->checkTooltip(inpt->mouse); if (active_tab == 5 && tip_new.isEmpty()) tip_new = inactivemods_lstb->checkTooltip(inpt->mouse); if (!tip_new.isEmpty()) { if (!tip_new.compare(&tip_buf)) { tip_buf.clear(); tip_buf = tip_new; } tip->render(tip_buf, inpt->mouse, STYLE_FLOAT); } } int GameStateConfig::getVideoModes() { video_modes.clear(); // Set predefined modes const unsigned int cm_count = 5; SDL_Rect common_modes[cm_count]; common_modes[0].w = 640; common_modes[0].h = 480; common_modes[1].w = 800; common_modes[1].h = 600; common_modes[2].w = 1024; common_modes[2].h = 768; common_modes[3].w = VIEW_W; common_modes[3].h = VIEW_H; common_modes[4].w = MIN_VIEW_W; common_modes[4].h = MIN_VIEW_H; // Get available fullscreen/hardware modes SDL_Rect** detect_modes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE); // Check if there are any modes available if (detect_modes == (SDL_Rect**)0) { fprintf(stderr, "No modes available!\n"); return 0; } // Check if our resolution is restricted if (detect_modes == (SDL_Rect**)-1) { fprintf(stderr, "All resolutions available.\n"); } for (unsigned i=0; detect_modes[i]; ++i) { video_modes.push_back(*detect_modes[i]); if (detect_modes[i]->w < MIN_VIEW_W || detect_modes[i]->h < MIN_VIEW_H) { // make sure the resolution fits in the constraints of MIN_VIEW_W and MIN_VIEW_H video_modes.pop_back(); } else { // check previous resolutions for duplicates. If one is found, drop the one we just added for (unsigned j=0; jw && video_modes[j].h == detect_modes[i]->h) { video_modes.pop_back(); break; } } } } for (unsigned i=0; i width && MIN_VIEW_H > height) { fprintf (stderr, "A mod is requiring a minimum resolution of %dx%d\n", MIN_VIEW_W, MIN_VIEW_H); if (width < MIN_VIEW_W) width = MIN_VIEW_W; if (height < MIN_VIEW_H) height = MIN_VIEW_H; } // Attempt to apply the new settings setupSDLVideoMode(width, height); // If the new settings fail, revert to the old ones if (!screen) { fprintf (stderr, "Error during SDL_SetVideoMode: %s\n", SDL_GetError()); setupSDLVideoMode(VIEW_W, VIEW_H); return false; } else { // If the new settings succeed, adjust the view area VIEW_W = width; VIEW_W_HALF = width/2; VIEW_H = height; VIEW_H_HALF = height/2; resolution_confirm->visible = true; return true; } } /** * Activate mods */ void GameStateConfig::enableMods() { for (int i=0; igetSize(); i++) { if (inactivemods_lstb->selected[i]) { activemods_lstb->append(inactivemods_lstb->getValue(i),inactivemods_lstb->getTooltip(i)); inactivemods_lstb->remove(i); i--; } } } /** * Deactivate mods */ void GameStateConfig::disableMods() { for (int i=0; igetSize(); i++) { if (activemods_lstb->selected[i] && activemods_lstb->getValue(i) != FALLBACK_MOD) { inactivemods_lstb->append(activemods_lstb->getValue(i),activemods_lstb->getTooltip(i)); activemods_lstb->remove(i); i--; } } } /** * Save new mods list. Return true if modlist was changed. Else return false */ bool GameStateConfig::setMods() { vector temp_list = mods->mod_list; mods->mod_list.clear(); for (int i=0; igetSize(); i++) { if (activemods_lstb->getValue(i) != "") mods->mod_list.push_back(activemods_lstb->getValue(i)); } ofstream outfile; outfile.open((PATH_CONF + "mods.txt").c_str(), ios::out); if (outfile.is_open()) { outfile<<"# Mods lower on the list will overwrite data in the entries higher on the list"<<"\n"; outfile<<"\n"; for (unsigned int i = 0; i < mods->mod_list.size(); i++) { outfile<mod_list[i]<<"\n"; } } if (outfile.bad()) fprintf(stderr, "Unable to save mod list into file. No write access or disk is full!\n"); outfile.close(); outfile.clear(); if (mods->mod_list != temp_list) return true; else return false; } /** * Scan key binding */ void GameStateConfig::scanKey(int button) { if (input_confirm->visible) { if (inpt->last_button != -1 && inpt->last_button < 8) { if (button < 29) inpt->binding[button] = inpt->last_button; else inpt->binding_alt[button-29] = inpt->last_button; settings_key[button]->label = inpt->mouse_button[inpt->last_button-1]; input_confirm->visible = false; input_confirm_ticks = 0; settings_key[button]->refresh(); return; } if (inpt->last_key != -1) { if (button < 29) inpt->binding[button] = inpt->last_key; else inpt->binding_alt[button-29] = inpt->last_key; settings_key[button]->label = SDL_GetKeyName((SDLKey)inpt->last_key); input_confirm->visible = false; input_confirm_ticks = 0; settings_key[button]->refresh(); return; } } } GameStateConfig::~GameStateConfig() { tip_buf.clear(); delete tip; delete tabControl; delete ok_button; delete defaults_button; delete cancel_button; delete input_scrollbox; delete input_confirm; delete defaults_confirm; delete resolution_confirm; SDL_FreeSurface(background); for (std::vector::iterator iter = child_widget.begin(); iter != child_widget.end(); ++iter) { delete (*iter); } child_widget.clear(); for (unsigned int i = 0; i < 29; i++) { delete settings_lb[i]; } for (unsigned int i = 0; i < 58; i++) { delete settings_key[i]; } language_ISO.clear(); language_full.clear(); } void GameStateConfig::placeLabeledCheckbox( WidgetLabel* lb, WidgetCheckBox* cb, int x1, int y1, int x2, int y2, std::string const& str, int tab ) { cb->pos.x = frame.x + x2; cb->pos.y = frame.y + y2; child_widget.push_back(cb); optiontab[child_widget.size()-1] = tab; lb->setX(frame.x + x1); lb->setY(frame.y + y1); lb->set(str); lb->setJustify(JUSTIFY_RIGHT); child_widget.push_back(lb); optiontab[child_widget.size()-1] = tab; } flare-engine-0.19/src/GameStateConfig.h000066400000000000000000000115251224717101500177430ustar00rootroot00000000000000/* Copyright © 2012 Clint Bellanger Copyright © 2012 davidriod Copyright © 2012 Igor Paliychuk This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * GameStateConfig * * Handle game Settings Menu */ #pragma once #ifndef GAMESTATECONFIG_H #define GAMESTATECONFIG_H #include "CommonIncludes.h" #include "GameState.h" #include "TooltipData.h" class MenuConfirm; class Widget; class WidgetButton; class WidgetCheckBox; class WidgetInput; class WidgetLabel; class WidgetListBox; class WidgetScrollBox; class WidgetSlider; class WidgetTabControl; class WidgetTooltip; class GameStateConfig : public GameState { public: GameStateConfig (); ~GameStateConfig (); void logic (); void render (); private: int optiontab[138]; SDL_Rect frame; std::vector video_modes; SDL_Rect menuConfirm_area; std::string menuConfirm_align; std::vector language_ISO; std::vector language_full; int getVideoModes(void); bool getLanguagesList(void); int getLanguagesNumber(void); void init(); void readConfig(); void update(); void setDefaultResolution(); void refreshFont(); bool applyVideoSettings(int width, int height); void enableMods(); void disableMods(); bool setMods(); void scanKey(int button); void placeLabeledCheckbox( WidgetLabel* lb, WidgetCheckBox* cb, int x1, int y1, int x2, int y2, std::string const& str, int tab ); TabList tablist; std::vector child_widget; WidgetTabControl * tabControl; WidgetButton * ok_button; WidgetButton * defaults_button; WidgetButton * cancel_button; SDL_Surface * background; WidgetCheckBox * fullscreen_cb; WidgetLabel * fullscreen_lb; WidgetCheckBox * mouse_move_cb; WidgetLabel * mouse_move_lb; WidgetCheckBox * combat_text_cb; WidgetLabel * combat_text_lb; WidgetCheckBox * hwsurface_cb; WidgetLabel * hwsurface_lb; WidgetCheckBox * doublebuf_cb; WidgetLabel * doublebuf_lb; WidgetCheckBox * enable_joystick_cb; WidgetLabel * enable_joystick_lb; WidgetCheckBox * texture_quality_cb; WidgetLabel * texture_quality_lb; WidgetCheckBox * change_gamma_cb; WidgetLabel * change_gamma_lb; WidgetCheckBox * animated_tiles_cb; WidgetLabel * animated_tiles_lb; WidgetCheckBox * mouse_aim_cb; WidgetLabel * mouse_aim_lb; WidgetCheckBox * no_mouse_cb; WidgetLabel * no_mouse_lb; WidgetCheckBox * show_fps_cb; WidgetLabel * show_fps_lb; WidgetCheckBox * show_hotkeys_cb; WidgetLabel * show_hotkeys_lb; WidgetCheckBox * colorblind_cb; WidgetLabel * colorblind_lb; WidgetSlider * music_volume_sl; WidgetLabel * music_volume_lb; WidgetSlider * sound_volume_sl; WidgetLabel * sound_volume_lb; WidgetSlider * gamma_sl; WidgetLabel * gamma_lb; WidgetListBox * resolution_lstb; WidgetLabel * resolution_lb; WidgetListBox * activemods_lstb; WidgetLabel * activemods_lb; WidgetListBox * inactivemods_lstb; WidgetLabel * inactivemods_lb; WidgetListBox * joystick_device_lstb; WidgetLabel * joystick_device_lb; WidgetListBox * language_lstb; WidgetLabel * language_lb; WidgetLabel * hws_note_lb; WidgetLabel * dbuf_note_lb; WidgetLabel * anim_tiles_note_lb; WidgetLabel * test_note_lb; WidgetLabel * handheld_note_lb; WidgetButton * activemods_shiftup_btn; WidgetButton * activemods_shiftdown_btn; WidgetButton * activemods_deactivate_btn; WidgetButton * inactivemods_activate_btn; WidgetSlider * joystick_deadzone_sl; WidgetLabel * joystick_deadzone_lb; WidgetLabel * settings_lb[29]; WidgetButton * settings_key[58]; WidgetScrollBox * input_scrollbox; MenuConfirm * input_confirm; MenuConfirm * defaults_confirm; MenuConfirm * resolution_confirm; WidgetTooltip * tip; TooltipData tip_buf; int input_key; int mods_total; bool check_resolution; SDL_Rect scrollpane; SDL_Color scrollpane_color; int scrollpane_contents; int old_view_w; int old_view_h; int resolution_confirm_ticks; int input_confirm_ticks; }; #endif flare-engine-0.19/src/GameStateCutscene.cpp000066400000000000000000000146331224717101500206450ustar00rootroot00000000000000/* Copyright © 2012-2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "CommonIncludes.h" #include "GameStateCutscene.h" #include "GameStatePlay.h" #include "FileParser.h" #include "WidgetScrollBox.h" using namespace std; Scene::Scene() : frame_counter(0) , pause_frames(0) , caption("") , caption_size(0,0) , art(NULL) , sid(-1) , caption_box(NULL) , done(false) { } Scene::~Scene() { SDL_FreeSurface(art); delete caption_box; while(!components.empty()) { if (components.front().i != NULL) SDL_FreeSurface(components.front().i); components.pop(); } } bool Scene::logic(FPoint *caption_margins) { if (done) return false; bool skip = false; if (inpt->pressing[MAIN1] && !inpt->lock[MAIN1]) { inpt->lock[MAIN1] = true; skip = true; } if (inpt->pressing[ACCEPT] && !inpt->lock[ACCEPT]) { inpt->lock[ACCEPT] = true; skip = true; } if (inpt->pressing[CANCEL] && !inpt->lock[CANCEL]) { inpt->lock[CANCEL] = true; done = true; } /* Pause until specified frame */ if (!skip && pause_frames != 0 && frame_counter < pause_frames) { ++frame_counter; return true; } /* parse scene components until next pause */ while (!components.empty() && components.front().type != "pause") { if (components.front().type == "caption") { int caption_width = screen->w - (screen->w * (caption_margins->x * 2)); font->setFont("font_captions"); caption = components.front().s; caption_size = font->calc_size(caption, caption_width); delete caption_box; caption_box = new WidgetScrollBox(screen->w,caption_size.y); caption_box->pos.x = 0; caption_box->pos.y = screen->h - caption_size.y - (int)(VIEW_H * caption_margins->y); font->renderShadowed(caption, screen->w / 2, 0, JUSTIFY_CENTER, caption_box->contents, caption_width, FONT_WHITE); } else if (components.front().type == "image") { if (art) SDL_FreeSurface(art); art = components.front().i; art_dest.x = (VIEW_W/2) - (art->w/2); art_dest.y = (VIEW_H/2) - (art->h/2); art_dest.w = art->w; art_dest.h = art->h; } else if (components.front().type == "soundfx") { if (sid != 0) snd->unload(sid); sid = snd->load(components.front().s, "Cutscenes"); snd->play(sid); } components.pop(); } /* check if current scene has reached the end */ if (components.empty()) return false; /* setup frame pausing */ frame_counter = 0; pause_frames = components.front().x; components.pop(); return true; } void Scene::render() { SDL_Rect r = art_dest; if (art != NULL) SDL_BlitSurface(art, NULL, screen, &r); if (caption != "") { caption_box->render(); } } GameStateCutscene::GameStateCutscene(GameState *game_state) : previous_gamestate(game_state) , scale_graphics(false) , caption_margins(0.1, 0) , game_slot(-1) { } GameStateCutscene::~GameStateCutscene() { } void GameStateCutscene::logic() { if (scenes.empty()) { if (game_slot != -1) { GameStatePlay *gsp = new GameStatePlay(); gsp->resetGame(); gsp->game_slot = game_slot; gsp->loadGame(); previous_gamestate = gsp; } /* return to previous gamestate */ delete requestedGameState; requestedGameState = previous_gamestate; return; } while (!scenes.empty() && !scenes.front().logic(&caption_margins)) scenes.pop(); } void GameStateCutscene::render() { if (!scenes.empty()) scenes.front().render(); } bool GameStateCutscene::load(std::string filename) { FileParser infile; // @CLASS Cutscene|Description of cutscenes in cutscenes/ if (!infile.open("cutscenes/" + filename, true, false)) return false; // parse the cutscene file while (infile.next()) { if (infile.new_section) { if (infile.section == "scene") scenes.push(Scene()); } if (infile.section.empty()) { // allow having an empty section (globals such as scale_gfx might be set here } else if (infile.section == "scene") { SceneComponent sc = SceneComponent(); if (infile.key == "caption") { // @ATTR scene.caption|string|A caption that will be shown. sc.type = infile.key; sc.s = msg->get(infile.val); } else if (infile.key == "image") { // @ATTR scene.image|string|An image that will be shown. sc.type = infile.key; sc.i = loadImage(infile.val); if (sc.i == NULL) sc.type = ""; } else if (infile.key == "pause") { // @ATTR scene.pause|integer|Pause before next component sc.type = infile.key; sc.x = toInt(infile.val); } else if (infile.key == "soundfx") { // @ATTR scene.soundfx|string|A sound that will be played sc.type = infile.key; sc.s = infile.val; } if (sc.type != "") scenes.back().components.push(sc); } else { fprintf(stderr, "unknown section %s in file %s\n", infile.section.c_str(), infile.getFileName().c_str()); } if (infile.key == "scale_gfx") { // @ATTR scale_gfx|bool|The graphics will be scaled to fit screen width scale_graphics = toBool(infile.val); } else if (infile.key == "caption_margins") { // @ATTR caption_margins|[x,y]|Percentage-based margins for the caption text based on screen size caption_margins.x = toFloat(infile.nextValue())/100.0f; caption_margins.y = toFloat(infile.val)/100.0f; } } if (scenes.empty()) { fprintf(stderr, "No scenes defined in cutscene file %s\n", filename.c_str()); return false; } return true; } SDL_Surface *GameStateCutscene::loadImage(std::string filename) { std::string image_file = (mods->locate("images/"+ filename)); SDL_Surface *image = IMG_Load(image_file.c_str()); if (!image) { fprintf(stderr, "Missing cutscene art reference: %s\n", image_file.c_str()); return NULL; } /* scale image to fit height */ if (scale_graphics) { float ratio = image->h/(float)image->w; SDL_Surface *art = scaleSurface(image, VIEW_W, (int)(VIEW_W*ratio)); if (art == NULL) return image; SDL_FreeSurface(image); image = art; } return image; } flare-engine-0.19/src/GameStateCutscene.h000066400000000000000000000035231224717101500203060ustar00rootroot00000000000000/* Copyright © 2012-2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #ifndef GAMESTATECUTSCENE_H #define GAMESTATECUTSCENE_H #include "CommonIncludes.h" #include "GameState.h" #include "Settings.h" #include "SharedResources.h" #include "Utils.h" #include "UtilsParsing.h" #include #include class WidgetScrollBox; class SceneComponent { public: std::string type; SDL_Surface *i; std::string s; int x,y,z; SceneComponent() : type("") , i(NULL) , s("") , x(0) , y(0) , z(0) {} }; class Scene { private: int frame_counter; int pause_frames; std::string caption; Point caption_size; SDL_Surface *art; SDL_Rect art_dest; SoundManager::SoundID sid; WidgetScrollBox *caption_box; bool done; public: Scene(); ~Scene(); bool logic(FPoint *caption_margins); void render(); std::queue components; }; class GameStateCutscene : public GameState { private: GameState *previous_gamestate; std::string dest_map; Point dest_pos; bool scale_graphics; FPoint caption_margins; std::queue scenes; SDL_Surface *loadImage(std::string filename); public: GameStateCutscene(GameState *game_state); ~GameStateCutscene(); bool load(std::string filename); void logic(); void render(); int game_slot; }; #endif flare-engine-0.19/src/GameStateLoad.cpp000066400000000000000000000436251224717101500177560ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * GameStateLoad */ #include "Avatar.h" #include "SDL_gfxBlitFunc.h" #include "FileParser.h" #include "GameStateLoad.h" #include "GameStateTitle.h" #include "GameStatePlay.h" #include "GameStateNew.h" #include "ItemManager.h" #include "MenuConfirm.h" #include "SharedResources.h" #include "Settings.h" #include "UtilsFileSystem.h" #include "UtilsParsing.h" using namespace std; GameStateLoad::GameStateLoad() : GameState() { items = new ItemManager(); portrait = NULL; loading_requested = false; loading = false; loaded = false; label_loading = new WidgetLabel(); for (int i = 0; i < GAME_SLOT_MAX; i++) { label_name[i] = new WidgetLabel(); label_level[i] = new WidgetLabel(); label_map[i] = new WidgetLabel(); } // Confirmation box to confirm deleting confirm = new MenuConfirm(msg->get("Delete Save"), msg->get("Delete this save?")); button_exit = new WidgetButton("images/menus/buttons/button_default.png"); button_exit->label = msg->get("Exit to Title"); button_exit->pos.x = VIEW_W_HALF - button_exit->pos.w/2; button_exit->pos.y = VIEW_H - button_exit->pos.h; button_exit->refresh(); button_action = new WidgetButton("images/menus/buttons/button_default.png"); button_action->label = msg->get("Choose a Slot"); button_action->enabled = false; button_alternate = new WidgetButton("images/menus/buttons/button_default.png"); button_alternate->label = msg->get("Delete Save"); button_alternate->enabled = false; // Set up tab list tablist = TabList(HORIZONTAL); tablist.add(button_exit); // Read positions from config file FileParser infile; if (infile.open("menus/gameload.txt")) { while (infile.next()) { infile.val = infile.val + ','; if (infile.key == "action_button") { button_action->pos.x = eatFirstInt(infile.val, ','); button_action->pos.y = eatFirstInt(infile.val, ','); } else if (infile.key == "alternate_button") { button_alternate->pos.x = eatFirstInt(infile.val, ','); button_alternate->pos.y = eatFirstInt(infile.val, ','); } else if (infile.key == "portrait") { portrait_pos.x = eatFirstInt(infile.val, ','); portrait_pos.y = eatFirstInt(infile.val, ','); portrait_pos.w = eatFirstInt(infile.val, ','); portrait_pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "gameslot") { gameslot_pos.x = eatFirstInt(infile.val, ','); gameslot_pos.y = eatFirstInt(infile.val, ','); gameslot_pos.w = eatFirstInt(infile.val, ','); gameslot_pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "preview") { preview_pos.x = eatFirstInt(infile.val, ','); preview_pos.y = eatFirstInt(infile.val, ','); preview_pos.w = eatFirstInt(infile.val, ','); preview_pos.h = eatFirstInt(infile.val, ','); // label positions within each slot } else if (infile.key == "name") { name_pos = eatLabelInfo(infile.val); } else if (infile.key == "level") { level_pos = eatLabelInfo(infile.val); } else if (infile.key == "map") { map_pos = eatLabelInfo(infile.val); } else if (infile.key == "loading_label") { loading_pos = eatLabelInfo(infile.val); // Position for the avatar preview image in each slot } else if (infile.key == "sprite") { sprites_pos.x = eatFirstInt(infile.val, ','); sprites_pos.y = eatFirstInt(infile.val, ','); } } infile.close(); } // Load the MenuConfirm positions and alignments from menus/menus.txt if (infile.open("menus/menus.txt")) { int menu_index = -1; while (infile.next()) { if (infile.key == "id") { if (infile.val == "confirm") menu_index = 0; else menu_index = -1; } if (menu_index == -1) continue; if (infile.key == "layout") { infile.val = infile.val + ','; confirm->window_area.x = eatFirstInt(infile.val, ','); confirm->window_area.y = eatFirstInt(infile.val, ','); confirm->window_area.w = eatFirstInt(infile.val, ','); confirm->window_area.h = eatFirstInt(infile.val, ','); } if (infile.key == "align") { confirm->alignment = infile.val; } } infile.close(); } confirm->align(); confirm->update(); // get displayable types list bool found_layer = false; if (infile.open("engine/hero_options.txt", true, false)) { while(infile.next()) { infile.val = infile.val + ','; if (infile.key == "layer") { unsigned dir = eatFirstInt(infile.val,','); if (dir != 6) continue; else found_layer = true; string layer = eatFirstString(infile.val,','); while (layer != "") { preview_layer.push_back(layer); layer = eatFirstString(infile.val,','); } } } infile.close(); } if (!found_layer) fprintf(stderr, "Warning: Could not find layers for direction 6\n"); button_action->pos.x += (VIEW_W - FRAME_W)/2; button_action->pos.y += (VIEW_H - FRAME_H)/2; button_action->refresh(); button_alternate->pos.x += (VIEW_W - FRAME_W)/2; button_alternate->pos.y += (VIEW_H - FRAME_H)/2; button_alternate->refresh(); load_game = false; for (int i=0; igetColor("menu_normal"); } void GameStateLoad::loadGraphics() { background = loadGraphicSurface("images/menus/game_slots.png"); selection = loadGraphicSurface("images/menus/game_slot_select.png", "Couldn't load image", false, true); portrait_border = loadGraphicSurface("images/menus/portrait_border.png", "Couldn't load image", false, true); } void GameStateLoad::loadPortrait(int slot) { SDL_FreeSurface(portrait); portrait = NULL; if (slot < 0) return; if (stats[slot].name == "") return; portrait = loadGraphicSurface("images/portraits/" + stats[slot].gfx_portrait + ".png"); } void GameStateLoad::readGameSlots() { for (int i=0; iget(infile.val); } infile.close(); return map_name; } void GameStateLoad::readGameSlot(int slot) { stringstream filename; FileParser infile; // abort if not a valid slot number if (slot < 0 || slot >= GAME_SLOT_MAX) return; // save slots are named save#.txt filename << PATH_USER; if (GAME_PREFIX.length() > 0) filename << GAME_PREFIX << "_"; filename << "save" << (slot+1) << ".txt"; if (!infile.open(filename.str(),false, true, "")) return; while (infile.next()) { // load (key=value) pairs if (infile.key == "name") stats[slot].name = infile.val; else if (infile.key == "class") stats[slot].character_class = infile.val; else if (infile.key == "xp") stats[slot].xp = toInt(infile.val); else if (infile.key == "build") { stats[slot].physical_character = toInt(infile.nextValue()); stats[slot].mental_character = toInt(infile.nextValue()); stats[slot].offense_character = toInt(infile.nextValue()); stats[slot].defense_character = toInt(infile.nextValue()); } else if (infile.key == "equipped") { string repeat_val = infile.nextValue(); while (repeat_val != "") { equipped[slot].push_back(toInt(repeat_val)); repeat_val = infile.nextValue(); } } else if (infile.key == "option") { stats[slot].gfx_base = infile.nextValue(); stats[slot].gfx_head = infile.nextValue(); stats[slot].gfx_portrait = infile.nextValue(); } else if (infile.key == "spawn") { current_map[slot] = getMapName(infile.nextValue()); } else if (infile.key == "permadeath") { stats[slot].permadeath = toBool(infile.val); } } infile.close(); stats[slot].recalc(); loadPreview(slot); } void GameStateLoad::loadPreview(int slot) { vector img_gfx; for (unsigned int i=0; ilocate("animations/avatar/" + stats[slot].gfx_base + "/default_" + preview_layer[i] + ".txt")); if (exists) { img_gfx.push_back("default_" + preview_layer[i]); } else if (preview_layer[i] == "head") { img_gfx.push_back(stats[slot].gfx_head); } else { img_gfx.push_back(""); } } for (unsigned int i=0; i items->items.size()-1) { fprintf(stderr, "Item with id=%d out of bounds 1-%d. Your savegame is broken or you might use incompatible savegame/mod\nQuitting to avoid savegame rewriting\n", equipped[slot][i], (int)items->items.size()-1); SDL_Quit(); exit(1); } vector::iterator found = find(preview_layer.begin(), preview_layer.end(), items->items[equipped[slot][i]].type); if (equipped[slot][i] > 0 && found != preview_layer.end()) { img_gfx[distance(preview_layer.begin(), found)] = items->items[equipped[slot][i]].gfx; } } // composite the hero graphic for (unsigned int i=0; ivisible) { tablist.logic(); if (button_exit->checkClick() || (inpt->pressing[CANCEL] && !inpt->lock[CANCEL])) { inpt->lock[CANCEL] = true; delete requestedGameState; requestedGameState = new GameStateTitle(); } if (loading_requested) { loading = true; loading_requested = false; logicLoading(); } if (button_action->checkClick()) { if (stats[selected_slot].name == "") { // create a new game GameStateNew* newgame = new GameStateNew(); newgame->game_slot = selected_slot + 1; requestedGameState = newgame; } else { loading_requested = true; } } if (button_alternate->checkClick()) { // Display pop-up to make sure save should be deleted confirm->visible = true; confirm->render(); } // check clicking game slot if (inpt->pressing[MAIN1] && !inpt->lock[MAIN1]) { for (int i=0; imouse)) { inpt->lock[MAIN1] = true; selected_slot = i; updateButtons(); } } } // Allow characters to be navigateable via up/down keys if (inpt->pressing[UP] && !inpt->lock[UP]) { inpt->lock[UP] = true; selected_slot = (--selected_slot < 0) ? GAME_SLOT_MAX - 1 : selected_slot; updateButtons(); } if (inpt->pressing[DOWN] && !inpt->lock[DOWN]) { inpt->lock[DOWN] = true; selected_slot = (++selected_slot == GAME_SLOT_MAX) ? 0 : selected_slot; updateButtons(); } } else if (confirm->visible) { confirm->logic(); if (confirm->confirmClicked) { stringstream filename; filename.str(""); filename << PATH_USER; if (GAME_PREFIX.length() > 0) filename << GAME_PREFIX << "_"; filename << "save" << (selected_slot+1) << ".txt"; if (remove(filename.str().c_str()) != 0) perror("Error deleting save from path"); if (stats[selected_slot].permadeath) { // Remove stash stringstream ss; ss.str(""); ss << PATH_USER; if (GAME_PREFIX.length() > 0) ss << GAME_PREFIX << "_"; ss << "stash_HC" << (selected_slot+1) << ".txt"; if (remove(ss.str().c_str()) != 0) fprintf(stderr, "Error deleting hardcore stash in slot %d\n", selected_slot+1); } stats[selected_slot] = StatBlock(); readGameSlot(selected_slot); updateButtons(); confirm->visible = false; confirm->confirmClicked = false; } } } void GameStateLoad::logicLoading() { // load an existing game GameStatePlay* play = new GameStatePlay(); play->resetGame(); play->game_slot = selected_slot + 1; play->loadGame(); requestedGameState = play; loaded = true; loading = false; } void GameStateLoad::updateButtons() { loadPortrait(selected_slot); if (button_action->enabled == false) { button_action->enabled = true; tablist.add(button_action); } button_action->tooltip = ""; if (stats[selected_slot].name == "") { button_action->label = msg->get("New Game"); if (!fileExists(mods->locate("maps/spawn.txt"))) { button_action->enabled = false; tablist.remove(button_action); button_action->tooltip = msg->get("Enable a story mod to continue"); } button_alternate->enabled = false; tablist.remove(button_alternate); } else { if (button_alternate->enabled == false) { button_alternate->enabled = true; tablist.add(button_alternate); } button_action->label = msg->get("Load Game"); if (current_map[selected_slot] == "") { if (!fileExists(mods->locate("maps/spawn.txt"))) { button_action->enabled = false; tablist.remove(button_action); button_action->tooltip = msg->get("Enable a story mod to continue"); } } } button_action->refresh(); button_alternate->refresh(); } void GameStateLoad::render() { SDL_Rect src; SDL_Rect dest; // display background src.w = gameslot_pos.w; src.h = gameslot_pos.h * GAME_SLOT_MAX; src.x = src.y = 0; dest.x = slot_pos[0].x; dest.y = slot_pos[0].y; SDL_BlitSurface(background, &src, screen, &dest); // display selection if (selected_slot >= 0) { src.w = gameslot_pos.w; src.h = gameslot_pos.h; src.x = src.y = 0; SDL_BlitSurface(selection, &src, screen, &slot_pos[selected_slot]); } // portrait if (selected_slot >= 0 && portrait != NULL) { src.w = portrait_pos.w; src.h = portrait_pos.h; dest.x = portrait_pos.x + (VIEW_W - FRAME_W)/2; dest.y = portrait_pos.y + (VIEW_H - FRAME_H)/2; SDL_BlitSurface(portrait, &src, screen, &dest); SDL_BlitSurface(portrait_border, &src, screen, &dest); } Point label; stringstream ss; if (loading_requested || loading || loaded) { label.x = loading_pos.x + (VIEW_W - FRAME_W)/2; label.y = loading_pos.y + (VIEW_H - FRAME_H)/2; if ( loaded) { label_loading->set(msg->get("Entering game world...")); } else { label_loading->set(msg->get("Loading saved game...")); } label_loading->set(label.x, label.y, loading_pos.justify, loading_pos.valign, label_loading->get(), color_normal, loading_pos.font_style); label_loading->render(); } SDL_Color color_permadeath_enabled = font->getColor("hardcore_color_name"); // display text for (int slot=0; slotset(label.x, label.y, name_pos.justify, name_pos.valign, stats[slot].name, color_used, name_pos.font_style); label_name[slot]->render(); // level ss.str(""); label.x = slot_pos[slot].x + level_pos.x; label.y = slot_pos[slot].y + level_pos.y; ss << msg->get("Level %d %s", stats[slot].level, msg->get(stats[slot].character_class)); if (stats[slot].permadeath) ss << ", " + msg->get("Permadeath"); label_level[slot]->set(label.x, label.y, level_pos.justify, level_pos.valign, ss.str(), color_normal, level_pos.font_style); label_level[slot]->render(); // map label.x = slot_pos[slot].x + map_pos.x; label.y = slot_pos[slot].y + map_pos.y; label_map[slot]->set(label.x, label.y, map_pos.justify, map_pos.valign, current_map[slot], color_normal, map_pos.font_style); label_map[slot]->render(); // render character preview dest.x = slot_pos[slot].x + sprites_pos.x; dest.y = slot_pos[slot].y + sprites_pos.y; src.x = current_frame * preview_pos.h; src.y = 0; src.w = src.h = preview_pos.h; for (unsigned int i=0; iset(label.x, label.y, name_pos.justify, name_pos.valign, msg->get("Empty Slot"), color_normal, name_pos.font_style); label_name[slot]->render(); } } // display warnings if (confirm->visible) confirm->render(); // display buttons button_exit->render(); button_action->render(); button_alternate->render(); } GameStateLoad::~GameStateLoad() { SDL_FreeSurface(background); SDL_FreeSurface(selection); SDL_FreeSurface(portrait_border); SDL_FreeSurface(portrait); delete button_exit; delete button_action; delete button_alternate; delete items; for (int slot=0; slot sprites[GAME_SLOT_MAX]; StatBlock stats[GAME_SLOT_MAX]; std::vector equipped[GAME_SLOT_MAX]; std::vector preview_layer; SDL_Rect slot_pos[GAME_SLOT_MAX]; std::string current_map[GAME_SLOT_MAX]; bool loading_requested; bool loading; bool loaded; LabelInfo name_pos; LabelInfo level_pos; LabelInfo map_pos; LabelInfo loading_pos; Point sprites_pos; // animation info int current_frame; int frame_ticker; SDL_Rect portrait_pos; SDL_Rect gameslot_pos; SDL_Rect preview_pos; SDL_Color color_normal; public: GameStateLoad(); ~GameStateLoad(); void logic(); void logicLoading(); void render(); void readGameSlot(int slot); void readGameSlots(); void loadPreview(int slot); bool load_game; int selected_slot; }; #endif flare-engine-0.19/src/GameStateNew.cpp000066400000000000000000000260441224717101500176240ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * GameStateNew * * Handle player choices when starting a new game * (e.g. character appearance) */ #include "Avatar.h" #include "FileParser.h" #include "GameStateConfig.h" #include "GameStateNew.h" #include "GameStateLoad.h" #include "GameStatePlay.h" #include "Settings.h" #include "SharedResources.h" #include "TooltipData.h" #include "UtilsParsing.h" #include "WidgetButton.h" #include "WidgetCheckBox.h" #include "WidgetInput.h" #include "WidgetLabel.h" #include "WidgetListBox.h" #include "WidgetTooltip.h" using namespace std; GameStateNew::GameStateNew() : GameState() { game_slot = 0; current_option = 0; option_count = 0; portrait_image = NULL; tip_buf.clear(); modified_name = false; // set up buttons button_exit = new WidgetButton("images/menus/buttons/button_default.png"); button_exit->label = msg->get("Cancel"); button_exit->pos.x = VIEW_W_HALF - button_exit->pos.w; button_exit->pos.y = VIEW_H - button_exit->pos.h; button_exit->refresh(); button_create = new WidgetButton("images/menus/buttons/button_default.png"); button_create->label = msg->get("Create"); button_create->pos.x = VIEW_W_HALF; button_create->pos.y = VIEW_H - button_create->pos.h; button_create->enabled = false; button_create->refresh(); button_prev = new WidgetButton("images/menus/buttons/left.png"); button_next = new WidgetButton("images/menus/buttons/right.png"); input_name = new WidgetInput(); button_permadeath = new WidgetCheckBox("images/menus/buttons/checkbox_default.png"); if (DEATH_PENALTY_PERMADEATH) { button_permadeath->enabled = false; button_permadeath->Check(); } class_list = new WidgetListBox (HERO_CLASSES.size(), 12, "images/menus/buttons/listbox_default.png"); class_list->can_deselect = false; class_list->selected[0] = true; show_classlist = true; tip = new WidgetTooltip(); // Read positions from config file FileParser infile; if (infile.open("menus/gamenew.txt")) { while (infile.next()) { infile.val = infile.val + ','; if (infile.key == "button_prev") { button_prev->pos.x = eatFirstInt(infile.val, ','); button_prev->pos.y = eatFirstInt(infile.val, ','); } else if (infile.key == "button_next") { button_next->pos.x = eatFirstInt(infile.val, ','); button_next->pos.y = eatFirstInt(infile.val, ','); } else if (infile.key == "button_permadeath") { button_permadeath->pos.x = eatFirstInt(infile.val, ','); button_permadeath->pos.y = eatFirstInt(infile.val, ','); } else if (infile.key == "name_input") { name_pos.x = eatFirstInt(infile.val, ','); name_pos.y = eatFirstInt(infile.val, ','); } else if (infile.key == "portrait_label") { portrait_label = eatLabelInfo(infile.val); } else if (infile.key == "name_label") { name_label = eatLabelInfo(infile.val); } else if (infile.key == "permadeath_label") { permadeath_label = eatLabelInfo(infile.val); } else if (infile.key == "classlist_label") { classlist_label = eatLabelInfo(infile.val); } else if (infile.key == "portrait") { portrait_pos.x = eatFirstInt(infile.val, ','); portrait_pos.y = eatFirstInt(infile.val, ','); portrait_pos.w = eatFirstInt(infile.val, ','); portrait_pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "class_list") { class_list->pos.x = eatFirstInt(infile.val, ','); class_list->pos.y = eatFirstInt(infile.val, ','); } else if (infile.key == "show_classlist") { int show_cl = eatFirstInt(infile.val, ','); if (show_cl == 1) show_classlist = true; else show_classlist = false; } } infile.close(); } button_prev->pos.x += (VIEW_W - FRAME_W)/2; button_prev->pos.y += (VIEW_H - FRAME_H)/2; button_next->pos.x += (VIEW_W - FRAME_W)/2; button_next->pos.y += (VIEW_H - FRAME_H)/2; class_list->pos.x += (VIEW_W - FRAME_W)/2; class_list->pos.y += (VIEW_H - FRAME_H)/2; name_pos.x += (VIEW_W - FRAME_W)/2; name_pos.y += (VIEW_H - FRAME_H)/2; input_name->setPosition(name_pos.x, name_pos.y); button_permadeath->pos.x += (VIEW_W - FRAME_W)/2; button_permadeath->pos.y += (VIEW_H - FRAME_H)/2; portrait_label.x += (VIEW_W - FRAME_W)/2; portrait_label.y += (VIEW_H - FRAME_H)/2; name_label.x += (VIEW_W - FRAME_W)/2; name_label.y += (VIEW_H - FRAME_H)/2; permadeath_label.x += (VIEW_W - FRAME_W)/2; permadeath_label.y += (VIEW_H - FRAME_H)/2; classlist_label.x += (VIEW_W - FRAME_W)/2; classlist_label.y += (VIEW_H - FRAME_H)/2; // set up labels color_normal = font->getColor("menu_normal"); label_portrait = new WidgetLabel(); label_portrait->set(portrait_label.x, portrait_label.y, portrait_label.justify, portrait_label.valign, msg->get("Choose a Portrait"), color_normal, portrait_label.font_style); label_name = new WidgetLabel(); label_name->set(name_label.x, name_label.y, name_label.justify, name_label.valign, msg->get("Choose a Name"), color_normal, name_label.font_style); label_permadeath = new WidgetLabel(); label_permadeath->set(permadeath_label.x, permadeath_label.y, permadeath_label.justify, permadeath_label.valign, msg->get("Permadeath?"), color_normal, permadeath_label.font_style); label_classlist = new WidgetLabel(); label_classlist->set(classlist_label.x, classlist_label.y, classlist_label.justify, classlist_label.valign, msg->get("Choose a Class"), color_normal, classlist_label.font_style); // set up class list for (unsigned i=0; iappend(msg->get(HERO_CLASSES[i].name),getClassTooltip(i)); } loadGraphics(); loadOptions("hero_options.txt"); if (portrait.empty()) portrait.push_back(""); if (name.empty()) name.push_back(""); loadPortrait(portrait[0]); setName(name[0]); // Set up tab list tablist.add(button_exit); tablist.add(button_create); tablist.add(button_permadeath); tablist.add(button_prev); tablist.add(button_next); tablist.add(class_list); } void GameStateNew::loadGraphics() { portrait_border = loadGraphicSurface("images/menus/portrait_border.png", "Couldn't load portrait border image", false, true); } void GameStateNew::loadPortrait(const string& portrait_filename) { SDL_FreeSurface(portrait_image); portrait_image = loadGraphicSurface("images/portraits/" + portrait_filename + ".png"); } /** * Load body type "base" and portrait/head "portrait" options from a config file * * @param filename File containing entries for option=base,look */ void GameStateNew::loadOptions(const string& filename) { FileParser fin; if (!fin.open("engine/" + filename, true, false)) return; while (fin.next()) { if (fin.key == "option") { base.push_back(fin.nextValue()); head.push_back(fin.nextValue()); portrait.push_back(fin.nextValue()); name.push_back(fin.nextValue()); } } fin.close(); } /** * If the name text box is empty or hasn't been user-modified, set the name * * @param default_name The name we want to use for the hero */ void GameStateNew:: setName(const string& default_name) { if (input_name->getText() == "" || !modified_name) { input_name->setText(default_name); modified_name = false; } } void GameStateNew::logic() { if (!input_name->inFocus) tablist.logic(); button_permadeath->checkClick(); if (show_classlist) class_list->checkClick(); // require character name if (input_name->getText() == "") { if (button_create->enabled) { button_create->enabled = false; button_create->refresh(); } } else { if (!button_create->enabled) { button_create->enabled = true; button_create->refresh(); } } if ((inpt->pressing[CANCEL] && !inpt->lock[CANCEL]) || button_exit->checkClick()) { inpt->lock[CANCEL] = true; delete requestedGameState; requestedGameState = new GameStateLoad(); } if (button_create->checkClick()) { // start the new game GameStatePlay* play = new GameStatePlay(); Avatar *pc = play->getAvatar(); pc->stats.gfx_base = base[current_option]; pc->stats.gfx_head = head[current_option]; pc->stats.gfx_portrait = portrait[current_option]; pc->stats.name = input_name->getText(); pc->stats.permadeath = button_permadeath->isChecked(); play->game_slot = game_slot; play->resetGame(); play->loadClass(class_list->getSelected()); requestedGameState = play; } // scroll through portrait options if (button_next->checkClick()) { current_option++; if (current_option == (int)portrait.size()) current_option = 0; loadPortrait(portrait[current_option]); setName(name[current_option]); } else if (button_prev->checkClick()) { current_option--; if (current_option == -1) current_option = portrait.size()-1; loadPortrait(portrait[current_option]); setName(name[current_option]); } input_name->logic(); if (input_name->getText() != name[current_option]) modified_name = true; } void GameStateNew::render() { // display buttons button_exit->render(); button_create->render(); button_prev->render(); button_next->render(); input_name->render(); button_permadeath->render(); // display portrait option SDL_Rect src; SDL_Rect dest; src.w = dest.w = portrait_pos.w; src.h = dest.h = portrait_pos.h; src.x = src.y = 0; dest.x = portrait_pos.x + (VIEW_W - FRAME_W)/2; dest.y = portrait_pos.y + (VIEW_H - FRAME_H)/2; SDL_BlitSurface(portrait_image, &src, screen, &dest); SDL_BlitSurface(portrait_border, &src, screen, &dest); // display labels if (!portrait_label.hidden) label_portrait->render(); if (!name_label.hidden) label_name->render(); if (!permadeath_label.hidden) label_permadeath->render(); // display class list if (show_classlist) { if (!classlist_label.hidden) label_classlist->render(); class_list->render(); TooltipData tip_new = class_list->checkTooltip(inpt->mouse); if (!tip_new.isEmpty()) { // when we render a tooltip it buffers the rasterized text for performance. // If this new tooltip is the same as the existing one, reuse. if (!tip_new.compare(&tip_buf)) { tip_buf.clear(); tip_buf = tip_new; } tip->render(tip_buf, inpt->mouse, STYLE_FLOAT); } } } std::string GameStateNew::getClassTooltip(int index) { string tooltip; if (HERO_CLASSES[index].description != "") tooltip += msg->get(HERO_CLASSES[index].description); return tooltip; } GameStateNew::~GameStateNew() { SDL_FreeSurface(portrait_image); SDL_FreeSurface(portrait_border); delete button_exit; delete button_create; delete button_next; delete button_prev; delete label_portrait; delete label_name; delete input_name; delete button_permadeath; delete label_permadeath; delete label_classlist; delete class_list; delete tip; } flare-engine-0.19/src/GameStateNew.h000066400000000000000000000043421224717101500172660ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * GameStateNew * * Handle player choices when starting a new game * (e.g. character appearance) */ #pragma once #ifndef GAMESTATENEW_H #define GAMESTATENEW_H #include "CommonIncludes.h" #include "GameState.h" #include "TooltipData.h" #include "WidgetLabel.h" class WidgetButton; class WidgetCheckBox; class WidgetInput; class WidgetLabel; class WidgetListBox; class WidgetTooltip; class GameStateNew : public GameState { private: void loadGraphics(); void loadPortrait(const std::string& portrait_filename); void loadOptions(const std::string& option_filename); std::string getClassTooltip(int index); void setName(const std::string& default_name); std::vector base; std::vector head; std::vector portrait; std::vector name; int option_count; int current_option; SDL_Surface *portrait_image; SDL_Surface *portrait_border; WidgetButton *button_exit; WidgetButton *button_create; WidgetButton *button_next; WidgetButton *button_prev; WidgetLabel *label_portrait; WidgetLabel *label_name; WidgetInput *input_name; WidgetCheckBox *button_permadeath; WidgetLabel *label_permadeath; WidgetLabel *label_classlist; WidgetListBox *class_list; WidgetTooltip *tip; TabList tablist; Point name_pos; LabelInfo portrait_label; LabelInfo name_label; LabelInfo permadeath_label; LabelInfo classlist_label; SDL_Rect portrait_pos; bool show_classlist; TooltipData tip_buf; bool modified_name; SDL_Color color_normal; public: GameStateNew(); ~GameStateNew(); void logic(); void render(); int game_slot; }; #endif flare-engine-0.19/src/GameStatePlay.cpp000066400000000000000000000723571224717101500200100ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk Copyright © 2012-2013 Henrik Andersson Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class GameStatePlay * * Handles logic and rendering of the main action game play * Also handles message passing between child objects, often to avoid circular dependencies. */ #include "Avatar.h" #include "CampaignManager.h" #include "EnemyManager.h" #include "GameStatePlay.h" #include "GameState.h" #include "GameStateTitle.h" #include "GameStateCutscene.h" #include "Hazard.h" #include "HazardManager.h" #include "Menu.h" #include "MenuActionBar.h" #include "MenuCharacter.h" #include "MenuEnemy.h" #include "MenuHUDLog.h" #include "MenuInventory.h" #include "MenuLog.h" #include "MenuManager.h" #include "MenuMiniMap.h" #include "MenuNPCActions.h" #include "MenuStash.h" #include "MenuTalker.h" #include "MenuVendor.h" #include "NPC.h" #include "NPCManager.h" #include "QuestLog.h" #include "WidgetLabel.h" #include "SharedGameResources.h" #include "SharedResources.h" #include "UtilsFileSystem.h" #include "FileParser.h" #include "UtilsParsing.h" #include "MenuPowers.h" using namespace std; const int MENU_ENEMY_TIMEOUT = MAX_FRAMES_PER_SEC * 10; GameStatePlay::GameStatePlay() : GameState() , enemy(NULL) , loading(new WidgetLabel()) // Load the loading screen image (we currently use the confirm dialog background): , loading_bg(loadGraphicSurface("images/menus/confirm_bg.png")) , npc_id(-1) , eventDialogOngoing(false) , eventPendingDialog(false) , color_normal(font->getColor("menu_normal")) , nearest_npc(-1) , game_slot(0) { hasMusic = true; // GameEngine scope variables powers = new PowerManager(); items = new ItemManager(); camp = new CampaignManager(); mapr = new MapRenderer(); pc = new Avatar(); enemies = new EnemyManager(); hazards = new HazardManager(); menu = new MenuManager(&pc->stats); npcs = new NPCManager(&pc->stats); quests = new QuestLog(menu->log); enemyg = new EnemyGroupManager(); loot = new LootManager(&pc->stats); // assign some object pointers after object creation, based on dependency order camp->carried_items = &menu->inv->inventory[CARRIED]; camp->currency = &menu->inv->currency; camp->hero = &pc->stats; loading->set(VIEW_W_HALF, VIEW_H_HALF, JUSTIFY_CENTER, VALIGN_CENTER, msg->get("Loading..."), color_normal); // load the config file for character titles loadTitles(); } /** * Reset all game states to a new game. */ void GameStatePlay::resetGame() { mapr->load("spawn.txt"); camp->clearAll(); pc->init(); pc->stats.currency = 0; menu->act->clear(); menu->inv->inventory[0].clear(); menu->inv->inventory[1].clear(); menu->inv->changed_equipment = true; menu->inv->currency = 0; menu->log->clear(); quests->createQuestList(); menu->hudlog->clear(); loadStash(); // Finalize new character settings menu->talker->setHero(pc->stats.name, pc->stats.character_class, pc->stats.gfx_portrait); pc->loadSounds(); } /** * Check mouseover for enemies. * class variable "enemy" contains a live enemy on mouseover. * This function also sets enemy mouseover for Menu Enemy. */ void GameStatePlay::checkEnemyFocus() { // check the last hit enemy first // if there's none, then either get the nearest enemy or one under the mouse (depending on mouse mode) if (NO_MOUSE) { if (hazards->last_enemy) { if (enemy == hazards->last_enemy) { if (menu->enemy->timeout > 0) return; else hazards->last_enemy = NULL; } enemy = hazards->last_enemy; } else { enemy = enemies->getNearestEnemy(pc->stats.pos); } } else { if (hazards->last_enemy) { enemy = hazards->last_enemy; hazards->last_enemy = NULL; } else { enemy = enemies->enemyFocus(inpt->mouse, mapr->cam, true); } } if (enemy) { // set the actual menu with the enemy selected above if (!enemy->stats.suppress_hp) { menu->enemy->enemy = enemy; menu->enemy->timeout = MENU_ENEMY_TIMEOUT; } } else if (!NO_MOUSE) { // if we're using a mouse and we didn't select an enemy, try selecting a dead one instead Enemy *temp_enemy = enemies->enemyFocus(inpt->mouse, mapr->cam, false); if (temp_enemy) { menu->enemy->enemy = temp_enemy; menu->enemy->timeout = MENU_ENEMY_TIMEOUT; } } } /** * If mouse_move is enabled, and the mouse is over a live enemy, * Do not allow power use with button MAIN1 */ bool GameStatePlay::restrictPowerUse() { if(MOUSE_MOVE) { if(inpt->pressing[MAIN1] && !inpt->pressing[SHIFT] && !(isWithin(menu->act->numberArea,inpt->mouse) || isWithin(menu->act->mouseArea,inpt->mouse) || isWithin(menu->act->menuArea, inpt->mouse))) { if(enemy == NULL) { return true; } else { if(menu->act->slot_enabled[10] && (powers->powers[menu->act->hotkeys[10]].target_party != enemy->stats.hero_ally)) return true; } } } return false; } /** * Check to see if the player is picking up loot on the ground */ void GameStatePlay::checkLoot() { if (!pc->stats.alive) return; if (menu->isDragging()) return; ItemStack pickup; // Autopickup if (AUTOPICKUP_CURRENCY) { pickup = loot->checkAutoPickup(pc->stats.pos, menu->inv); if (pickup.item > 0) menu->inv->add(pickup); } // Pickup with mouse click if (inpt->pressing[MAIN1] && !inpt->lock[MAIN1] && !NO_MOUSE) { pickup = loot->checkPickup(inpt->mouse, mapr->cam, pc->stats.pos, menu->inv); if (pickup.item > 0) { inpt->lock[MAIN1] = true; menu->inv->add(pickup); camp->setStatus(items->items[pickup.item].pickup_status); } if (loot->full_msg) { inpt->lock[MAIN1] = true; menu->log->add(msg->get("Inventory is full."), LOG_TYPE_MESSAGES); menu->hudlog->add(msg->get("Inventory is full.")); loot->full_msg = false; } } // Pickup with ACCEPT key/button if ((inpt->pressing[ACCEPT] && !inpt->lock[ACCEPT])) { pickup = loot->checkNearestPickup(pc->stats.pos, menu->inv); if (pickup.item > 0) { if (inpt->pressing[ACCEPT]) inpt->lock[ACCEPT] = true; menu->inv->add(pickup); camp->setStatus(items->items[pickup.item].pickup_status); } if (loot->full_msg) { if (inpt->pressing[ACCEPT]) inpt->lock[ACCEPT] = true; menu->log->add(msg->get("Inventory is full."), LOG_TYPE_MESSAGES); menu->hudlog->add(msg->get("Inventory is full.")); loot->full_msg = false; } } } void GameStatePlay::checkTeleport() { // both map events and player powers can cause teleportation if (mapr->teleportation || pc->stats.teleportation) { mapr->collider.unblock(pc->stats.pos.x, pc->stats.pos.y); if (mapr->teleportation) { mapr->cam.x = pc->stats.pos.x = mapr->teleport_destination.x; mapr->cam.y = pc->stats.pos.y = mapr->teleport_destination.y; } else { mapr->cam.x = pc->stats.pos.x = pc->stats.teleport_destination.x; mapr->cam.y = pc->stats.pos.y = pc->stats.teleport_destination.y; } for (unsigned int i=0; i < enemies->enemies.size(); i++) { if(enemies->enemies[i]->stats.hero_ally && enemies->enemies[i]->stats.alive) { mapr->collider.unblock(enemies->enemies[i]->stats.pos.x, enemies->enemies[i]->stats.pos.y); enemies->enemies[i]->stats.pos.x = pc->stats.pos.x; enemies->enemies[i]->stats.pos.y = pc->stats.pos.y; } } // process intermap teleport if (mapr->teleportation && mapr->teleport_mapname != "") { std::string teleport_mapname = mapr->teleport_mapname; mapr->teleport_mapname = ""; mapr->executeOnMapExitEvents(); showLoading(); mapr->load(teleport_mapname); enemies->handleNewMap(); hazards->handleNewMap(); loot->handleNewMap(); powers->handleNewMap(&mapr->collider); menu->enemy->handleNewMap(); npcs->handleNewMap(); menu->vendor->npc = NULL; menu->vendor->visible = false; menu->talker->visible = false; menu->stash->visible = false; menu->npc->visible = false; menu->mini->prerender(&mapr->collider, mapr->w, mapr->h); npc_id = nearest_npc = -1; // store this as the new respawn point mapr->respawn_map = teleport_mapname; mapr->respawn_point.x = pc->stats.pos.x; mapr->respawn_point.y = pc->stats.pos.y; // return to title (permadeath) OR auto-save if (pc->stats.permadeath && pc->stats.corpse) { stringstream filename; filename << PATH_USER; if (GAME_PREFIX.length() > 0) filename << GAME_PREFIX << "_"; filename << "save" << game_slot << ".txt"; if (remove(filename.str().c_str()) != 0) perror("Error deleting save from path"); // Remove stash stringstream ss; ss.str(""); ss << PATH_USER; if (GAME_PREFIX.length() > 0) ss << GAME_PREFIX << "_"; ss << "stash_HC" << game_slot << ".txt"; if (remove(ss.str().c_str()) != 0) fprintf(stderr, "Error deleting hardcore stash in slot %d\n", game_slot); delete requestedGameState; requestedGameState = new GameStateTitle(); } else { saveGame(); } } mapr->collider.block(pc->stats.pos.x, pc->stats.pos.y, false); pc->stats.teleportation = false; // teleport spell } if (mapr->teleport_mapname == "") mapr->teleportation = false; } /** * Check for cancel key to exit menus or exit the game. * Also check closing the game window entirely. */ void GameStatePlay::checkCancel() { // if user has clicked exit game from exit menu if (menu->requestingExit()) { saveGame(); Mix_HaltMusic(); delete requestedGameState; requestedGameState = new GameStateTitle(); } // if user closes the window if (inpt->done) { saveGame(); Mix_HaltMusic(); exitRequested = true; } } /** * Check for log messages from various child objects */ void GameStatePlay::checkLog() { // If the player has just respawned, we want to clear the HUD log if (pc->respawn) { menu->hudlog->clear(); } // Map events can create messages if (mapr->log_msg != "") { menu->log->add(mapr->log_msg, LOG_TYPE_MESSAGES); menu->hudlog->add(mapr->log_msg); mapr->log_msg = ""; } // The avatar can create messages (e.g. level up) if (pc->log_msg != "") { menu->log->add(pc->log_msg, LOG_TYPE_MESSAGES); menu->hudlog->add(pc->log_msg); pc->log_msg = ""; } // Campaign events can create messages (e.g. quest rewards) if (camp->log_msg != "") { menu->log->add(camp->log_msg, LOG_TYPE_MESSAGES); menu->hudlog->add(camp->log_msg); camp->log_msg = ""; } // MenuInventory has hints to help the player use items properly if (menu->inv->log_msg != "") { menu->hudlog->add(menu->inv->log_msg); menu->inv->log_msg = ""; } // PowerManager has hints for powers if (powers->log_msg != "") { menu->hudlog->add(powers->log_msg); powers->log_msg = ""; } } void GameStatePlay::loadTitles() { FileParser infile; if (infile.open("engine/titles.txt")) { while (infile.next()) { if (infile.new_section && infile.section == "title") { Title t; titles.push_back(t); } if (titles.empty()) continue; if (infile.key == "title") titles.back().title = infile.val; else if (infile.key == "level") titles.back().level = toInt(infile.val); else if (infile.key == "power") titles.back().power = toInt(infile.val); else if (infile.key == "requires_status") titles.back().requires_status = infile.val; else if (infile.key == "requires_not_status") titles.back().requires_not = infile.val; else if (infile.key == "primary_stat") titles.back().primary_stat = infile.val; else fprintf(stderr, "GameStatePlay: Unknown key value in title definitons: %s in file %s in section %s\n", infile.key.c_str(), infile.getFileName().c_str(), infile.section.c_str()); } infile.close(); } } void GameStatePlay::checkTitle() { if (!pc->stats.check_title || titles.empty()) return; int title_id = -1; for (unsigned i=0; i 0 && pc->stats.level < titles[i].level) continue; if (titles[i].power > 0 && find(pc->stats.powers_list.begin(), pc->stats.powers_list.end(), titles[i].power) == pc->stats.powers_list.end()) continue; if (titles[i].requires_status != "" && !camp->checkStatus(titles[i].requires_status)) continue; if (titles[i].requires_not != "" && camp->checkStatus(titles[i].requires_not)) continue; if (titles[i].primary_stat != "") { if (titles[i].primary_stat == "physical") { if (pc->stats.get_physical() <= pc->stats.get_mental() || pc->stats.get_physical() <= pc->stats.get_offense() || pc->stats.get_physical() <= pc->stats.get_defense()) continue; } else if (titles[i].primary_stat == "offense") { if (pc->stats.get_offense() <= pc->stats.get_mental() || pc->stats.get_offense() <= pc->stats.get_physical() || pc->stats.get_offense() <= pc->stats.get_defense()) continue; } else if (titles[i].primary_stat == "mental") { if (pc->stats.get_mental() <= pc->stats.get_physical() || pc->stats.get_mental() <= pc->stats.get_offense() || pc->stats.get_mental() <= pc->stats.get_defense()) continue; } else if (titles[i].primary_stat == "defense") { if (pc->stats.get_defense() <= pc->stats.get_mental() || pc->stats.get_defense() <= pc->stats.get_offense() || pc->stats.get_defense() <= pc->stats.get_physical()) continue; } else if (titles[i].primary_stat == "physoff") { if (pc->stats.physoff() <= pc->stats.physdef() || pc->stats.physoff() <= pc->stats.mentoff() || pc->stats.physoff() <= pc->stats.mentdef() || pc->stats.physoff() <= pc->stats.physment() || pc->stats.physoff() <= pc->stats.offdef()) continue; } else if (titles[i].primary_stat == "physment") { if (pc->stats.physment() <= pc->stats.physdef() || pc->stats.physment() <= pc->stats.mentoff() || pc->stats.physment() <= pc->stats.mentdef() || pc->stats.physment() <= pc->stats.physoff() || pc->stats.physment() <= pc->stats.offdef()) continue; } else if (titles[i].primary_stat == "physdef") { if (pc->stats.physdef() <= pc->stats.physoff() || pc->stats.physdef() <= pc->stats.mentoff() || pc->stats.physdef() <= pc->stats.mentdef() || pc->stats.physdef() <= pc->stats.physment() || pc->stats.physdef() <= pc->stats.offdef()) continue; } else if (titles[i].primary_stat == "mentoff") { if (pc->stats.mentoff() <= pc->stats.physdef() || pc->stats.mentoff() <= pc->stats.physoff() || pc->stats.mentoff() <= pc->stats.mentdef() || pc->stats.mentoff() <= pc->stats.physment() || pc->stats.mentoff() <= pc->stats.offdef()) continue; } else if (titles[i].primary_stat == "offdef") { if (pc->stats.offdef() <= pc->stats.physdef() || pc->stats.offdef() <= pc->stats.mentoff() || pc->stats.offdef() <= pc->stats.mentdef() || pc->stats.offdef() <= pc->stats.physment() || pc->stats.offdef() <= pc->stats.physoff()) continue; } else if (titles[i].primary_stat == "mentdef") { if (pc->stats.mentdef() <= pc->stats.physdef() || pc->stats.mentdef() <= pc->stats.mentoff() || pc->stats.mentdef() <= pc->stats.physoff() || pc->stats.mentdef() <= pc->stats.physment() || pc->stats.mentdef() <= pc->stats.offdef()) continue; } } // Title meets the requirements title_id = i; break; } if (title_id != -1) pc->stats.character_class = titles[title_id].title; pc->stats.check_title = false; pc->stats.refresh_stats = true; } void GameStatePlay::checkEquipmentChange() { if (menu->inv->changed_equipment) { vector img_gfx; // load only displayable layers for (unsigned int j=0; jlayer_reference_order.size(); j++) { Layer_gfx gfx; gfx.gfx = ""; gfx.type = ""; for (int i=0; iinv->inventory[EQUIPMENT].getSlotNumber(); i++) { if (pc->layer_reference_order[j] == menu->inv->inventory[EQUIPMENT].slot_type[i]) { gfx.gfx = items->items[menu->inv->inventory[EQUIPMENT][i].item].gfx; gfx.type = menu->inv->inventory[EQUIPMENT].slot_type[i]; } } // special case: if we don't have a head, use the portrait's head if (gfx.gfx == "" && pc->layer_reference_order[j] == "head") { gfx.gfx = pc->stats.gfx_head; gfx.type = "head"; } // fall back to default if it exists if (gfx.gfx == "") { bool exists = fileExists(mods->locate("animations/avatar/" + pc->stats.gfx_base + "/default_" + gfx.type + ".txt")); if (exists) gfx.gfx = "default_" + gfx.type; } img_gfx.push_back(gfx); } assert(pc->layer_reference_order.size()==img_gfx.size()); pc->loadGraphics(img_gfx); pc->loadStepFX(items->items[menu->inv->inventory[EQUIPMENT][1].item].stepfx); menu->inv->changed_equipment = false; } } void GameStatePlay::checkLootDrop() { // if the player has dropped an item from the inventory if (menu->drop_stack.item > 0) { loot->addLoot(menu->drop_stack, pc->stats.pos); menu->drop_stack.item = 0; menu->drop_stack.quantity = 0; } // if the player has dropped a quest rward because inventory full if (camp->drop_stack.item > 0) { loot->addLoot(camp->drop_stack, pc->stats.pos); camp->drop_stack.item = 0; camp->drop_stack.quantity = 0; } // if the player been directly given items, but their inventory is full // this happens when adding currency from older save files if (menu->inv->drop_stack.item > 0) { loot->addLoot(menu->inv->drop_stack, pc->stats.pos); menu->inv->drop_stack.item = 0; menu->inv->drop_stack.quantity = 0; } } /** * When a consumable-based power is used, we need to remove it from the inventory. */ void GameStatePlay::checkConsumable() { for (unsigned i=0; iused_items.size(); i++) { if (items->items[powers->used_items[i]].type == "consumable") { menu->inv->remove(powers->used_items[i]); } } for (unsigned i=0; iused_equipped_items.size(); i++) { menu->inv->removeEquipped(powers->used_equipped_items[i]); } powers->used_items.clear(); powers->used_equipped_items.clear(); } /** * Marks the menu if it needs attention. */ void GameStatePlay::checkNotifications() { if (pc->newLevelNotification) { pc->newLevelNotification = false; menu->act->requires_attention[MENU_CHARACTER] = true; } if (menu->chr->newPowerNotification) { menu->chr->newPowerNotification = false; menu->act->requires_attention[MENU_POWERS] = true; } if (quests->resetQuestNotification) { //remove if no quests quests->resetQuestNotification = false; menu->act->requires_attention[MENU_LOG] = false; } if (quests->newQuestNotification) { quests->newQuestNotification = false; menu->act->requires_attention[MENU_LOG] = true; } // if the player is transformed into a creature, don't notifications for the powers menu if (pc->stats.transformed) { menu->act->requires_attention[MENU_POWERS] = false; } } /** * If the player has clicked on an NPC, the game mode might be changed. * If a player walks away from an NPC, end the interaction with that NPC * If an NPC is giving a reward, process it */ void GameStatePlay::checkNPCInteraction() { if (pc->attacking) return; int npc_click = -1; float interact_distance = 0; nearest_npc = npcs->getNearestNPC(pc->stats.pos); // check for clicking on an NPC if (inpt->pressing[MAIN1] && !inpt->lock[MAIN1] && !NO_MOUSE) { npc_click = npcs->checkNPCClick(inpt->mouse, mapr->cam); if (npc_click != -1) npc_id = npc_click; } // if we press the ACCEPT key, find the nearest NPC to interact with else if (nearest_npc != -1 && inpt->pressing[ACCEPT] && !inpt->lock[ACCEPT]) { npc_id = npc_click = nearest_npc; } // check distance to this npc if (npc_id != -1) { interact_distance = calcDist(pc->stats.pos, npcs->npcs[npc_id]->pos); } if (mapr->event_npc != "") { npc_id = npcs->getID(mapr->event_npc); if (npc_id != -1) { eventDialogOngoing = true; eventPendingDialog = true; } mapr->event_npc = ""; } // if close enough to the NPC, open the appropriate interaction screen if (npc_id != -1 && ((npc_click != -1 && interact_distance < INTERACT_RANGE && pc->stats.alive && pc->stats.humanoid) || eventPendingDialog)) { if (inpt->pressing[MAIN1] && !NO_MOUSE) inpt->lock[MAIN1] = true; if (inpt->pressing[ACCEPT]) inpt->lock[ACCEPT] = true; menu->npc->setNPC(npcs->npcs[npc_id]); // only show npc action menu if multiple actions are available if (!menu->npc->empty() && !menu->npc->selection()) menu->npc->visible = true; } // check if a NPC action selection is made if (menu->npc->selection()) { if (menu->npc->vendor_selected) { menu->vendor->talker_visible = false; menu->talker->vendor_visible = true; npcs->npcs[npc_id]->playSound(NPC_VOX_INTRO); } else if (menu->npc->dialog_selected) { menu->vendor->talker_visible = true; menu->talker->vendor_visible = false; } menu->npc->setNPC(NULL); } if (npc_id != -1 && ((interact_distance < INTERACT_RANGE && pc->stats.alive && pc->stats.humanoid) || eventPendingDialog)) { if (menu->talker->vendor_visible && !menu->vendor->talker_visible) { // begin trading menu->vendor->setTab(0); // Show the NPC's inventory as opposed to the buyback tab menu->vendor->npc = npcs->npcs[npc_id]; menu->vendor->setInventory(); menu->closeAll(); menu->talker->visible = false; menu->vendor->visible = true; menu->inv->visible = true; // if this vendor has voice-over, play it if (!npcs->npcs[npc_id]->talker) npcs->npcs[npc_id]->playSound(NPC_VOX_INTRO); snd->play(menu->vendor->sfx_open); menu->talker->vendor_visible = false; menu->vendor->talker_visible = false; } else if (!menu->talker->vendor_visible && menu->vendor->talker_visible && npcs->npcs[npc_id]->talker) { // begin talking if (npcs->npcs[npc_id]->vendor) { menu->talker->vendor_visible = false; menu->vendor->talker_visible = true; } menu->talker->npc = npcs->npcs[npc_id]; menu->talker->chooseDialogNode(menu->npc->selected_dialog_node); pc->allow_movement = npcs->npcs[npc_id]->checkMovement(menu->npc->selected_dialog_node); menu->closeAll(); menu->talker->visible = true; menu->vendor->visible = false; menu->inv->visible = false; menu->talker->vendor_visible = false; menu->vendor->talker_visible = false; } if (eventPendingDialog) eventPendingDialog = false; } // check for walking away from an NPC if (npc_id != -1 && !eventDialogOngoing) { if (interact_distance > INTERACT_RANGE || !pc->stats.alive) { menu->npc->setNPC(NULL); menu->vendor->npc = NULL; menu->talker->npc = NULL; if (menu->vendor->visible || menu->talker->visible || menu->npc->visible) { menu->vendor->visible = false; menu->talker->visible = false; menu->npc->visible = false; } npc_id = -1; } } else if ((!menu->vendor->visible && !menu->talker->visible) || npc_click != -1) { eventDialogOngoing = false; } // reset movement restrictions when we're not in dialog if (!menu->talker->visible) { pc->allow_movement = true; } } void GameStatePlay::checkStash() { float interact_distance; if (mapr->stash) { // If triggered, open the stash and inventory menus menu->closeAll(); menu->inv->visible = true; menu->stash->visible = true; mapr->stash = false; } else { // Close stash if inventory is closed if (!menu->inv->visible) menu->stash->visible = false; // If the player walks away from the stash, close its menu interact_distance = calcDist(pc->stats.pos, mapr->stash_pos); if (interact_distance > INTERACT_RANGE || !pc->stats.alive) { menu->stash->visible = false; } // If the stash has been updated, save the game if (menu->stash->updated) { menu->stash->updated = false; saveGame(); } } } void GameStatePlay::checkCutscene() { if (!mapr->cutscene) return; GameStateCutscene *cutscene = new GameStateCutscene(NULL); if (!cutscene->load(mapr->cutscene_file)) { delete cutscene; mapr->cutscene = false; return; } // handle respawn point and set game play game_slot cutscene->game_slot = game_slot; if (mapr->teleportation) { if (mapr->teleport_mapname != "") mapr->respawn_map = mapr->teleport_mapname; mapr->respawn_point = mapr->teleport_destination; } else { mapr->respawn_point = floor(pc->stats.pos); } saveGame(); delete requestedGameState; requestedGameState = cutscene; } /** * Process all actions for a single frame * This includes some message passing between child object */ void GameStatePlay::logic() { checkCutscene(); // check menus first (top layer gets mouse click priority) menu->logic(); if (!menu->pause) { // these actions only occur when the game isn't paused if (pc->stats.alive) checkLoot(); checkEnemyFocus(); if (pc->stats.alive) { checkNPCInteraction(); mapr->checkHotspots(); mapr->checkNearestEvent(); } checkTitle(); int actionbar_power = menu->act->checkAction(); pc->logic(actionbar_power, restrictPowerUse()); // Transform powers change the actionbar layout, // so we need to prevent accidental clicks if a new power is placed under the slot we clicked on. // It's a bit hacky, but it works if (powers->powers[actionbar_power].type == POWTYPE_TRANSFORM) { menu->act->resetSlots(); } // transfer hero data to enemies, for AI use if (pc->stats.get(STAT_STEALTH) > 100) enemies->hero_stealth = 100; else enemies->hero_stealth = pc->stats.get(STAT_STEALTH); enemies->logic(); hazards->logic(); loot->logic(); enemies->checkEnemiesforXP(); npcs->logic(); snd->logic(pc->stats.pos); } // close menus when the player dies, but still allow them to be reopened if (pc->close_menus) { pc->close_menus = false; menu->closeAll(); } // these actions occur whether the game is paused or not. checkTeleport(); checkLootDrop(); checkLog(); checkEquipmentChange(); checkConsumable(); checkStash(); checkNotifications(); checkCancel(); mapr->logic(); mapr->enemies_cleared = enemies->isCleared(); quests->logic(); // change hero powers on transformation if (pc->setPowers) { pc->setPowers = false; if (!pc->stats.humanoid && menu->pow->visible) menu->closeRight(); // save ActionBar state and lock slots from removing/replacing power for (int i=0; i<12 ; i++) { menu->act->actionbar[i] = menu->act->hotkeys[i]; menu->act->hotkeys[i] = 0; } int count = 10; for (int i=0; i<4 ; i++) { if (pc->charmed_stats->power_index[i] != 0) { menu->act->hotkeys[count] = pc->charmed_stats->power_index[i]; menu->act->locked[count] = true; count++; } if (count == 12) count = 0; } if (pc->stats.manual_untransform && pc->untransform_power > 0) { menu->act->hotkeys[count] = pc->untransform_power; menu->act->locked[count] = true; } else if (pc->stats.manual_untransform && pc->untransform_power == 0) fprintf(stderr, "Untransform power not found, you can't untransform manually\n"); // reapply equipment if the transformation allows it if (pc->stats.transform_with_equipment) menu->inv->applyEquipment(menu->inv->inventory[EQUIPMENT].storage); } // revert hero powers if (pc->revertPowers) { pc->revertPowers = false; // restore ActionBar state for (int i=0; i<12 ; i++) { menu->act->hotkeys[i] = menu->act->actionbar[i]; menu->act->locked[i] = false; } // also reapply equipment here, to account items that give bonuses to base stats menu->inv->applyEquipment(menu->inv->inventory[EQUIPMENT].storage); } // when the hero (re)spawns, reapply equipment & passive effects if (pc->respawn) { pc->stats.alive = true; pc->stats.corpse = false; pc->stats.cur_state = AVATAR_STANCE; menu->inv->applyEquipment(menu->inv->inventory[EQUIPMENT].storage); menu->inv->changed_equipment = true; checkEquipmentChange(); powers->activatePassives(&pc->stats); pc->stats.logic(); pc->stats.recalc(); pc->respawn = false; } } /** * Render all graphics for a single frame */ void GameStatePlay::render() { // Create a list of Renderables from all objects not already on the map. // split the list into the beings alive (may move) and dead beings (must not move) vector rens; vector rens_dead; pc->addRenders(rens); enemies->addRenders(rens, rens_dead); npcs->addRenders(rens); // npcs cannot be dead loot->addRenders(rens, rens_dead); hazards->addRenders(rens, rens_dead); // render the static map layers plus the renderables mapr->render(rens, rens_dead); // mouseover tooltips loot->renderTooltips(mapr->cam); npcs->renderTooltips(mapr->cam, inpt->mouse, nearest_npc); if (mapr->map_change) { menu->mini->prerender(&mapr->collider, mapr->w, mapr->h); mapr->map_change = false; } menu->mini->getMapTitle(mapr->title); menu->mini->render(pc->stats.pos); menu->render(); // render combat text last - this should make it obvious you're being // attacked, even if you have menus open CombatText *combat_text = comb; combat_text->setCam(mapr->cam); combat_text->render(); } void GameStatePlay::showLoading() { if (!loading_bg) return; SDL_Rect dest; dest.x = VIEW_W_HALF - loading_bg->w/2; dest.y = VIEW_H_HALF - loading_bg->h/2; SDL_BlitSurface(loading_bg,NULL,screen,&dest); loading->render(); SDL_Flip(screen); } Avatar *GameStatePlay::getAvatar() const { return pc; } GameStatePlay::~GameStatePlay() { delete quests; delete npcs; delete hazards; delete enemies; delete pc; delete mapr; delete menu; delete loot; delete camp; delete items; delete powers; delete loading; delete enemyg; SDL_FreeSurface(loading_bg); } flare-engine-0.19/src/GameStatePlay.h000066400000000000000000000045221224717101500174420ustar00rootroot00000000000000/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class GameStatePlay * * Handles logic and rendering of the main action game play * Also handles message passing between child objects, often to avoid circular dependencies. */ #pragma once #ifndef GAMESTATEPLAY_H #define GAMESTATEPLAY_H #include "CommonIncludes.h" #include "GameState.h" class Avatar; class Enemy; class HazardManager; class MenuManager; class NPCManager; class QuestLog; class WidgetLabel; class Title{ public: std::string title; int level; int power; std::string requires_status; std::string requires_not; std::string primary_stat; Title() : title("") , level(0) , power(0) , requires_status("") , requires_not("") , primary_stat("") {} }; class GameStatePlay : public GameState { private: Enemy *enemy; HazardManager *hazards; MenuManager *menu; NPCManager *npcs; QuestLog *quests; WidgetLabel *loading; SDL_Surface *loading_bg; bool restrictPowerUse(); void checkEnemyFocus(); void checkLoot(); void checkLootDrop(); void checkTeleport(); void checkCancel(); void checkLog(); void checkEquipmentChange(); void checkTitle(); void checkConsumable(); void checkNotifications(); void checkNPCInteraction(); void checkStash(); void checkCutscene(); void showLoading(); void loadTitles(); int npc_id; bool eventDialogOngoing; bool eventPendingDialog; SDL_Color color_normal; std::vector titles; int nearest_npc; public: GameStatePlay(); ~GameStatePlay(); void initialize(); void logic(); void render(); void showFPS(int fps); void saveGame(); void loadGame(); void loadClass(int index); void loadStash(); void resetGame(); int game_slot; Avatar *getAvatar() const; }; #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/GameStateTitle.cpp������������������������������������������������������������0000664�0000000�0000000�00000007711�12247171015�0020154�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "CommonIncludes.h" #include "GameStateConfig.h" #include "GameStateCutscene.h" #include "GameStateLoad.h" #include "GameStateTitle.h" #include "Settings.h" #include "SharedResources.h" #include "WidgetButton.h" #include "WidgetLabel.h" GameStateTitle::GameStateTitle() : GameState() { exit_game = false; load_game = false; logo = loadGraphicSurface("images/menus/logo.png"); // set up buttons button_play = new WidgetButton("images/menus/buttons/button_default.png"); button_exit = new WidgetButton("images/menus/buttons/button_default.png"); button_cfg = new WidgetButton("images/menus/buttons/button_default.png"); button_credits = new WidgetButton("images/menus/buttons/button_default.png"); button_play->label = msg->get("Play Game"); button_play->pos.x = VIEW_W_HALF - button_play->pos.w/2; button_play->pos.y = VIEW_H - (button_exit->pos.h*4); if (!ENABLE_PLAYGAME) { button_play->enabled = false; button_play->tooltip = msg->get("Enable a core mod to continue"); } button_play->refresh(); button_cfg->label = msg->get("Configuration"); button_cfg->pos.x = VIEW_W_HALF - button_cfg->pos.w/2; button_cfg->pos.y = VIEW_H - (button_exit->pos.h*3); button_cfg->refresh(); button_credits->label = msg->get("Credits"); button_credits->pos.x = VIEW_W_HALF - button_credits->pos.w/2; button_credits->pos.y = VIEW_H - (button_exit->pos.h*2); button_credits->refresh(); button_exit->label = msg->get("Exit Game"); button_exit->pos.x = VIEW_W_HALF - button_exit->pos.w/2; button_exit->pos.y = VIEW_H - button_exit->pos.h; button_exit->refresh(); // set up labels label_version = new WidgetLabel(); label_version->set(VIEW_W, 0, JUSTIFY_RIGHT, VALIGN_TOP, msg->get("Flare Alpha v0.19"), font->getColor("menu_normal")); // Setup tab order tablist.add(button_play); tablist.add(button_cfg); tablist.add(button_credits); tablist.add(button_exit); } void GameStateTitle::logic() { button_play->enabled = ENABLE_PLAYGAME; snd->logic(FPoint(0,0)); if(inpt->pressing[CANCEL] && !inpt->lock[CANCEL]) { inpt->lock[CANCEL] = true; exitRequested = true; } tablist.logic(); if (button_play->checkClick()) { delete requestedGameState; requestedGameState = new GameStateLoad(); } else if (button_cfg->checkClick()) { delete requestedGameState; requestedGameState = new GameStateConfig(); } else if (button_credits->checkClick()) { GameStateTitle *title = new GameStateTitle(); GameStateCutscene *credits = new GameStateCutscene(title); if (!credits->load("credits.txt")) { delete credits; delete title; } else { delete requestedGameState; requestedGameState = credits; } } else if (button_exit->checkClick()) { exitRequested = true; } } void GameStateTitle::render() { SDL_Rect src; SDL_Rect dest; // display logo centered if (logo) { src.x = src.y = 0; src.w = dest.w = logo->w; src.h = dest.h = logo->h; dest.x = VIEW_W_HALF - (logo->w/2); dest.y = VIEW_H_HALF - (logo->h/2); SDL_BlitSurface(logo, &src, screen, &dest); } // display buttons button_play->render(); button_cfg->render(); button_credits->render(); button_exit->render(); // version number label_version->render(); } GameStateTitle::~GameStateTitle() { delete button_play; delete button_cfg; delete button_credits; delete button_exit; delete label_version; SDL_FreeSurface(logo); } �������������������������������������������������������flare-engine-0.19/src/GameStateTitle.h��������������������������������������������������������������0000664�0000000�0000000�00000002237�12247171015�0017617�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #pragma once #ifndef GAMESTATETITLE_H #define GAMESTATETITLE_H #include "GameState.h" #include "Widget.h" class WidgetButton; class WidgetLabel; class GameStateTitle : public GameState { private: SDL_Surface *logo; WidgetButton *button_play; WidgetButton *button_exit; WidgetButton *button_cfg; WidgetButton *button_credits; WidgetLabel *label_version; TabList tablist; public: GameStateTitle(); ~GameStateTitle(); void logic(); void render(); // switch bool exit_game; bool load_game; }; #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/GameSwitcher.cpp��������������������������������������������������������������0000664�0000000�0000000�00000010133�12247171015�0017652�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /* * class GameSwitcher * * State machine handler between main game modes that take up the entire view/control * * Examples: * - the main gameplay (GameEngine class) * - title screen * - new game screen (character create) * - load game screen * - maybe full-video cutscenes */ #include "GameSwitcher.h" #include "GameStateTitle.h" #include "GameStateCutscene.h" #include "SharedResources.h" #include "Settings.h" #include "FileParser.h" #include "UtilsParsing.h" #include <typeinfo> using namespace std; GameSwitcher::GameSwitcher() { // The initial state is the intro cutscene and then title screen GameStateTitle *title=new GameStateTitle(); GameStateCutscene *intro = new GameStateCutscene(title); currentState = intro; if (!intro->load("intro.txt")) { delete intro; currentState = title; } label_fps = new WidgetLabel(); done = false; music = NULL; loadMusic(); loadFPS(); } void GameSwitcher::loadMusic() { if (AUDIO && MUSIC_VOLUME) { Mix_FreeMusic(music); music = Mix_LoadMUS((mods->locate("music/title_theme.ogg")).c_str()); if (!music) printf("Mix_LoadMUS: %s\n", Mix_GetError()); } if (music) { Mix_VolumeMusic(MUSIC_VOLUME); Mix_PlayMusic(music, -1); } } void GameSwitcher::logic() { // Check if a the game state is to be changed and change it if necessary, deleting the old state GameState* newState = currentState->getRequestedGameState(); if (newState != NULL) { delete currentState; currentState = newState; // reload the fps meter position loadFPS(); // if this game state does not provide music, use the title theme if (!currentState->hasMusic) if (!Mix_PlayingMusic()) if (music) Mix_PlayMusic(music, -1); } currentState->logic(); // Check if the GameState wants to quit the application done = currentState->isExitRequested(); if (currentState->reload_music) { loadMusic(); currentState->reload_music = false; } } void GameSwitcher::showFPS(int fps) { if (!SHOW_FPS) return; string sfps = toString(typeid(fps), &fps) + string(" fps"); label_fps->set(fps_position.x, fps_position.y, JUSTIFY_LEFT, VALIGN_TOP, sfps, fps_color); label_fps->render(); } void GameSwitcher::loadFPS() { // Load FPS rendering settings FileParser infile; if (infile.open("menus/fps.txt")) { while(infile.next()) { infile.val = infile.val + ','; if(infile.key == "position") { fps_position.x = eatFirstInt(infile.val,','); fps_position.y = eatFirstInt(infile.val,','); fps_corner = eatFirstString(infile.val,','); } else if(infile.key == "color") { fps_color.r = eatFirstInt(infile.val,','); fps_color.g = eatFirstInt(infile.val,','); fps_color.b = eatFirstInt(infile.val,','); } } infile.close(); } // this is a dummy string used to approximate the fps position when aligned to the right font->setFont("font_regular"); int w = font->calc_width("00 fps"); int h = font->getLineHeight(); if (fps_corner == "top_left") { // relative to {0,0}, so no changes } else if (fps_corner == "top_right") { fps_position.x += VIEW_W-w; } else if (fps_corner == "bottom_left") { fps_position.y += VIEW_H-h; } else if (fps_corner == "bottom_right") { fps_position.x += VIEW_W-w; fps_position.y += VIEW_H-h; } } void GameSwitcher::render() { currentState->render(); } GameSwitcher::~GameSwitcher() { delete currentState; delete label_fps; Mix_FreeMusic(music); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/GameSwitcher.h����������������������������������������������������������������0000664�0000000�0000000�00000003161�12247171015�0017322�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #pragma once #ifndef GAME_SWITCHER_H #define GAME_SWITCHER_H #include "CommonIncludes.h" #include "Utils.h" const int GAME_STATE_TITLE = 0; const int GAME_STATE_PLAY = 1; const int GAME_STATE_LOAD = 2; const int GAME_STATE_NEW = 3; class GameState; class WidgetLabel; /** * class GameSwitcher * * State machine handler between main game modes that take up the entire view/control * * Examples: * - the main gameplay (GameEngine class) * - title screen * - new game screen (character create) * - load game screen * - maybe full-video cutscenes */ class GameSwitcher { private: Mix_Music *music; GameState *currentState; WidgetLabel *label_fps; Point fps_position; SDL_Color fps_color; std::string fps_corner; public: GameSwitcher(); GameSwitcher(const GameSwitcher ©); // not implemented. ~GameSwitcher(); void loadMusic(); void loadFPS(); void logic(); void render(); void showFPS(int fps); bool done; }; #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/GetText.cpp�������������������������������������������������������������������0000664�0000000�0000000�00000005516�12247171015�0016665�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "GetText.h" #include "UtilsParsing.h" using namespace std; GetText::GetText() : line("") , key("") , val("") , fuzzy(false) { } bool GetText::open(const string& filename) { infile.open(filename.c_str(), ios::in); return infile.is_open(); } void GetText::close() { if (infile.is_open()) infile.close(); } // Turns all \" into just " string GetText::sanitize(string message) { signed int pos = 0; while ((pos = message.find("\\\"")) != -1) { message = message.substr(0, pos) + message.substr(pos+1); } return message; } /** * Advance to the next key pair * * @return false if EOF, otherwise true */ bool GetText::next() { key = ""; val = ""; fuzzy = false; while (infile.good()) { line = getLine(infile); // check if comment and if fuzzy if (line.compare(0,2,"#,") && line.find("fuzzy") == 0) fuzzy = true; // this is a key if (line.find("msgid") == 0) { // grab only what's contained in the quotes key = line.substr(6); key = key.substr(1, key.length()-2); //strips off "s key = sanitize(key); if (key != "") continue; else { // It is a multi-line value, unless it is the first msgid, in which case it will be empty // and it will be ignored when finding the matching msgstr, so no big deal. line = getLine(infile); while(line.find("\"") == 0) { // We remove the double quotes. key += line.substr(1, line.length()-2); line = getLine(infile); } } } // this is a value if (line.find("msgstr") == 0) { // grab only what's contained in the quotes val = line.substr(7); val = val.substr(1, val.length()-2); //strips off "s val = sanitize(val); // handle keypairs if (key != "") { if(val != "") { // One-line value found. return true; } else { // Might be a multi-line value. line = getLine(infile); while(line.find("\"") == 0) { // We remove the double quotes. val += line.substr(1, line.length()-2); line = getLine(infile); } if(val != "") { // It was a multi-line value indeed. return true; } } } } } // hit the end of file return false; } GetText::~GetText() { close(); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/GetText.h���������������������������������������������������������������������0000664�0000000�0000000�00000002310�12247171015�0016317�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Thane Brimhall & Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * GetText * * Abstract the generic key-value pair handling from the gettext .po file format. * We don't need full gettext functionality (yet) so this is a simple solution. */ #pragma once #ifndef GET_TEXT_H #define GET_TEXT_H #include "CommonIncludes.h" class GetText { private: std::ifstream infile; std::string line; std::string sanitize(std::string input); public: GetText(); ~GetText(); bool open(const std::string& filename); void close(); bool next(); std::string key; std::string val; bool fuzzy; }; #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/Hazard.cpp��������������������������������������������������������������������0000664�0000000�0000000�00000007004�12247171015�0016504�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class Hazard * * Stand-alone object that can harm the hero or creatures * These are generated whenever something makes any attack */ #include "Animation.h" #include "AnimationSet.h" #include "AnimationManager.h" #include "FileParser.h" #include "Hazard.h" #include "MapCollision.h" #include "SharedResources.h" #include "Settings.h" #include "UtilsParsing.h" #include <cmath> using namespace std; Hazard::Hazard(MapCollision *_collider) : collider(_collider) , activeAnimation(NULL) , animation_name("") , src_stats(NULL) , dmg_min(0) , dmg_max(0) , crit_chance(0) , accuracy(0) , source_type(0) , target_party(false) , pos() , speed() , base_speed(0) , lifespan(1) , radius(0) , power_index(0) , animationKind(0) , on_floor(false) , delay_frames(0) , complete_animation(false) , multitarget(false) , active(true) , remove_now(false) , hit_wall(false) , hp_steal(0) , mp_steal(0) , trait_armor_penetration(false) , trait_crits_impaired(0) , trait_elemental(-1) , beacon(false) , post_power(0) , wall_power(0) , mod_power(0) { } Hazard::~Hazard() { if (activeAnimation) { anim->decreaseCount(animation_name); delete activeAnimation; } } void Hazard::logic() { // if the hazard is on delay, take no action if (delay_frames > 0) { delay_frames--; return; } // handle tickers if (lifespan > 0) lifespan--; if (activeAnimation) activeAnimation->advanceFrame(); // handle movement if (!(speed.x == 0 && speed.y == 0)) { pos.x += speed.x; pos.y += speed.y; // very simplified collider, could skim around corners // or even pass through thin walls if speed > tilesize if (collider->is_wall(pos.x, pos.y)) { lifespan = 0; hit_wall = true; if (collider->is_outside_map((int)floor(pos.x), (int)floor(pos.y))) remove_now = true; } } } void Hazard::loadAnimation(std::string &s) { if (activeAnimation) { anim->decreaseCount(animation_name); delete activeAnimation; activeAnimation = 0; } animation_name = s; if (animation_name != "") { anim->increaseCount(animation_name); AnimationSet *animationSet = anim->getAnimationSet(animation_name); activeAnimation = animationSet->getAnimation(); } } bool Hazard::isDangerousNow() { return active && (delay_frames == 0) && ( (activeAnimation != NULL && activeAnimation->isActiveFrame()) || activeAnimation == NULL); } bool Hazard::hasEntity(Entity *ent) { for(vector<Entity*>::iterator it = entitiesCollided.begin(); it != entitiesCollided.end(); ++it) if(*it == ent) return true; return false; } void Hazard::addEntity(Entity *ent) { entitiesCollided.push_back(ent); } void Hazard::addRenderable(vector<Renderable> &r, vector<Renderable> &r_dead) { if (delay_frames == 0 && activeAnimation) { Renderable re = activeAnimation->getCurrentFrame(animationKind); re.map_pos.x = pos.x; re.map_pos.y = pos.y; (on_floor ? r_dead : r).push_back(re); } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/Hazard.h����������������������������������������������������������������������0000664�0000000�0000000�00000005537�12247171015�0016162�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class Hazard * * Stand-alone object that can harm the hero or creatures * These are generated whenever something makes any attack */ #pragma once #ifndef HAZARD_H #define HAZARD_H class Entity; #include "CommonIncludes.h" #include "Utils.h" class Animation; class StatBlock; class MapCollision; // the spell/power's source type: eg. which team did it come from? const int SOURCE_TYPE_HERO = 0; const int SOURCE_TYPE_NEUTRAL = 1; const int SOURCE_TYPE_ENEMY = 2; const int SOURCE_TYPE_ALLY = 3; class Hazard { private: const MapCollision *collider; // Keeps track of entities already hit std::vector<Entity*> entitiesCollided; Animation *activeAnimation; std::string animation_name; public: Hazard(MapCollision *_collider); Hazard(const Hazard&); // not implemented! If you implement this, take care to create a real copy of the pointers, such as Animation. Hazard & operator= (const Hazard & other); // same as copy constructor! ~Hazard(); StatBlock *src_stats; void logic(); bool hasEntity(Entity*); void addEntity(Entity*); void loadAnimation(std::string &s); int dmg_min; int dmg_max; int crit_chance; int accuracy; int source_type; bool target_party; FPoint pos; FPoint speed; float base_speed; int lifespan; // ticks down to zero float radius; int power_index; int animationKind; // direction or other, it is a specific value according to // some hazard animations are 8-directional // some hazard animations have random/varietal options bool isDangerousNow(); void addRenderable(std::vector<Renderable> &r, std::vector<Renderable> &r_dead); bool on_floor; // rendererable goes on the floor layer int delay_frames; bool complete_animation; // if not multitarget but hitting a creature, still complete the animation? // these work in conjunction // if the attack is not multitarget, set active=false // only process active hazards for collision bool multitarget; bool active; bool remove_now; bool hit_wall; // after effects of various powers int hp_steal; int mp_steal; bool trait_armor_penetration; int trait_crits_impaired; int trait_elemental; bool beacon; // pre/post power effects int post_power; int wall_power; int mod_power; }; #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/HazardManager.cpp�������������������������������������������������������������0000664�0000000�0000000�00000012550�12247171015�0020001�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class HazardManager * * Holds the collection of hazards (active attacks, spells, etc) and handles group operations */ #include "Avatar.h" #include "Animation.h" #include "EnemyManager.h" #include "Hazard.h" #include "HazardManager.h" #include "SharedGameResources.h" using namespace std; HazardManager::HazardManager() : last_enemy(NULL) { } void HazardManager::logic() { // remove all hazards with lifespan 0. Most hazards still display their last frame. for (int i=h.size()-1; i>=0; i--) { if (h[i]->lifespan == 0) expire(i); } checkNewHazards(); // handle single-frame transforms for (int i=h.size()-1; i>=0; i--) { h[i]->logic(); // remove all hazards that need to die immediately (e.g. exit the map) if (h[i]->remove_now) { expire(i); continue; } // if a moving hazard hits a wall, check for an after-effect if (h[i]->hit_wall && h[i]->wall_power > 0) { powers->activate(h[i]->wall_power, h[i]->src_stats, h[i]->pos); if (powers->powers[h[i]->wall_power].directional) powers->hazards.back()->animationKind = h[i]->animationKind; } } bool hit; // handle collisions for (unsigned int i=0; i<h.size(); i++) { if (h[i]->isDangerousNow()) { // process hazards that can hurt enemies if (h[i]->source_type != SOURCE_TYPE_ENEMY) { //hero or neutral sources for (unsigned int eindex = 0; eindex < enemies->enemies.size(); eindex++) { // only check living enemies if (enemies->enemies[eindex]->stats.hp > 0 && h[i]->active && (enemies->enemies[eindex]->stats.hero_ally == h[i]->target_party)) { if (isWithin(h[i]->pos, h[i]->radius, enemies->enemies[eindex]->stats.pos)) { if (!h[i]->hasEntity(enemies->enemies[eindex])) { h[i]->addEntity(enemies->enemies[eindex]); if (!h[i]->beacon) last_enemy = enemies->enemies[eindex]; // hit! hit = enemies->enemies[eindex]->takeHit(*h[i]); if (!h[i]->multitarget && hit) { h[i]->active = false; if (!h[i]->complete_animation) h[i]->lifespan = 0; } } } } } } // process hazards that can hurt the hero if (h[i]->source_type != SOURCE_TYPE_HERO && h[i]->source_type != SOURCE_TYPE_ALLY) { //enemy or neutral sources if (pc->stats.hp > 0 && h[i]->active) { if (isWithin(h[i]->pos, h[i]->radius, pc->stats.pos)) { if (!h[i]->hasEntity(pc)) { h[i]->addEntity(pc); // hit! hit = pc->takeHit(*h[i]); if (!h[i]->multitarget && hit) { h[i]->active = false; if (!h[i]->complete_animation) h[i]->lifespan = 0; } } } } //now process allies for (unsigned int eindex = 0; eindex < enemies->enemies.size(); eindex++) { // only check living allies if (enemies->enemies[eindex]->stats.hp > 0 && h[i]->active && enemies->enemies[eindex]->stats.hero_ally) { if (isWithin(h[i]->pos, h[i]->radius, enemies->enemies[eindex]->stats.pos)) { if (!h[i]->hasEntity(enemies->enemies[eindex])) { h[i]->addEntity(enemies->enemies[eindex]); // hit! hit = enemies->enemies[eindex]->takeHit(*h[i]); if (!h[i]->multitarget && hit) { h[i]->active = false; if (!h[i]->complete_animation) h[i]->lifespan = 0; } } } } } } } } } /** * Look for hazards generated this frame * TODO: all these hazards will originate from PowerManager instead */ void HazardManager::checkNewHazards() { // check PowerManager for hazards while (!powers->hazards.empty()) { Hazard *new_haz = powers->hazards.front(); powers->hazards.pop(); //new_haz->setCollision(collider); h.push_back(new_haz); } // check hero hazards if (pc->haz != NULL) { h.push_back(pc->haz); pc->haz = NULL; } // check monster hazards for (unsigned int eindex = 0; eindex < enemies->enemies.size(); eindex++) { if (enemies->enemies[eindex]->haz != NULL) { h.push_back(enemies->enemies[eindex]->haz); enemies->enemies[eindex]->haz = NULL; } } } void HazardManager::expire(int index) { delete h[index]; h.erase(h.begin()+index); } /** * Reset all hazards and get new collision object */ void HazardManager::handleNewMap() { for (unsigned int i = 0; i < h.size(); i++) delete h[i]; h.clear(); last_enemy = NULL; } /** * addRenders() * Map objects need to be drawn in Z order, so we allow a parent object (GameEngine) * to collect all mobile sprites each frame. */ void HazardManager::addRenders(vector<Renderable> &r, vector<Renderable> &r_dead) { for (unsigned int i=0; i<h.size(); i++) h[i]->addRenderable(r, r_dead); } HazardManager::~HazardManager() { for (unsigned int i = 0; i < h.size(); i++) delete h[i]; // h.clear(); not needed in destructor last_enemy = NULL; } ��������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/HazardManager.h���������������������������������������������������������������0000664�0000000�0000000�00000002311�12247171015�0017440�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class HazardManager * * Holds the collection of hazards (active attacks, spells, etc) and handles group operations */ #pragma once #ifndef HAZARD_MANAGER_H #define HAZARD_MANAGER_H #include "CommonIncludes.h" #include "Utils.h" class Avatar; class Hazard; class HazardManager { public: HazardManager(); ~HazardManager(); void logic(); void expire(int index); void checkNewHazards(); void handleNewMap(); void addRenders(std::vector<Renderable> &r, std::vector<Renderable> &r_dead); std::vector<Hazard*> h; Enemy* last_enemy; }; #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/ImageManager.cpp��������������������������������������������������������������0000664�0000000�0000000�00000005217�12247171015�0017614�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "CommonIncludes.h" #include "ImageManager.h" #include "Settings.h" #include "SharedResources.h" #include <assert.h> using namespace std; ImageManager::ImageManager() { } ImageManager::~ImageManager() { cleanUp(); // NDEBUG is used by posix to disable assertions, so use the same MACRO. #ifndef NDEBUG if (!sprites.empty()) { fprintf(stderr, "ImageManager still holding these images:\n"); for (unsigned i = 0; i < sprites.size(); ++i) fprintf(stderr, "%s %d\n", names[i].c_str(), counts[i]); } assert(sprites.size() == 0); #endif } SDL_Surface *ImageManager::getSurface(const std::string &name) { vector<string>::iterator found = find(names.begin(), names.end(), name); if (found != names.end()) { int index = distance(names.begin(), found); if (!sprites[index]) { if (!TEXTURE_QUALITY) { string newname = string(name); newname.replace(name.rfind("/"), 0, "/noalpha"); sprites[index] = loadGraphicSurface(newname, "Falling back to alpha version", false, true); } if (!sprites[index]) sprites[index] = loadGraphicSurface(name); } return sprites[index]; } return 0; } void ImageManager::increaseCount(const std::string &name) { vector<string>::iterator found = find(names.begin(), names.end(), name); if (found != names.end()) { int index = distance(names.begin(), found); counts[index]++; } else { sprites.push_back(0); names.push_back(name); counts.push_back(1); } } void ImageManager::decreaseCount(const std::string &name) { vector<string>::iterator found = find(names.begin(), names.end(), name); if (found != names.end()) { int index = distance(names.begin(), found); counts[index]--; } else { fprintf(stderr, "ImageManager::decreaseCount: Couldn't decrease image count: %s\n", name.c_str()); } } void ImageManager::cleanUp() { int i = sprites.size() - 1; while (i >= 0) { if (counts[i] <= 0) { SDL_FreeSurface(sprites[i]); counts.erase(counts.begin()+i); sprites.erase(sprites.begin()+i); names.erase(names.begin()+i); } --i; } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/ImageManager.h����������������������������������������������������������������0000664�0000000�0000000�00000003475�12247171015�0017265�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #pragma once #ifndef __IMAGE_MANAGER__ #define __IMAGE_MANAGER__ #include "CommonIncludes.h" /** * The image manager class is a manager for images of any kind. * It makes sure there are no images loaded twice, but returns the appropriate * references to the already loaded image. * * The API is designed for lazy loading of images, so on map change events, * which renews most images, this manager tries not to reload the images * but rather keep them in memory. */ class ImageManager { private: std::vector<SDL_Surface*> sprites; std::vector<std::string> names; std::vector<int> counts; public: ImageManager(); ~ImageManager(); /** * Returns the image specified by the filename as parameter. * The image must be in the pool already, i.e. the increaseCount * function with the same parameter must be called before. */ SDL_Surface *getSurface(const std::string &name); /** * Decreases the count for this image. */ void decreaseCount(const std::string &name); /** * Increases the count for this image. */ void increaseCount(const std::string &name); /** * Removes all images with count equal zero. */ void cleanUp(); }; #endif // __IMAGE_MANAGER__ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/InputState.cpp����������������������������������������������������������������0000664�0000000�0000000�00000046712�12247171015�0017404�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class InputState * * Handles keyboard and mouse states */ #include "CommonIncludes.h" #include "FileParser.h" #include "InputState.h" #include "Settings.h" #include "SharedResources.h" #include "UtilsDebug.h" #include "UtilsParsing.h" using namespace std; InputState::InputState(void) : done(false) , mouse() , last_key(0) , last_button(0) , scroll_up(false) , scroll_down(false) { SDL_EnableUNICODE(true); defaultQwertyKeyBindings(); defaultJoystickBindings(); for (int key=0; key<key_count; key++) { pressing[key] = false; lock[key] = false; } loadKeyBindings(); setKeybindNames(); } void InputState::defaultQwertyKeyBindings () { binding[CANCEL] = SDLK_ESCAPE; binding[ACCEPT] = SDLK_RETURN; binding[UP] = SDLK_w; binding[DOWN] = SDLK_s; binding[LEFT] = SDLK_a; binding[RIGHT] = SDLK_d; binding_alt[CANCEL] = SDLK_ESCAPE; binding_alt[ACCEPT] = SDLK_SPACE; binding_alt[UP] = SDLK_UP; binding_alt[DOWN] = SDLK_DOWN; binding_alt[LEFT] = SDLK_LEFT; binding_alt[RIGHT] = SDLK_RIGHT; binding[BAR_1] = binding_alt[BAR_1] = SDLK_1; binding[BAR_2] = binding_alt[BAR_2] = SDLK_2; binding[BAR_3] = binding_alt[BAR_3] = SDLK_3; binding[BAR_4] = binding_alt[BAR_4] = SDLK_4; binding[BAR_5] = binding_alt[BAR_5] = SDLK_5; binding[BAR_6] = binding_alt[BAR_6] = SDLK_6; binding[BAR_7] = binding_alt[BAR_7] = SDLK_7; binding[BAR_8] = binding_alt[BAR_8] = SDLK_8; binding[BAR_9] = binding_alt[BAR_9] = SDLK_9; binding[BAR_0] = binding_alt[BAR_0] = SDLK_0; binding[CHARACTER] = binding_alt[CHARACTER] = SDLK_c; binding[INVENTORY] = binding_alt[INVENTORY] = SDLK_i; binding[POWERS] = binding_alt[POWERS] = SDLK_p; binding[LOG] = binding_alt[LOG] = SDLK_l; binding[MAIN1] = binding_alt[MAIN1] = SDL_BUTTON_LEFT; binding[MAIN2] = binding_alt[MAIN2] = SDL_BUTTON_RIGHT; binding[CTRL] = SDLK_LCTRL; binding_alt[CTRL] = SDLK_RCTRL; binding[SHIFT] = SDLK_LSHIFT; binding_alt[SHIFT] = SDLK_RSHIFT; binding[DEL] = SDLK_DELETE; binding_alt[DEL] = SDLK_BACKSPACE; binding[ACTIONBAR] = SDLK_b; binding_alt[ACTIONBAR] = SDLK_b; binding[ACTIONBAR_BACK] = SDLK_z; binding_alt[ACTIONBAR_BACK] = SDLK_z; binding[ACTIONBAR_FORWARD] = SDLK_x; binding_alt[ACTIONBAR_FORWARD] = SDLK_x; binding[ACTIONBAR_USE] = SDLK_n; binding_alt[ACTIONBAR_USE] = SDLK_n; } void InputState::defaultJoystickBindings () { // most joystick buttons are unbound by default for (int key=0; key<key_count; key++) { binding_joy[key] = -1; } // TODO make these configurable from the config menu binding_joy[CANCEL] = 0; binding_joy[ACCEPT] = 1; binding_joy[ACTIONBAR] = 2; binding_joy[ACTIONBAR_USE] = 3; binding_joy[ACTIONBAR_BACK] = 4; binding_joy[ACTIONBAR_FORWARD] = 5; } /** * Key bindings are found in config/keybindings.txt */ void InputState::loadKeyBindings() { FileParser infile; if (!infile.open(PATH_CONF + FILE_KEYBINDINGS, false, true, "")) { if (!infile.open("engine/default_keybindings.txt", true, true, "")) { saveKeyBindings(); return; } else saveKeyBindings(); } while (infile.next()) { infile.val = infile.val + ','; int key1 = eatFirstInt(infile.val, ','); int key2 = eatFirstInt(infile.val, ','); // if we're loading an older keybindings file, we need to unbind all joystick bindings int key3 = -1; std::string temp = infile.val; if (eatFirstString(temp, ',') != "") { key3 = eatFirstInt(infile.val, ','); } int cursor = -1; if (infile.key == "cancel") cursor = CANCEL; else if (infile.key == "accept") cursor = ACCEPT; else if (infile.key == "up") cursor = UP; else if (infile.key == "down") cursor = DOWN; else if (infile.key == "left") cursor = LEFT; else if (infile.key == "right") cursor = RIGHT; else if (infile.key == "bar1") cursor = BAR_1; else if (infile.key == "bar2") cursor = BAR_2; else if (infile.key == "bar3") cursor = BAR_3; else if (infile.key == "bar4") cursor = BAR_4; else if (infile.key == "bar5") cursor = BAR_5; else if (infile.key == "bar6") cursor = BAR_6; else if (infile.key == "bar7") cursor = BAR_7; else if (infile.key == "bar8") cursor = BAR_8; else if (infile.key == "bar9") cursor = BAR_9; else if (infile.key == "bar0") cursor = BAR_0; else if (infile.key == "main1") cursor = MAIN1; else if (infile.key == "main2") cursor = MAIN2; else if (infile.key == "character") cursor = CHARACTER; else if (infile.key == "inventory") cursor = INVENTORY; else if (infile.key == "powers") cursor = POWERS; else if (infile.key == "log") cursor = LOG; else if (infile.key == "ctrl") cursor = CTRL; else if (infile.key == "shift") cursor = SHIFT; else if (infile.key == "delete") cursor = DEL; else if (infile.key == "actionbar") cursor = ACTIONBAR; else if (infile.key == "actionbar_back") cursor = ACTIONBAR_BACK; else if (infile.key == "actionbar_forward") cursor = ACTIONBAR_FORWARD; else if (infile.key == "actionbar_use") cursor = ACTIONBAR_USE; if (cursor != -1) { binding[cursor] = key1; binding_alt[cursor] = key2; binding_joy[cursor] = key3; } } infile.close(); } /** * Write current key bindings to config file */ void InputState::saveKeyBindings() { ofstream outfile; outfile.open((PATH_CONF + FILE_KEYBINDINGS).c_str(), ios::out); if (outfile.is_open()) { outfile << "cancel=" << binding[CANCEL] << "," << binding_alt[CANCEL] << "," << binding_joy[CANCEL] << "\n"; outfile << "accept=" << binding[ACCEPT] << "," << binding_alt[ACCEPT] << "," << binding_joy[ACCEPT] << "\n"; outfile << "up=" << binding[UP] << "," << binding_alt[UP] << "," << binding_joy[UP] << "\n"; outfile << "down=" << binding[DOWN] << "," << binding_alt[DOWN] << "," << binding_joy[DOWN] << "\n"; outfile << "left=" << binding[LEFT] << "," << binding_alt[LEFT] << "," << binding_joy[LEFT] << "\n"; outfile << "right=" << binding[RIGHT] << "," << binding_alt[RIGHT] << "," << binding_joy[RIGHT] << "\n"; outfile << "bar1=" << binding[BAR_1] << "," << binding_alt[BAR_1] << "," << binding_joy[BAR_1] << "\n"; outfile << "bar2=" << binding[BAR_2] << "," << binding_alt[BAR_2] << "," << binding_joy[BAR_2] << "\n"; outfile << "bar3=" << binding[BAR_3] << "," << binding_alt[BAR_3] << "," << binding_joy[BAR_3] << "\n"; outfile << "bar4=" << binding[BAR_4] << "," << binding_alt[BAR_4] << "," << binding_joy[BAR_4] << "\n"; outfile << "bar5=" << binding[BAR_5] << "," << binding_alt[BAR_5] << "," << binding_joy[BAR_5] << "\n"; outfile << "bar6=" << binding[BAR_6] << "," << binding_alt[BAR_6] << "," << binding_joy[BAR_6] << "\n"; outfile << "bar7=" << binding[BAR_7] << "," << binding_alt[BAR_7] << "," << binding_joy[BAR_7] << "\n"; outfile << "bar8=" << binding[BAR_8] << "," << binding_alt[BAR_8] << "," << binding_joy[BAR_8] << "\n"; outfile << "bar9=" << binding[BAR_9] << "," << binding_alt[BAR_9] << "," << binding_joy[BAR_9] << "\n"; outfile << "bar0=" << binding[BAR_0] << "," << binding_alt[BAR_0] << "," << binding_joy[BAR_0] << "\n"; outfile << "main1=" << binding[MAIN1] << "," << binding_alt[MAIN1] << "," << binding_joy[MAIN1] << "\n"; outfile << "main2=" << binding[MAIN2] << "," << binding_alt[MAIN2] << "," << binding_joy[MAIN2] << "\n"; outfile << "character=" << binding[CHARACTER] << "," << binding_alt[CHARACTER] << "," << binding_joy[CHARACTER] << "\n"; outfile << "inventory=" << binding[INVENTORY] << "," << binding_alt[INVENTORY] << "," << binding_joy[INVENTORY] << "\n"; outfile << "powers=" << binding[POWERS] << "," << binding_alt[POWERS] << "," << binding_joy[POWERS] << "\n"; outfile << "log=" << binding[LOG] << "," << binding_alt[LOG] << "," << binding_joy[LOG] << "\n"; outfile << "ctrl=" << binding[CTRL] << "," << binding_alt[CTRL] << "," << binding_joy[CTRL] << "\n"; outfile << "shift=" << binding[SHIFT] << "," << binding_alt[SHIFT] << "," << binding_joy[SHIFT] << "\n"; outfile << "delete=" << binding[DEL] << "," << binding_alt[DEL] << "," << binding_joy[DEL] << "\n"; outfile << "actionbar=" << binding[ACTIONBAR] << "," << binding_alt[ACTIONBAR] << "," << binding_joy[ACTIONBAR] << "\n"; outfile << "actionbar_back=" << binding[ACTIONBAR_BACK] << "," << binding_alt[ACTIONBAR_BACK] << "," << binding_joy[ACTIONBAR_BACK] << "\n"; outfile << "actionbar_forward=" << binding[ACTIONBAR_FORWARD] << "," << binding_alt[ACTIONBAR_FORWARD] << "," << binding_joy[ACTIONBAR_FORWARD] << "\n"; outfile << "actionbar_use=" << binding[ACTIONBAR_USE] << "," << binding_alt[ACTIONBAR_USE] << "," << binding_joy[ACTIONBAR_USE] << "\n"; if (outfile.bad()) fprintf(stderr, "Unable to write keybindings config file. No write access or disk is full!\n"); outfile.close(); outfile.clear(); } } void InputState::handle(bool dump_event) { SDL_Event event; SDL_GetMouseState(&mouse.x, &mouse.y); inkeys = ""; /* Check for events */ while (SDL_PollEvent (&event)) { if (dump_event) { cout << event << endl; } // grab symbol keys if (event.type == SDL_KEYDOWN) { int ch = event.key.keysym.unicode; // if it is printable char then write its utf-8 representation if (ch >= 0x800) { inkeys += (char) ((ch >> 12) | 0xe0); inkeys += (char) (((ch >> 6) & 0x3f) | 0x80); inkeys += (char) ((ch & 0x3f) | 0x80); } else if (ch >= 0x80) { inkeys += (char) ((ch >> 6) | 0xc0); inkeys += (char) ((ch & 0x3f) | 0x80); } else if (ch >= 32 && ch != 127) { inkeys += (char)ch; } } switch (event.type) { case SDL_MOUSEBUTTONDOWN: if (event.button.button == SDL_BUTTON_WHEELUP) { scroll_up = true; } else if (event.button.button == SDL_BUTTON_WHEELDOWN) { scroll_down = true; } else { for (int key=0; key<key_count; key++) { if (event.button.button == binding[key] || event.button.button == binding_alt[key]) { pressing[key] = true; } } } break; case SDL_MOUSEBUTTONUP: for (int key=0; key<key_count; key++) { if (event.button.button == binding[key] || event.button.button == binding_alt[key]) { pressing[key] = false; lock[key] = false; } } last_button = event.button.button; break; case SDL_KEYDOWN: for (int key=0; key<key_count; key++) { if (event.key.keysym.sym == binding[key] || event.key.keysym.sym == binding_alt[key]) { pressing[key] = true; } } break; case SDL_KEYUP: for (int key=0; key<key_count; key++) { if (event.key.keysym.sym == binding[key] || event.key.keysym.sym == binding_alt[key]) { pressing[key] = false; lock[key] = false; } } last_key = event.key.keysym.sym; break; /* case SDL_JOYAXISMOTION: // Reading joystick from SDL_JOYAXISMOTION is slow. Joystick analog input is handled by SDL_JoystickGetAxis() now. break; */ case SDL_JOYHATMOTION: if(JOYSTICK_DEVICE == event.jhat.which && ENABLE_JOYSTICK) { switch (event.jhat.value) { case SDL_HAT_CENTERED: pressing[UP] = false; lock[UP] = false; pressing[DOWN] = false; lock[DOWN] = false; pressing[LEFT] = false; lock[LEFT] = false; pressing[RIGHT] = false; lock[RIGHT] = false; break; case SDL_HAT_UP: pressing[UP] = true; pressing[DOWN] = false; lock[DOWN] = false; pressing[LEFT] = false; lock[LEFT] = false; pressing[RIGHT] = false; lock[RIGHT] = false; break; case SDL_HAT_DOWN: pressing[UP] = false; lock[UP] = false; pressing[DOWN] = true; pressing[LEFT] = false; lock[LEFT] = false; pressing[RIGHT] = false; lock[RIGHT] = false; break; case SDL_HAT_LEFT: pressing[UP] = false; lock[UP] = false; pressing[DOWN] = false; lock[DOWN] = false; pressing[LEFT] = true; pressing[RIGHT] = false; lock[RIGHT] = false; break; case SDL_HAT_RIGHT: pressing[UP] = false; lock[UP] = false; pressing[DOWN] = false; lock[DOWN] = false; pressing[LEFT] = false; lock[LEFT] = false; pressing[RIGHT] = true; break; case SDL_HAT_LEFTUP: pressing[UP] = true; pressing[DOWN] = false; lock[DOWN] = false; pressing[LEFT] = true; pressing[RIGHT] = false; lock[RIGHT] = false; break; case SDL_HAT_LEFTDOWN: pressing[UP] = false; lock[UP] = false; pressing[DOWN] = true; pressing[LEFT] = true; pressing[RIGHT] = false; lock[RIGHT] = false; break; case SDL_HAT_RIGHTUP: pressing[UP] = true; pressing[DOWN] = false; lock[DOWN] = false; pressing[LEFT] = false; lock[LEFT] = false; pressing[RIGHT] = true; break; case SDL_HAT_RIGHTDOWN: pressing[UP] = false; lock[UP] = false; pressing[DOWN] = true; pressing[LEFT] = false; lock[LEFT] = false; pressing[RIGHT] = true; break; } } break; case SDL_JOYBUTTONDOWN: if(JOYSTICK_DEVICE == event.jbutton.which && ENABLE_JOYSTICK) { for (int key=0; key<key_count; key++) { if (event.jbutton.button == binding_joy[key]) { pressing[key] = true; } } } break; case SDL_JOYBUTTONUP: if(JOYSTICK_DEVICE == event.jbutton.which && ENABLE_JOYSTICK) { for (int key=0; key<key_count; key++) { if (event.jbutton.button == binding_joy[key]) { pressing[key] = false; lock[key] = false; } } } break; case SDL_QUIT: done = 1; break; default: break; } } // joystick analog input if(ENABLE_JOYSTICK) { static bool joyReverseAxisX; static bool joyReverseAxisY; static bool joyHasMovedX; static bool joyHasMovedY; static int joyLastPosX; static int joyLastPosY; int joyAxisXval = SDL_JoystickGetAxis(joy, 0); int joyAxisYval = SDL_JoystickGetAxis(joy, 1); // axis 0 if(joyAxisXval < -JOY_DEADZONE) { if(!joyReverseAxisX) { if(joyLastPosX == JOY_POS_RIGHT) { joyHasMovedX = 0; } } else { if(joyLastPosX == JOY_POS_LEFT) { joyHasMovedX = 0; } } if(joyHasMovedX == 0) { if(!joyReverseAxisX) { pressing[LEFT] = true; pressing[RIGHT] = false; lock[RIGHT] = false; joyLastPosX = JOY_POS_LEFT; } else { pressing[RIGHT] = true; pressing[LEFT] = false; lock[LEFT] = false; joyLastPosX = JOY_POS_RIGHT; } joyHasMovedX = 1; } } if(joyAxisXval > JOY_DEADZONE) { if(!joyReverseAxisX) { if(joyLastPosX == JOY_POS_LEFT) { joyHasMovedX = 0; } } else { if(joyLastPosX == JOY_POS_RIGHT) { joyHasMovedX = 0; } } if(joyHasMovedX == 0) { if(!joyReverseAxisX) { pressing[RIGHT] = true; pressing[LEFT] = false; lock[LEFT] = false; joyLastPosX = JOY_POS_RIGHT; } else { pressing[LEFT] = true; pressing[RIGHT] = false; lock[RIGHT] = false; joyLastPosX = JOY_POS_LEFT; } joyHasMovedX = 1; } } if((joyAxisXval >= -JOY_DEADZONE) && (joyAxisXval < JOY_DEADZONE)) { pressing[LEFT] = false; lock[LEFT] = false; pressing[RIGHT] = false; lock[RIGHT] = false; joyHasMovedX = 0; joyLastPosX = JOY_POS_CENTER; } // axis 1 if(joyAxisYval < -JOY_DEADZONE) { if(!joyReverseAxisY) { if(joyLastPosY == JOY_POS_DOWN) { joyHasMovedY = 0; } } else { if(joyLastPosY == JOY_POS_UP) { joyHasMovedY = 0; } } if(joyHasMovedY == 0) { if(!joyReverseAxisY) { pressing[UP] = true; pressing[DOWN] = false; lock[DOWN] = false; joyLastPosY = JOY_POS_UP; } else { pressing[DOWN] = true; pressing[UP] = false; lock[UP] = false; joyLastPosY = JOY_POS_DOWN; } joyHasMovedY = 1; } } if(joyAxisYval > JOY_DEADZONE) { if(!joyReverseAxisY) { if(joyLastPosY == JOY_POS_UP) { joyHasMovedY = 0; } } else { if(joyLastPosY == JOY_POS_DOWN) { joyHasMovedY = 0; } } if(joyHasMovedY == 0) { if(!joyReverseAxisY) { pressing[DOWN] = true; pressing[UP] = false; lock[UP] = false; joyLastPosY = JOY_POS_DOWN; } else { pressing[UP] = true; pressing[DOWN] = false; lock[DOWN] = false; joyLastPosY = JOY_POS_UP; } joyHasMovedY = 1; } } if((joyAxisYval >= -JOY_DEADZONE) && (joyAxisYval < JOY_DEADZONE)) { pressing[UP] = false; lock[UP] = false; pressing[DOWN] = false; lock[DOWN] = false; joyHasMovedY = 0; joyLastPosY = JOY_POS_CENTER; } } } void InputState::resetScroll() { scroll_up = false; scroll_down = false; } void InputState::lockActionBar() { pressing[BAR_1] = false; pressing[BAR_2] = false; pressing[BAR_3] = false; pressing[BAR_4] = false; pressing[BAR_5] = false; pressing[BAR_6] = false; pressing[BAR_7] = false; pressing[BAR_8] = false; pressing[BAR_9] = false; pressing[BAR_0] = false; pressing[MAIN1] = false; pressing[MAIN2] = false; pressing[ACTIONBAR_USE] = false; lock[BAR_1] = true; lock[BAR_2] = true; lock[BAR_3] = true; lock[BAR_4] = true; lock[BAR_5] = true; lock[BAR_6] = true; lock[BAR_7] = true; lock[BAR_8] = true; lock[BAR_9] = true; lock[BAR_0] = true; lock[MAIN1] = true; lock[MAIN2] = true; lock[ACTIONBAR_USE] = true; } void InputState::unlockActionBar() { lock[BAR_1] = false; lock[BAR_2] = false; lock[BAR_3] = false; lock[BAR_4] = false; lock[BAR_5] = false; lock[BAR_6] = false; lock[BAR_7] = false; lock[BAR_8] = false; lock[BAR_9] = false; lock[BAR_0] = false; lock[MAIN1] = false; lock[MAIN2] = false; lock[ACTIONBAR_USE] = false; } void InputState::setKeybindNames() { binding_name[0] = msg->get("Cancel"); binding_name[1] = msg->get("Accept"); binding_name[2] = msg->get("Up"); binding_name[3] = msg->get("Down"); binding_name[4] = msg->get("Left"); binding_name[5] = msg->get("Right"); binding_name[6] = msg->get("Bar1"); binding_name[7] = msg->get("Bar2"); binding_name[8] = msg->get("Bar3"); binding_name[9] = msg->get("Bar4"); binding_name[10] = msg->get("Bar5"); binding_name[11] = msg->get("Bar6"); binding_name[12] = msg->get("Bar7"); binding_name[13] = msg->get("Bar8"); binding_name[14] = msg->get("Bar9"); binding_name[15] = msg->get("Bar0"); binding_name[16] = msg->get("Character"); binding_name[17] = msg->get("Inventory"); binding_name[18] = msg->get("Powers"); binding_name[19] = msg->get("Log"); binding_name[20] = msg->get("Main1"); binding_name[21] = msg->get("Main2"); binding_name[22] = msg->get("Ctrl"); binding_name[23] = msg->get("Shift"); binding_name[24] = msg->get("Delete"); binding_name[25] = msg->get("ActionBar Accept"); binding_name[26] = msg->get("ActionBar Left"); binding_name[27] = msg->get("ActionBar Right"); binding_name[28] = msg->get("ActionBar Use"); mouse_button[0] = msg->get("lmb"); mouse_button[1] = msg->get("mmb"); mouse_button[2] = msg->get("rmb"); mouse_button[3] = msg->get("wheel up"); mouse_button[4] = msg->get("wheel down"); mouse_button[5] = msg->get("mbx1"); mouse_button[6] = msg->get("mbx2"); } InputState::~InputState() { } ������������������������������������������������������flare-engine-0.19/src/InputState.h������������������������������������������������������������������0000664�0000000�0000000�00000004406�12247171015�0017043�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #pragma once #ifndef INPUT_STATE_H #define INPUT_STATE_H #include "CommonIncludes.h" #include "Utils.h" #define JOY_POS_CENTER 0 #define JOY_POS_LEFT -1 #define JOY_POS_RIGHT 1 #define JOY_POS_UP -1 #define JOY_POS_DOWN 1 // Input commands enum const int CANCEL = 0; const int ACCEPT = 1; const int UP = 2; const int DOWN = 3; const int LEFT = 4; const int RIGHT = 5; const int BAR_1 = 6; const int BAR_2 = 7; const int BAR_3 = 8; const int BAR_4 = 9; const int BAR_5 = 10; const int BAR_6 = 11; const int BAR_7 = 12; const int BAR_8 = 13; const int BAR_9 = 14; const int BAR_0 = 15; const int CHARACTER = 16; const int INVENTORY = 17; const int POWERS = 18; const int LOG = 19; const int MAIN1 = 20; const int MAIN2 = 21; const int CTRL = 22; const int SHIFT = 23; const int DEL = 24; const int ACTIONBAR = 25; const int ACTIONBAR_BACK = 26; const int ACTIONBAR_FORWARD = 27; const int ACTIONBAR_USE = 28; /** * class InputState * * Handles keyboard and mouse states */ class InputState { public: static const int key_count = 29; int binding[key_count]; int binding_alt[key_count]; int binding_joy[key_count]; std::string binding_name[29]; std::string mouse_button[7]; InputState(void); ~InputState(); void defaultQwertyKeyBindings(); void defaultJoystickBindings(); void loadKeyBindings(); void saveKeyBindings(); void handle(bool dump_event); void resetScroll(); void lockActionBar(); void unlockActionBar(); void setKeybindNames(); bool pressing[key_count]; bool lock[key_count]; bool done; Point mouse; std::string inkeys; int last_key; int last_button; bool scroll_up; bool scroll_down; }; #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/ItemManager.cpp���������������������������������������������������������������0000664�0000000�0000000�00000055326�12247171015�0017476�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class ItemManager */ #include "CommonIncludes.h" #include "FileParser.h" #include "ItemManager.h" #include "Settings.h" #include "SharedResources.h" #include "StatBlock.h" #include "UtilsFileSystem.h" #include "UtilsParsing.h" #include "WidgetLabel.h" #include <cassert> #include <climits> #include <cstring> using namespace std; /** * Resizes vector vec, so it can fit index id. */ template <typename Ty_> static inline void ensureFitsId(vector<Ty_>& vec, int id) { // id's are always greater or equal 1; if (id < 1) return; typedef typename vector<Ty_>::size_type VecSz; if (vec.size() <= VecSz(id+1)) vec.resize(id+1); } /** * Trims vector allocated memory to its size. * * Emulates C++2011 vector::shrink_to_fit(). * It is sometimes also called "swap trick". */ template <typename Ty_> static inline void shrinkVecToFit(std::vector<Ty_>& vec) { if (vec.capacity() != vec.size()) std::vector<Ty_>(vec).swap(vec); } ItemManager::ItemManager() : color_normal(font->getColor("item_normal")) , color_low(font->getColor("item_low")) , color_high(font->getColor("item_high")) , color_epic(font->getColor("item_epic")) , color_bonus(font->getColor("item_bonus")) , color_penalty(font->getColor("item_penalty")) , color_requirements_not_met(font->getColor("requirements_not_met")) , color_flavor(font->getColor("item_flavor")) { // NB: 20 is arbitrary picked number, but it looks like good start. items.reserve(20); item_sets.reserve(5); loadAll(); loadIcons(); } /** * Load all items files in all mods */ void ItemManager::loadAll() { // load each items.txt file. Individual item IDs can be overwritten with mods. this->loadItems(); this->loadTypes(); this->loadSets(); /* * Shrinks the items vector to the absolute needed size. * * While loading the items, the item vector grows dynamically. To have * no much time overhead for reallocating the vector, a new reallocation * is twice as large as the needed item id, which means in the worst case * the item vector was reallocated for loading the last element, so the * vector is twice as large as needed. This memory is definitly not used, * so we can free it. */ shrinkVecToFit(items); shrinkVecToFit(item_sets); if (items.empty()) fprintf(stderr, "No items were found.\n"); if (item_sets.empty()) printf("No item sets were found.\n"); } /** * Load a specific items file * * @param filename The full path and name of the file to load */ void ItemManager::loadItems() { FileParser infile; // @CLASS Item|Description about the class and it usage, items/items.txt... if (!infile.open("items/items.txt", true, false)) return; int id = 0; bool id_line = false; while (infile.next()) { if (infile.key == "id") { // @ATTR id|integer|An uniq id of the item used as reference from other classes. id_line = true; id = toInt(infile.val); ensureFitsId(items, id+1); } else id_line = false; if (id < 1) { if (id_line) fprintf(stderr, "Item index out of bounds 1-%d, skipping\n", INT_MAX); continue; } if (id_line) continue; assert(items.size() > std::size_t(id)); if (infile.key == "name") // @ATTR name|string|Item name displayed on long and short tooltips. items[id].name = msg->get(infile.val); else if (infile.key == "flavor") // @ATTR flavor|string| items[id].flavor = msg->get(infile.val); else if (infile.key == "level") // @ATTR level|integer| items[id].level = toInt(infile.val); else if (infile.key == "icon") { // @ATTR icon|integer| items[id].icon = toInt(infile.nextValue()); } else if (infile.key == "quality") { // @ATTR quality|[low:high:epic]|Item quality, corresponds to item color. if (infile.val == "low") items[id].quality = ITEM_QUALITY_LOW; else if (infile.val == "high") items[id].quality = ITEM_QUALITY_HIGH; else if (infile.val == "epic") items[id].quality = ITEM_QUALITY_EPIC; } else if (infile.key == "item_type") { // @ATTR item_type|string|Equipment slot [artifact, head, chest, hands, legs, feets, main, off, ring] or base item type [gem, consumable] items[id].type = infile.val; } else if (infile.key == "equip_flags") { infile.val = infile.val + ','; std::string flag = eatFirstString(infile.val,','); while (flag != "") { items[id].equip_flags.push_back(flag); flag = eatFirstString(infile.val,','); } } else if (infile.key == "dmg_melee") { // @ATTR dmg_melee|[min (integer), max (integer)]|Defines the item melee damage, if only min is specified the melee damage is fixed. items[id].dmg_melee_min = toInt(infile.nextValue()); if (infile.val.length() > 0) items[id].dmg_melee_max = toInt(infile.nextValue()); else items[id].dmg_melee_max = items[id].dmg_melee_min; } else if (infile.key == "dmg_ranged") { // @ATTR dmg_ranged|[min (integer), max (integer)]|Defines the item ranged damage, if only min is specified the ranged damage is fixed. items[id].dmg_ranged_min = toInt(infile.nextValue()); if (infile.val.length() > 0) items[id].dmg_ranged_max = toInt(infile.nextValue()); else items[id].dmg_ranged_max = items[id].dmg_ranged_min; } else if (infile.key == "dmg_ment") { // @ATTR dmg_ment|[min (integer), max (integer)]|Defines the item mental damage, if only min is specified the ranged damage is fixed. items[id].dmg_ment_min = toInt(infile.nextValue()); if (infile.val.length() > 0) items[id].dmg_ment_max = toInt(infile.nextValue()); else items[id].dmg_ment_max = items[id].dmg_ment_min; } else if (infile.key == "abs") { // @ATTR abs|[min (integer), max (integer)]|Defines the item absorb value, if only min is specified the absorb value is fixed. items[id].abs_min = toInt(infile.nextValue()); if (infile.val.length() > 0) items[id].abs_max = toInt(infile.nextValue()); else items[id].abs_max = items[id].abs_min; } else if (infile.key == "req") { // @ATTR req|[ [p:m:o:d], amount (integer) ]|Make item require specific stat level ex. req=p,6 will require hero to have level 6 in physical stats string s = infile.nextValue(); if (s == "p") items[id].req_stat = REQUIRES_PHYS; else if (s == "m") items[id].req_stat = REQUIRES_MENT; else if (s == "o") items[id].req_stat = REQUIRES_OFF; else if (s == "d") items[id].req_stat = REQUIRES_DEF; items[id].req_val = toInt(infile.nextValue()); } else if (infile.key == "bonus") { // @ATTR bonus|[power_tag (string), amount (integer)]|Adds a bonus to the item power_tag being a uniq tag of a power definition, e.: bonus=HP regen, 50 items[id].bonus_stat.push_back(infile.nextValue()); items[id].bonus_val.push_back(toInt(infile.nextValue())); } else if (infile.key == "soundfx") { // @ATTR soundfx|string|Sound effect for the specific item. items[id].sfx = snd->load(infile.val, "ItemManager"); } else if (infile.key == "gfx") // @ATTR gfx|string|Graphics for the specific item. items[id].gfx = infile.val; else if (infile.key == "loot_animation") { // @ATTR loot_animation|string|Specifies the loot animation for the item. infile.val = infile.val + ','; LootAnimation la; la.name = eatFirstString(infile.val, ','); la.low = eatFirstInt(infile.val, ','); la.high = eatFirstInt(infile.val, ','); items[id].loot_animation.push_back(la); } else if (infile.key == "power") { // @ATTR power|power_id|Adds a specific power to the item which makes it usable as a power and can be placed in action bar. if (toInt(infile.val) > 0) { items[id].power = toInt(infile.val); } else fprintf(stderr, "Power index inside item %d definition out of bounds 1-%d, skipping item\n", id, INT_MAX); } else if (infile.key == "power_mod") // @ATTR power_mod|integer|Power modifier of item. items[id].power_mod = toInt(infile.val); else if (infile.key == "power_desc") // @ATTR power_desc|string|A string describing the additional power. items[id].power_desc = msg->get(infile.val); else if (infile.key == "price") // @ATTR price|integer|The amount of currency the item costs, if set to 0 the item cannot be sold. items[id].price = toInt(infile.val); else if (infile.key == "price_sell") // @ATTR sell_price|integer|The amount of currency the item is sold for, if set to 0 the sell prices is prices*vendor_ratio. items[id].price_sell = toInt(infile.val); else if (infile.key == "max_quantity") // @ATTR max_quantity|integer|Max item count per stack. items[id].max_quantity = toInt(infile.val); else if (infile.key == "rand_loot") // @ATTR rand_loot|integer|Max amount appearing in loot stack. items[id].rand_loot = toInt(infile.val); else if (infile.key == "rand_vendor") // @ATTR rand_vendor|integer|Max amount appearing in vendor stack. items[id].rand_vendor = toInt(infile.val); else if (infile.key == "pickup_status") // @ATTR pickup_status|string|Set a campaign status when item is picked up, this is used for quest items. items[id].pickup_status = infile.val; else if (infile.key == "stepfx") // @ATTR stepfx|string|Sound effect when walking, this applies only to armors. items[id].stepfx = infile.val; else if (infile.key == "class") { // @ATTR class|[classname (string), ...]|A comma separated list of classes the item belongs too. string classname = infile.nextValue(); while (classname != "") { unsigned pos; // find the position where this classname is stored: for (pos = 0; pos < item_class_names.size(); pos++) { if (item_class_names[pos] == classname) break; } // if it was not found, add it to the end. // pos is already the correct index. if (pos == item_class_names.size()) { item_class_names.push_back(classname); item_class_items.push_back(vector<unsigned int>()); } // add item id to the item list of that class: item_class_items[pos].push_back(id); classname = infile.nextValue(); } } } infile.close(); } void ItemManager::loadTypes() { FileParser infile; string type,description; type = description = ""; // @CLASS Item Type|Definition of a item types, items/types.txt... if (infile.open("items/types.txt", true, false)) { while (infile.next()) { // @ATTR name|string|Item type name. if (infile.key == "name") type = infile.val; // @ATTR description|string|Item type description. else if (infile.key == "description") description = infile.val; if (type != "" && description != "") { item_types[type] = description; type = description = ""; } } infile.close(); } } string ItemManager::getItemType(std::string _type) { map<string,string>::iterator it,end; for (it=item_types.begin(), end=item_types.end(); it!=end; ++it) { if (_type.compare(it->first) == 0) return it->second; } // If all else fails, return the original string return _type; } void ItemManager::loadSets() { FileParser infile; // @CLASS Item Set|Definition of a item sets, items/sets.txt... if (!infile.open("items/sets.txt", true, false)) return; int id = 0; bool id_line; while (infile.next()) { if (infile.key == "id") { // @ATTR id|integer|A uniq id for the item set. id_line = true; id = toInt(infile.val); ensureFitsId(item_sets, id+1); } else id_line = false; if (id < 1) { if (id_line) fprintf(stderr, "Item set index out of bounds 1-%d, skipping\n", INT_MAX); continue; } if (id_line) continue; assert(item_sets.size() > std::size_t(id)); if (infile.key == "name") { // @ATTR name|string|Name of the item set. item_sets[id].name = msg->get(infile.val); } else if (infile.key == "items") { // @ATTR name|[item_id,...]|List of item id's that is part of the set. string item_id = infile.nextValue(); while (item_id != "") { int temp_id = toInt(item_id); if (temp_id > 0 && temp_id < static_cast<int>(items.size())) { items[temp_id].set = id; item_sets[id].items.push_back(temp_id); } else { const int maxsize = static_cast<int>(items.size()-1); const char* cname = item_sets[id].name.c_str(); fprintf(stderr, "Item index inside item set %s definition out of bounds 1-%d, skipping item\n", cname, maxsize); } item_id = infile.nextValue(); } } else if (infile.key == "color") { // @ATTR color|color|A specific of color for the set. item_sets[id].color.r = toInt(infile.nextValue()); item_sets[id].color.g = toInt(infile.nextValue()); item_sets[id].color.b = toInt(infile.nextValue()); } else if (infile.key == "bonus") { // @ATTR bonus|[requirements (integer), bonus stat (string), bonus (integer)]|Bonus to append to items in the set. Set_bonus bonus; bonus.requirement = toInt(infile.nextValue()); bonus.bonus_stat = infile.nextValue(); bonus.bonus_val = toInt(infile.nextValue()); item_sets[id].bonus.push_back(bonus); } } infile.close(); } /** * Icon sets */ void ItemManager::loadIcons() { icons = loadGraphicSurface("images/icons/icons.png", "Couldn't load icons"); } SDL_Surface* ItemManager::getIcons() { return icons; } /** * Renders icons at small size or large size * Also display the stack size */ void ItemManager::renderIcon(ItemStack stack, int x, int y, int size) { if (!icons) return; SDL_Rect src, dest; dest.x = x; dest.y = y; src.w = src.h = dest.w = dest.h = size; if (stack.item > 0) { int columns = icons->w / ICON_SIZE; src.x = (items[stack.item].icon % columns) * size; src.y = (items[stack.item].icon / columns) * size; SDL_BlitSurface(icons, &src, screen, &dest); } if (stack.quantity > 1 || items[stack.item].max_quantity > 1) { WidgetLabel label; label.set(dest.x + 2, dest.y + 2, JUSTIFY_LEFT, VALIGN_TOP, abbreviateKilo(stack.quantity), color_normal); label.render(); } } void ItemManager::playSound(int item, Point pos) { snd->play(items[item].sfx, GLOBAL_VIRTUAL_CHANNEL, pos, false); } TooltipData ItemManager::getShortTooltip(ItemStack stack) { stringstream ss; TooltipData tip; SDL_Color color = color_normal; if (stack.item == 0) return tip; // color quality if (items[stack.item].set > 0) { color = item_sets[items[stack.item].set].color; } else if (items[stack.item].quality == ITEM_QUALITY_LOW) { color = color_low; } else if (items[stack.item].quality == ITEM_QUALITY_HIGH) { color = color_high; } else if (items[stack.item].quality == ITEM_QUALITY_EPIC) { color = color_epic; } // name if (stack.quantity > 1) { ss << stack.quantity << " " << items[stack.item].name; } else { ss << items[stack.item].name; } tip.addText(ss.str(), color); return tip; } /** * Create detailed tooltip showing all relevant item info */ TooltipData ItemManager::getTooltip(ItemStack stack, StatBlock *stats, int context) { TooltipData tip; SDL_Color color = color_normal; string quality_desc = ""; if (stack.item == 0) return tip; // color quality if (items[stack.item].set > 0) { color = item_sets[items[stack.item].set].color; } else if (items[stack.item].quality == ITEM_QUALITY_LOW) { color = color_low; quality_desc = msg->get("Low"); } else if (items[stack.item].quality == ITEM_QUALITY_NORMAL) { color = color_normal; quality_desc = msg->get("Normal"); } else if (items[stack.item].quality == ITEM_QUALITY_HIGH) { color = color_high; quality_desc = msg->get("High"); } else if (items[stack.item].quality == ITEM_QUALITY_EPIC) { color = color_epic; quality_desc = msg->get("Epic"); } // name stringstream ss; if (stack.quantity < 1000) ss << items[stack.item].name; else ss << items[stack.item].name << " (" << stack.quantity << ")"; tip.addText(ss.str(), color); // level if (items[stack.item].level != 0) { tip.addText(msg->get("Level %d", items[stack.item].level)); } // type if (items[stack.item].type != "other") { tip.addText(msg->get(getItemType(items[stack.item].type))); } // damage if (items[stack.item].dmg_melee_max > 0) { if (items[stack.item].dmg_melee_min < items[stack.item].dmg_melee_max) tip.addText(msg->get("Melee damage: %d-%d", items[stack.item].dmg_melee_min, items[stack.item].dmg_melee_max)); else tip.addText(msg->get("Melee damage: %d", items[stack.item].dmg_melee_max)); } if (items[stack.item].dmg_ranged_max > 0) { if (items[stack.item].dmg_ranged_min < items[stack.item].dmg_ranged_max) tip.addText(msg->get("Ranged damage: %d-%d", items[stack.item].dmg_ranged_min, items[stack.item].dmg_ranged_max)); else tip.addText(msg->get("Ranged damage: %d", items[stack.item].dmg_ranged_max)); } if (items[stack.item].dmg_ment_max > 0) { if (items[stack.item].dmg_ment_min < items[stack.item].dmg_ment_max) tip.addText(msg->get("Mental damage: %d-%d", items[stack.item].dmg_ment_min, items[stack.item].dmg_ment_max)); else tip.addText(msg->get("Mental damage: %d", items[stack.item].dmg_ment_max)); } // absorb if (items[stack.item].abs_max > 0) { if (items[stack.item].abs_min < items[stack.item].abs_max) tip.addText(msg->get("Absorb: %d-%d", items[stack.item].abs_min, items[stack.item].abs_max)); else tip.addText(msg->get("Absorb: %d", items[stack.item].abs_max)); } // bonuses unsigned bonus_counter = 0; string modifier; while (bonus_counter < items[stack.item].bonus_val.size() && items[stack.item].bonus_stat[bonus_counter] != "") { if (items[stack.item].bonus_stat[bonus_counter] == "speed") { modifier = msg->get("%d% Speed", items[stack.item].bonus_val[bonus_counter]); if (items[stack.item].bonus_val[bonus_counter] >= 100) color = color_bonus; else color = color_penalty; } else { if (items[stack.item].bonus_val[bonus_counter] > 0) { modifier = msg->get("Increases %s by %d", items[stack.item].bonus_val[bonus_counter], msg->get(items[stack.item].bonus_stat[bonus_counter])); color = color_bonus; } else { modifier = msg->get("Decreases %s by %d", items[stack.item].bonus_val[bonus_counter], msg->get(items[stack.item].bonus_stat[bonus_counter])); color = color_penalty; } } tip.addText(modifier, color); bonus_counter++; } // power if (items[stack.item].power_desc != "") { tip.addText(items[stack.item].power_desc, color_bonus); } // requirement if (items[stack.item].req_val > 0) { if (items[stack.item].req_stat == REQUIRES_PHYS) { if (stats->get_physical() < items[stack.item].req_val) color = color_requirements_not_met; else color = color_normal; tip.addText(msg->get("Requires Physical %d", items[stack.item].req_val), color); } else if (items[stack.item].req_stat == REQUIRES_MENT) { if (stats->get_mental() < items[stack.item].req_val) color = color_requirements_not_met; else color = color_normal; tip.addText(msg->get("Requires Mental %d", items[stack.item].req_val), color); } else if (items[stack.item].req_stat == REQUIRES_OFF) { if (stats->get_offense() < items[stack.item].req_val) color = color_requirements_not_met; else color = color_normal; tip.addText(msg->get("Requires Offense %d", items[stack.item].req_val), color); } else if (items[stack.item].req_stat == REQUIRES_DEF) { if (stats->get_defense() < items[stack.item].req_val) color = color_requirements_not_met; else color = color_normal; tip.addText(msg->get("Requires Defense %d", items[stack.item].req_val), color); } } if (COLORBLIND && quality_desc != "") { color = color_normal; tip.addText(msg->get("Quality: %s", quality_desc), color); } // flavor text if (items[stack.item].flavor != "") { tip.addText(items[stack.item].flavor, color_flavor); } // buy or sell price if (items[stack.item].price > 0 && stack.item != CURRENCY_ID) { int price_per_unit; if (context == VENDOR_BUY) { price_per_unit = items[stack.item].price; if (stats->currency < items[stack.item].price) color = color_requirements_not_met; else color = color_normal; if (items[stack.item].max_quantity <= 1) tip.addText(msg->get("Buy Price: %d %s", price_per_unit, CURRENCY), color); else tip.addText(msg->get("Buy Price: %d %s each", price_per_unit, CURRENCY), color); } else if (context == VENDOR_SELL) { price_per_unit = items[stack.item].getSellPrice(); if (stats->currency < price_per_unit) color = color_requirements_not_met; else color = color_normal; if (items[stack.item].max_quantity <= 1) tip.addText(msg->get("Buy Price: %d %s", price_per_unit, CURRENCY), color); else tip.addText(msg->get("Buy Price: %d %s each", price_per_unit, CURRENCY), color); } else if (context == PLAYER_INV) { price_per_unit = items[stack.item].getSellPrice(); if (price_per_unit == 0) price_per_unit = 1; if (items[stack.item].max_quantity <= 1) tip.addText(msg->get("Sell Price: %d %s", price_per_unit, CURRENCY)); else tip.addText(msg->get("Sell Price: %d %s each", price_per_unit, CURRENCY)); } } if (items[stack.item].set > 0) { // item set bonuses ItemSet set = item_sets[items[stack.item].set]; bonus_counter = 0; modifier = ""; tip.addText("\n" + msg->get("Set: ") + msg->get(item_sets[items[stack.item].set].name), set.color); while (bonus_counter < set.bonus.size() && set.bonus[bonus_counter].bonus_stat != "") { if (set.bonus[bonus_counter].bonus_val > 0) { modifier = msg->get("%d items: ", set.bonus[bonus_counter].requirement) + msg->get("Increases %s by %d", set.bonus[bonus_counter].bonus_val, msg->get(set.bonus[bonus_counter].bonus_stat)); } else { modifier = msg->get("%d items: ", set.bonus[bonus_counter].requirement) + msg->get("Decreases %s by %d", set.bonus[bonus_counter].bonus_val, msg->get(set.bonus[bonus_counter].bonus_stat)); } tip.addText(modifier, set.color); bonus_counter++; } } return tip; } ItemManager::~ItemManager() { SDL_FreeSurface(icons); } /** * Compare two item stack to be able to sorting them on their item_id in the vendors' stock */ bool ItemStack::operator > (const ItemStack ¶m) const { if (item == 0 && param.item > 0) { // Make the empty slots the last while sorting return true; } else if (item > 0 && param.item == 0) { // Make the empty slots the last while sorting return false; } else { return item > param.item; } } int Item::getSellPrice() { int new_price = 0; if (price_sell != 0) new_price = price_sell; else new_price = static_cast<int>(price * VENDOR_RATIO); if (new_price == 0) new_price = 1; return new_price; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/ItemManager.h�����������������������������������������������������������������0000664�0000000�0000000�00000013536�12247171015�0017140�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class ItemManager */ #pragma once #ifndef ITEM_MANAGER_H #define ITEM_MANAGER_H #include "CommonIncludes.h" #include "TooltipData.h" #include <stdint.h> #define VENDOR_BUY 0 #define VENDOR_SELL 1 #define PLAYER_INV 2 class StatBlock; const int REQUIRES_PHYS = 0; const int REQUIRES_MENT = 1; const int REQUIRES_OFF = 2; const int REQUIRES_DEF = 3; const int ITEM_QUALITY_LOW = 0; const int ITEM_QUALITY_NORMAL = 1; const int ITEM_QUALITY_HIGH = 2; const int ITEM_QUALITY_EPIC = 3; class LootAnimation { public: std::string name; int low; int high; LootAnimation() : name("") , low(0) , high(0) {} }; class Set_bonus { public: int requirement; std::string bonus_stat; int bonus_val; Set_bonus() : requirement(0) , bonus_stat("") , bonus_val(0) {} }; class Item { public: std::string name; // item name displayed on long and short tool tips std::string flavor; // optional flavor text describing the item int level; // rough estimate of quality, used in the loot algorithm int set; // item can be attached to item set int quality; // low, normal, high, epic; corresponds to item name color std::string type; // equipment slot or base item type std::vector<std::string> equip_flags; // common values include: melee, ranged, mental, shield int icon; // icon index on small pixel sheet int dmg_melee_min; // minimum damage amount (melee) int dmg_melee_max; // maximum damage amount (melee) int dmg_ranged_min; // minimum damage amount (ranged) int dmg_ranged_max; // maximum damage amount (ranged) int dmg_ment_min; // minimum damage amount (mental) int dmg_ment_max; // maximum damage amount (mental) int abs_min; // minimum absorb amount int abs_max; // maximum absorb amount int req_stat; // physical, mental, offense, defense int req_val; // 1-5 (used with req_stat) std::vector<std::string> bonus_stat; // stat to increase/decrease e.g. hp, accuracy, speed std::vector<int> bonus_val; // amount to increase (used with bonus_stat) SoundManager::SoundID sfx; // the item sound when it hits the floor or inventory, etc std::string gfx; // the sprite layer shown when this item is equipped std::vector<LootAnimation> loot_animation;// the flying loot animation for this item int power; // this item can be dragged to the action bar and used as a power int power_mod; // alter powers when this item is equipped (e.g. shoot arrows from bows) std::string power_desc; // shows up in green text on the tooltip int price; // if price = 0 the item cannot be sold int price_sell; // if price_sell = 0, the sell price is price*vendor_ratio int max_quantity; // max count per stack int rand_loot; // max amount appearing in a loot stack int rand_vendor; // max amount appearing in a vendor stack std::string pickup_status; // when this item is picked up, set a campaign state (usually for quest items) std::string stepfx; // sound effect played when walking (armors only) int getSellPrice(); Item() : name("") , flavor("") , level(0) , set(0) , quality(ITEM_QUALITY_NORMAL) , type("other") , icon(0) , dmg_melee_min(0) , dmg_melee_max(0) , dmg_ranged_min(0) , dmg_ranged_max(0) , dmg_ment_min(0) , dmg_ment_max(0) , abs_min(0) , abs_max(0) , req_stat(0) , req_val(0) , sfx(0) , gfx("") , power(0) , power_mod(0) , power_desc("") , price(0) , price_sell(0) , max_quantity(1) , rand_loot(1) , rand_vendor(1) , pickup_status("") , stepfx("") {} ~Item() { } }; class ItemSet { public: std::string name; // item set name displayed on long and short tool tips std::vector<int> items; // items, included into set std::vector<Set_bonus> bonus;// vector with stats to increase/decrease SDL_Color color; ItemSet() : name("") { color.r = 255; color.g = 255; color.b = 255; } ~ItemSet() { } }; class ItemStack { public: ItemStack() : item(0) , quantity(0) {} ~ItemStack() {} int item; int quantity; bool operator > (const ItemStack ¶m) const; }; class ItemManager { private: SDL_Surface *icons; void loadItems(); void loadTypes(); void loadSets(); void loadAll(); void loadIcons(); SDL_Color color_normal; SDL_Color color_low; SDL_Color color_high; SDL_Color color_epic; SDL_Color color_bonus; SDL_Color color_penalty; SDL_Color color_requirements_not_met; SDL_Color color_flavor; public: ItemManager(); ~ItemManager(); SDL_Surface* getIcons(); void renderIcon(ItemStack stack, int x, int y, int size); void playSound(int item, Point pos = Point(0,0)); TooltipData getTooltip(ItemStack stack, StatBlock *stats, int context); TooltipData getShortTooltip(ItemStack item); std::string getItemType(std::string _type); std::vector<Item> items; std::map<std::string,std::string> item_types; std::vector<ItemSet> item_sets; std::vector<std::string> item_class_names; // a vector of all defined classes of items // belongs to the item_class_names vector and contains a vector of item ids which belong to that specific class. std::vector<std::vector<unsigned int> > item_class_items; }; #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/ItemStorage.cpp���������������������������������������������������������������0000664�0000000�0000000�00000015240�12247171015�0017517�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class ItemStorage */ #include "CommonIncludes.h" #include "ItemManager.h" #include "ItemStorage.h" #include "UtilsParsing.h" #include "SharedGameResources.h" using namespace std; void ItemStorage::init(int _slot_number) { slot_number = _slot_number; storage = new ItemStack[slot_number]; for( int i=0; i<slot_number; i++) { storage[i].item = 0; storage[i].quantity = 0; } } ItemStack & ItemStorage::operator [] (int slot) { return storage[slot]; } /** * Take the savefile CSV list of items id and convert to storage array */ void ItemStorage::setItems(string s) { s = s + ','; for (int i=0; i<slot_number; i++) { storage[i].item = eatFirstInt(s, ','); // check if such item exists to avoid crash if savegame was modified manually if (storage[i].item < 0) { fprintf(stderr, "Item on position %d has negative id, skipping\n", i); storage[i].item = 0; storage[i].quantity = 0; } else if ((unsigned)storage[i].item > items->items.size()-1) { fprintf(stderr, "Item id (%d) out of bounds 1-%d, skipping\n", storage[i].item, (int)items->items.size()); storage[i].item = 0; storage[i].quantity = 0; } else if (storage[i].item != 0 && items->items[storage[i].item].name == "") { fprintf(stderr, "Item with id=%d. found on position %d does not exist, skipping\n", storage[i].item, i); storage[i].item = 0; storage[i].quantity = 0; } } } /** * Take the savefile CSV list of items quantities and convert to storage array */ void ItemStorage::setQuantities(string s) { s = s + ','; for (int i=0; i<slot_number; i++) { storage[i].quantity = eatFirstInt(s, ','); if (storage[i].quantity < 0) { fprintf(stderr, "Items quantity on position %d is negative, setting to zero\n", i); storage[i].quantity = 0; } } } int ItemStorage::getSlotNumber() { return slot_number; } /** * Convert storage array to a CSV list of items id for savefile */ string ItemStorage::getItems() { stringstream ss; ss.str(""); for (int i=0; i<slot_number; i++) { ss << storage[i].item; if (i < slot_number-1) ss << ','; } return ss.str(); } /** * Convert storage array to a CSV list of items quantities for savefile */ string ItemStorage::getQuantities() { stringstream ss; ss.str(""); for (int i=0; i<slot_number; i++) { ss << storage[i].quantity; if (i < slot_number-1) ss << ','; } return ss.str(); } void ItemStorage::clear() { for( int i=0; i<slot_number; i++) { storage[i].item = 0; storage[i].quantity = 0; } } /** * Insert item into first available carried slot, preferably in the optionnal specified slot * * @param ItemStack Stack of items * @param slot Slot number where it will try to store the item */ void ItemStorage::add( ItemStack stack, int slot) { if (stack.item != 0) { int max_quantity = items->items[stack.item].max_quantity; if (slot > -1) { // a slot is specified if (storage[slot].item != 0 && storage[slot].item != stack.item) { // the proposed slot isn't available slot = -1; } } else { // first search of stack to complete if the item is stackable int i = 0; while (max_quantity > 1 && slot == -1 && i < slot_number) { if (storage[i].item == stack.item && storage[i].quantity < max_quantity) { slot = i; } i++; } // then an empty slot i = 0; while (slot == -1 && i < slot_number) { if (storage[i].item == 0) { slot = i; } i++; } } if (slot != -1) { // Add int quantity_added = min( stack.quantity, max_quantity - storage[slot].quantity); storage[slot].item = stack.item; storage[slot].quantity += quantity_added; stack.quantity -= quantity_added; // Add back the remaining if (stack.quantity > 0) { add( stack); } } else { // No available slot, drop } } } /** * Substract an item from the specified slot, or remove it if it's the last * * @param slot Slot number */ void ItemStorage::substract(int slot, int quantity) { storage[slot].quantity -= quantity; if (storage[slot].quantity <= 0) { storage[slot].item = 0; } } /** * Remove one given item */ bool ItemStorage::remove(int item) { for (int i=0; i<slot_number; i++) { if (storage[i].item == item) { substract(i, 1); return true; } } return false; } int compareItemStack (const void *a, const void *b) { const ItemStack *i1 = static_cast<const ItemStack*>(a); const ItemStack *i2 = static_cast<const ItemStack*>(b); if ((*i1) > (*i2)) return 1; else return -1; } void ItemStorage::sort() { qsort(storage, slot_number, sizeof(ItemStack), compareItemStack); } bool ItemStorage::full(ItemStack stack) { for (int i=0; i<slot_number; i++) { if (stack.quantity < 0) { return false; } if (storage[i].item == stack.item && storage[i].quantity < items->items[stack.item].max_quantity) { if (stack.quantity + storage[i].quantity >= items->items[stack.item].max_quantity) { stack.quantity -= storage[i].quantity; continue; } return false; } if (storage[i].item == 0) { return false; } } return true; } bool ItemStorage::full(int item) { ItemStack stack; stack.item = item; stack.quantity = 1; return full(stack); } /** * Get the number of the specified item carried (not equipped) */ int ItemStorage::count(int item) { int item_count=0; for (int i=0; i<slot_number; i++) { if (storage[i].item == item) { item_count += storage[i].quantity; } } return item_count; } /** * Check to see if the given item is equipped */ bool ItemStorage::contain(int item, int quantity) { int total_quantity = 0; for (int i=0; i<slot_number; i++) { if (storage[i].item == item) total_quantity += storage[i].quantity; if (total_quantity >= quantity) return true; } return false; } /** * Clear slots that contain an item, but have a quantity of 0 */ void ItemStorage::clean() { for (int i=0; i<slot_number; i++) { if (storage[i].item > 0 && storage[i].quantity < 1) { fprintf(stderr,"Removing item with id %d, which has a quantity of 0\n",storage[i].item); storage[i].item = 0; storage[i].quantity = 0; } } } ItemStorage::~ItemStorage() { delete[] storage; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/ItemStorage.h�����������������������������������������������������������������0000664�0000000�0000000�00000002611�12247171015�0017162�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class ItemStorage */ #pragma once #ifndef ITEM_STORAGE_H #define ITEM_STORAGE_H #include "CommonIncludes.h" class ItemManager; class ItemStack; class ItemStorage { protected: int slot_number; public: void init(int _slot_number); ~ItemStorage(); ItemStack & operator [] (int slot); void setItems(std::string s); void setQuantities(std::string s); int getSlotNumber(); std::string getItems(); std::string getQuantities(); void add(ItemStack stack, int slot = -1); void substract(int slot, int quantity = 1); bool remove(int item); void sort(); void clear(); void clean(); bool full(ItemStack stack); bool full(int item); int count(int item); bool contain(int item, int quantity = 1); ItemStack * storage; }; #endif �����������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/Loot.cpp����������������������������������������������������������������������0000664�0000000�0000000�00000003475�12247171015�0016220�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "Animation.h" #include "Loot.h" Loot::Loot() { stack.item = 0; stack.quantity = 0; pos.x = 0; pos.y = 0; animation = NULL; tip.clear(); gfx = ""; } Loot::Loot(const Loot &other) { stack.item = other.stack.item; stack.quantity = other.stack.quantity; pos.x = other.pos.x; pos.y = other.pos.y; loadAnimation(other.gfx); animation->syncTo(other.animation); tip = other.tip; } // The assignment operator mainly used in internal vector managing, // e.g. in vector::erase() Loot& Loot::operator= (const Loot &other) { if (gfx != "") anim->decreaseCount(gfx); delete animation; loadAnimation(other.gfx); animation->syncTo(other.animation); stack.item = other.stack.item; stack.quantity = other.stack.quantity; pos.x = other.pos.x; pos.y = other.pos.y; tip = other.tip; return *this; } void Loot::loadAnimation(std::string _gfx) { gfx = _gfx; if (gfx != "") { anim->increaseCount(gfx); AnimationSet *as = anim->getAnimationSet(gfx); animation = as->getAnimation(); } } bool Loot::isFlying() { return !animation->isLastFrame(); } Loot::~Loot() { if (gfx != "") anim->decreaseCount(gfx); delete animation; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/Loot.h������������������������������������������������������������������������0000664�0000000�0000000�00000002362�12247171015�0015657�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #pragma once #ifndef LOOT_H #define LOOT_H #include "CommonIncludes.h" #include "ItemManager.h" #include "Settings.h" #include "TooltipData.h" class Loot { private: std::string gfx; public: ItemStack stack; FPoint pos; Animation *animation; TooltipData tip; Loot(); Loot(const Loot &other); Loot& operator= (const Loot &other); ~Loot(); void loadAnimation(std::string _gfx); /** * If an item is flying, it hasn't completed its "flying loot" animation. * Only allow loot to be picked up if it is grounded. */ bool isFlying(); }; #endif // LOOT_H ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/LootManager.cpp���������������������������������������������������������������0000664�0000000�0000000�00000033253�12247171015�0017510�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class LootManager * * Handles floor loot */ #include "Animation.h" #include "AnimationManager.h" #include "AnimationSet.h" #include "CommonIncludes.h" #include "EnemyManager.h" #include "FileParser.h" #include "LootManager.h" #include "Menu.h" #include "MenuInventory.h" #include "SharedGameResources.h" #include "SharedResources.h" #include "Utils.h" #include "UtilsMath.h" #include "UtilsParsing.h" #include "WidgetTooltip.h" #include <limits> #include <math.h> using namespace std; LootManager::LootManager(StatBlock *_hero) { hero = _hero; // we need the player's position for dropping loot in a valid spot tip = new WidgetTooltip(); FileParser infile; // load loot animation settings from engine config file // @CLASS Loot|Description of engine/loot.txt if (infile.open("engine/loot.txt")) { while (infile.next()) { infile.val = infile.val + ','; if (infile.key == "loot_animation") { // @ATTR loot_animation|x(int), y(int), w(int), h(int)| animation_pos.x = eatFirstInt(infile.val, ','); animation_pos.y = eatFirstInt(infile.val, ','); animation_pos.w = eatFirstInt(infile.val, ','); animation_pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "loot_animation_offset") { // @ATTR loot_animation_offset|x (integer), y (integer)| animation_offset.x = eatFirstInt(infile.val, ','); animation_offset.y = eatFirstInt(infile.val, ','); } else if (infile.key == "tooltip_margin") { // @ATTR tooltip_margin|integer| tooltip_margin = eatFirstInt(infile.val, ','); } else if (infile.key == "autopickup_currency") { // @ATTR autopickup_currency|boolean|Enable autopickup for currency AUTOPICKUP_CURRENCY = toBool(eatFirstString(infile.val, ',')); } else if (infile.key == "currency_name") { // @ATTR currenct_name|string|Define the name of currency in game CURRENCY = msg->get(eatFirstString(infile.val, ',')); } else if (infile.key == "vendor_ratio") { // @ATTR vendor_ratio|integer|Prices ratio for vendors VENDOR_RATIO = eatFirstInt(infile.val, ',') / 100.0f; } else if (infile.key == "sfx_loot") { // @ATTR sfx_loot|string|Sound effect for dropping loot. sfx_loot = snd->load(eatFirstString(infile.val, ','), "LootManager dropping loot"); } } infile.close(); } // reset current map loot loot.clear(); loadGraphics(); full_msg = false; } /** * The "loot" variable on each item refers to the "flying loot" animation for that item. * Here we load all the animations used by the item database. */ void LootManager::loadGraphics() { // check all items in the item database for (unsigned int i=0; i < items->items.size(); i++) { if (items->items[i].loot_animation.empty()) continue; for (unsigned int j=0; j<items->items[i].loot_animation.size(); j++) { anim->increaseCount(items->items[i].loot_animation[j].name); } } } void LootManager::handleNewMap() { loot.clear(); } void LootManager::logic() { vector<Loot>::iterator it; for (it = loot.begin(); it != loot.end(); ++it) { // animate flying loot it->animation->advanceFrame(); if (it->animation->isSecondLastFrame()) { if (it->stack.item > 0) { Point pos; pos.x = (int)it->pos.x; pos.y = (int)it->pos.y; items->playSound(it->stack.item, pos); } } } checkEnemiesForLoot(); checkMapForLoot(); } /** * Show all tooltips for loot on the floor */ void LootManager::renderTooltips(FPoint cam) { Point dest; vector<Loot>::iterator it; for (it = loot.begin(); it != loot.end(); ++it) { if (it->animation->isLastFrame()) { Point p = map_to_screen(it->pos.x, it->pos.y, cam.x, cam.y); dest.x = p.x; dest.y = p.y + TILE_H_HALF; // adjust dest.y so that the tooltip floats above the item dest.y -= tooltip_margin; // create tooltip data if needed if (it->tip.isEmpty()) { if (it->stack.item > 0) { it->tip = items->getShortTooltip(it->stack); } } tip->render(it->tip, dest, STYLE_TOPLABEL); } } } /** * Enemies that drop loot raise a "loot_drop" flag to notify this loot * manager to create loot based on that creature's level and position. */ void LootManager::checkEnemiesForLoot() { ItemStack istack; istack.quantity = 1; for (unsigned i=0; i < enemiesDroppingLoot.size(); ++i) { const Enemy *e = enemiesDroppingLoot[i]; if (e->stats.quest_loot_id != 0) { // quest loot istack.item = e->stats.quest_loot_id; addLoot(istack, e->stats.pos); } else { // random loot //determine position FPoint pos = hero->pos; if (mapr->collider.is_valid_position(e->stats.pos.x, e->stats.pos.y, MOVEMENT_NORMAL, false)) pos = e->stats.pos; determineLootByEnemy(e, pos); } } enemiesDroppingLoot.clear(); } void LootManager::addEnemyLoot(const Enemy *e) { enemiesDroppingLoot.push_back(e); } /** * As map events occur, some might have a component named "loot" * Loot is created at component x,y */ void LootManager::checkMapForLoot() { FPoint p; Event_Component *ec; ItemStack new_loot; std::vector<int> possible_ids; int common_chance = -1; int chance = rand() % 100; // first drop any 'fixed' (0% chance) items for (unsigned i = mapr->loot.size(); i > 0; i--) { ec = &mapr->loot[i-1]; if (ec->z == 0) { p.x = ec->x + 0.5f; p.y = ec->y + 0.5f; new_loot.quantity = randBetween(ec->a,ec->b); // an item id of 0 means we should drop currency instead if (ec->s == "currency" || toInt(ec->s) == 0 || toInt(ec->s) == CURRENCY_ID) { new_loot.item = CURRENCY_ID; new_loot.quantity = new_loot.quantity * (100 + hero->get(STAT_CURRENCY_FIND)) / 100; } else { new_loot.item = toInt(ec->s); } addLoot(new_loot, p); mapr->loot.erase(mapr->loot.begin()+i-1); } } // now pick up to 1 random item to drop for (unsigned i = mapr->loot.size(); i > 0; i--) { ec = &mapr->loot[i-1]; if (possible_ids.empty()) { // Don't use item find bonus for currency int max_chance = ec->z; if (ec->s != "currency" && toInt(ec->s) != 0 && toInt(ec->s) != CURRENCY_ID) max_chance = ec->z * (hero->get(STAT_ITEM_FIND) + 100) / 100; // find the rarest loot less than the chance roll if (chance < max_chance) { possible_ids.push_back(i-1); common_chance = ec->z; i=mapr->loot.size(); // start searching from the beginning continue; } } else { // include loot with identical chances if (ec->z == common_chance) possible_ids.push_back(i-1); } } if (!possible_ids.empty()) { // if there was more than one item with the same chance, randomly pick one of them int chosen_loot = 0; if (possible_ids.size() > 1) chosen_loot = rand() % possible_ids.size(); ec = &mapr->loot[chosen_loot]; p.x = ec->x + 0.5f; p.y = ec->y + 0.5f; new_loot.quantity = randBetween(ec->a,ec->b); // an item id of 0 means we should drop currency instead if (ec->s == "currency" || toInt(ec->s) == 0 || toInt(ec->s) == CURRENCY_ID) { new_loot.item = CURRENCY_ID; new_loot.quantity = new_loot.quantity * (100 + hero->get(STAT_CURRENCY_FIND)) / 100; } else { new_loot.item = toInt(ec->s); } addLoot(new_loot, p); } mapr->loot.clear(); } /** * This function is called when there definitely is a piece of loot dropping * calls addLoot() */ void LootManager::determineLootByEnemy(const Enemy *e, FPoint pos) { ItemStack new_loot; std::vector<int> possible_ids; std::vector<Point> possible_ranges; Point range; int common_chance = -1; int chance = rand() % 100; for (unsigned i=0; i<e->stats.loot.size(); i++) { if (possible_ids.empty()) { // Don't use item find bonus for currency int max_chance = e->stats.loot[i].chance; if (e->stats.loot[i].id != 0 && e->stats.loot[i].id != CURRENCY_ID) max_chance = e->stats.loot[i].chance * (hero->get(STAT_ITEM_FIND) + 100) / 100; // find the rarest loot less than the chance roll if (chance < max_chance) { possible_ids.push_back(e->stats.loot[i].id); common_chance = e->stats.loot[i].chance; range.x = e->stats.loot[i].count_min; range.y = e->stats.loot[i].count_max; possible_ranges.push_back(range); i=-1; // start searching from the beginning continue; } } else { // include loot with identical chances if (e->stats.loot[i].chance == common_chance) { possible_ids.push_back(e->stats.loot[i].id); range.x = e->stats.loot[i].count_min; range.y = e->stats.loot[i].count_max; possible_ranges.push_back(range); } } } if (!possible_ids.empty()) { int roll = rand() % possible_ids.size(); new_loot.item = possible_ids[roll]; new_loot.quantity = randBetween(possible_ranges[roll].x, possible_ranges[roll].y); // an item id of 0 means we should drop currency instead if (new_loot.item == 0 || new_loot.item == CURRENCY_ID) { new_loot.item = CURRENCY_ID; new_loot.quantity = (new_loot.quantity * (100 + hero->get(STAT_CURRENCY_FIND))) / 100; } addLoot(new_loot, pos); } } void LootManager::addLoot(ItemStack stack, FPoint pos) { // TODO: z-sort insert? Loot ld; ld.stack = stack; ld.pos.x = pos.x; ld.pos.y = pos.y; int index = items->items[stack.item].loot_animation.size()-1; for (unsigned int i=0; i<items->items[stack.item].loot_animation.size(); i++) { if (stack.quantity >= items->items[stack.item].loot_animation[i].low && (stack.quantity <= items->items[stack.item].loot_animation[i].high || items->items[stack.item].loot_animation[i].high == 0)) { index = i; break; } } ld.loadAnimation(items->items[stack.item].loot_animation[index].name); loot.push_back(ld); snd->play(sfx_loot, GLOBAL_VIRTUAL_CHANNEL, pos, false); } /** * Click on the map to pick up loot. We need the camera position to translate * screen coordinates to map locations. We need the hero position because * the hero has to be within range to pick up an item. */ ItemStack LootManager::checkPickup(Point mouse, FPoint cam, FPoint hero_pos, MenuInventory *inv) { SDL_Rect r; ItemStack loot_stack; loot_stack.item = 0; loot_stack.quantity = 0; // I'm starting at the end of the loot list so that more recently-dropped // loot is picked up first. If a player drops several loot in the same // location, picking it back up will work like a stack. vector<Loot>::iterator it; for (it = loot.end(); it != loot.begin(); ) { --it; // loot close enough to pickup? if (fabs(hero_pos.x - it->pos.x) < INTERACT_RANGE && fabs(hero_pos.y - it->pos.y) < INTERACT_RANGE && !it->isFlying()) { Point p = map_to_screen(it->pos.x, it->pos.y, cam.x, cam.y); r.w = 32; r.h = 48; r.x = p.x - 16; r.y = p.y - 32; // clicked in pickup hotspot? if (mouse.x > r.x && mouse.x < r.x+r.w && mouse.y > r.y && mouse.y < r.y+r.h) { if (it->stack.item > 0 && !(inv->full(it->stack.item))) { loot_stack = it->stack; it = loot.erase(it); return loot_stack; } else if (it->stack.item > 0) { full_msg = true; } } } } return loot_stack; } /** * Autopickup loot if enabled in the engine * Currently, only currency is checked for autopickup */ ItemStack LootManager::checkAutoPickup(FPoint hero_pos, MenuInventory *inv) { ItemStack loot_stack; loot_stack.item = 0; loot_stack.quantity = 0; vector<Loot>::iterator it; for (it = loot.end(); it != loot.begin(); ) { --it; if (fabs(hero_pos.x - it->pos.x) < INTERACT_RANGE && fabs(hero_pos.y - it->pos.y) < INTERACT_RANGE && !it->isFlying()) { if (it->stack.item == CURRENCY_ID && AUTOPICKUP_CURRENCY) { if (!(inv->full(it->stack.item))) { loot_stack = it->stack; it = loot.erase(it); return loot_stack; } } } } return loot_stack; } ItemStack LootManager::checkNearestPickup(FPoint hero_pos, MenuInventory *inv) { ItemStack loot_stack; loot_stack.item = 0; loot_stack.quantity = 0; float best_distance = std::numeric_limits<float>::max(); vector<Loot>::iterator it; vector<Loot>::iterator nearest = loot.end(); for (it = loot.end(); it != loot.begin(); ) { --it; float distance = calcDist(hero_pos, it->pos); if (distance < INTERACT_RANGE && distance < best_distance) { best_distance = distance; nearest = it; } } if (nearest != loot.end()) { if (nearest->stack.item > 0 && !(inv->full(nearest->stack.item))) { loot_stack = nearest->stack; loot.erase(nearest); return loot_stack; } else if (nearest->stack.item > 0) { full_msg = true; } } return loot_stack; } void LootManager::addRenders(vector<Renderable> &ren, vector<Renderable> &ren_dead) { vector<Loot>::iterator it; for (it = loot.begin(); it != loot.end(); ++it) { Renderable r = it->animation->getCurrentFrame(0); r.map_pos.x = it->pos.x; r.map_pos.y = it->pos.y; (it->animation->isLastFrame() ? ren_dead : ren).push_back(r); } } LootManager::~LootManager() { // remove all items in the item database for (unsigned int i=0; i < items->items.size(); i++) { if (items->items[i].loot_animation.empty()) continue; for (unsigned int j=0; j<items->items[i].loot_animation.size(); j++) { anim->decreaseCount(items->items[i].loot_animation[j].name); } } // remove items, so Loots get destroyed! loot.clear(); anim->cleanUp(); snd->unload(sfx_loot); delete tip; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/LootManager.h�����������������������������������������������������������������0000664�0000000�0000000�00000004671�12247171015�0017157�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class LootManager * * Handles floor loot */ #pragma once #ifndef LOOT_MANAGER_H #define LOOT_MANAGER_H #include "CommonIncludes.h" #include "ItemManager.h" #include "Loot.h" #include "Settings.h" class Animation; class EnemyManager; class MenuInventory; class WidgetTooltip; // this means that normal items are 10x more common than epic items // these numbers have to be balanced by various factors const int RARITY_LOW = 7; const int RARITY_NORMAL = 10; const int RARITY_HIGH = 3; const int RARITY_EPIC = 1; class LootManager { private: WidgetTooltip *tip; StatBlock *hero; // functions void loadGraphics(); SoundManager::SoundID sfx_loot; // loot refers to ItemManager indices std::vector<Loot> loot; SDL_Rect animation_pos; Point animation_offset; // enemies which should drop loot, but didnt yet. std::vector<const class Enemy*> enemiesDroppingLoot; public: LootManager(StatBlock *_hero); LootManager(const LootManager ©); // not implemented ~LootManager(); void handleNewMap(); void logic(); void renderTooltips(FPoint cam); void checkEnemiesForLoot(); // called by enemy, who definitly wants to drop loot. void addEnemyLoot(const Enemy *e); void checkMapForLoot(); void determineLootByEnemy(const Enemy *e, FPoint pos); // pick from enemy-specific loot table void addLoot(ItemStack stack, FPoint pos); ItemStack checkPickup(Point mouse, FPoint cam, FPoint hero_pos, MenuInventory *inv); ItemStack checkAutoPickup(FPoint hero_pos, MenuInventory *inv); ItemStack checkNearestPickup(FPoint hero_pos, MenuInventory *inv); void addRenders(std::vector<Renderable> &ren, std::vector<Renderable> &ren_dead); int tooltip_margin; // pixels between loot drop center and label bool full_msg; }; #endif �����������������������������������������������������������������������flare-engine-0.19/src/Map.cpp�����������������������������������������������������������������������0000664�0000000�0000000�00000017405�12247171015�0016016�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012-2013 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "Map.h" #include "FileParser.h" #include "UtilsParsing.h" #include "Settings.h" Map::Map() : events() , enemy_groups() , filename("") , layers() , w(0) , h(0) , spawn() , spawn_dir(0) { } void Map::clearLayers() { for (unsigned i = 0; i < layers.size(); ++i) delete[] layers[i]; layers.clear(); layernames.clear(); } void Map::clearQueues() { enemies = std::queue<Map_Enemy>(); npcs = std::queue<Map_NPC>(); } void Map::clearEvents() { events.clear(); } int Map::load(std::string fname) { FileParser infile; maprow *cur_layer = NULL; clearEvents(); clearLayers(); clearQueues(); // @CLASS Map|Description of maps/ if (!infile.open("maps/" + fname)) return 0; this->filename = fname; while (infile.next()) { if (infile.new_section) { // for sections that are stored in collections, add a new object here if (infile.section == "enemy") enemies.push(Map_Enemy()); else if (infile.section == "enemygroup") enemy_groups.push(Map_Group()); else if (infile.section == "npc") npcs.push(Map_NPC()); else if (infile.section == "event") events.push_back(Event()); } if (infile.section == "header") loadHeader(infile); else if (infile.section == "layer") loadLayer(infile, &cur_layer); else if (infile.section == "enemy") loadEnemy(infile); else if (infile.section == "enemygroup") loadEnemyGroup(infile, &enemy_groups.back()); else if (infile.section == "npc") loadNPC(infile); else if (infile.section == "event") EventManager::loadEvent(infile, &events.back()); } infile.close(); return 0; } void Map::loadHeader(FileParser &infile) { if (infile.key == "title") { // @ATTR title|string|Title of map this->title = msg->get(infile.val); } else if (infile.key == "width") { // @ATTR width|integer|Width of map this->w = toInt(infile.val); } else if (infile.key == "height") { // @ATTR height|integer|Height of map this->h = toInt(infile.val); } else if (infile.key == "tileset") { // @ATTR tileset|string|Tileset to use for map this->tileset = infile.val; } else if (infile.key == "music") { // @ATTR music|string|Background music to use for map music_filename = infile.val; } else if (infile.key == "location") { // @ATTR location|[x(integer), y(integer), direction(integer))|Spawn point location in map spawn.x = toInt(infile.nextValue()) + 0.5f; spawn.y = toInt(infile.nextValue()) + 0.5f; spawn_dir = toInt(infile.nextValue()); } } void Map::loadLayer(FileParser &infile, maprow **current_layer) { if (infile.key == "type") { // @ATTR layer.type|string|Map layer type. *current_layer = new maprow[w]; layers.push_back(*current_layer); layernames.push_back(infile.val); } else if (infile.key == "format") { // @ATTR layer.format|string|Format for map layer, must be 'dec' if (infile.val != "dec") { fprintf(stderr, "ERROR: maploading: The format of a layer must be \"dec\"!\n"); SDL_Quit(); exit(1); } } else if (infile.key == "data") { // @ATTR layer.data|raw|Raw map layer data // layer map data handled as a special case // The next h lines must contain layer data. TODO: err for (int j=0; j<h; j++) { std::string val = infile.getRawLine() + ','; for (int i=0; i<w; i++) (*current_layer)[i][j] = eatFirstInt(val, ','); } } } void Map::loadEnemy(FileParser &infile) { if (infile.key == "type") { // @ATTR enemy.type|string|Enemy type enemies.back().type = infile.val; } else if (infile.key == "location") { // @ATTR enemy.location|[x(integer), y(integer)]|Location of enemy enemies.back().pos.x = toInt(infile.nextValue()) + 0.5f; enemies.back().pos.y = toInt(infile.nextValue()) + 0.5f; } else if (infile.key == "direction") { // @ATTR enemy.direction|integer|Direction of enemy enemies.back().direction = toInt(infile.val); } else if (infile.key == "waypoints") { // @ATTR enemy.waypoint|[x(integer), y(integer)]|Enemy waypoint std::string none = ""; std::string a = infile.nextValue(); std::string b = infile.nextValue(); while (a != none) { FPoint p; p.x = toInt(a) + 0.5f; p.y = toInt(b) + 0.5f; enemies.back().waypoints.push(p); a = infile.nextValue(); b = infile.nextValue(); } } else if (infile.key == "wander_area") { // @ATTR enemy.wander_area|[x(integer),y(integer),w(integer),h(integer)]|Wander area for the enemy. enemies.back().wander = true; enemies.back().wander_area.x = toInt(infile.nextValue()); enemies.back().wander_area.y = toInt(infile.nextValue()); enemies.back().wander_area.w = toInt(infile.nextValue()); enemies.back().wander_area.h = toInt(infile.nextValue()); } // @ATTR enemy.requires_status|string|Status required for enemy load else if (infile.key == "requires_status") enemies.back().requires_status.push_back(infile.nextValue()); // @ATTR enemy.requires_not_status|string|Status required to be missing for enemy load else if (infile.key == "requires_not_status") enemies.back().requires_not_status.push_back(infile.nextValue()); } void Map::loadEnemyGroup(FileParser &infile, Map_Group *group) { if (infile.key == "type") { // @ATTR enemygroup.type|string|Type of enemy group group->category = infile.val; } else if (infile.key == "level") { // @ATTR enemygroup.level|[min(integer), max(integer)]|Defines the level range of enemies in group. group->levelmin = toInt(infile.nextValue()); group->levelmax = toInt(infile.nextValue()); } else if (infile.key == "location") { // @ATTR enemygroup.location|[x(integer), y(integer), x2(integer), y2(integer)]|Location area for enemygroup group->pos.x = toInt(infile.nextValue()); group->pos.y = toInt(infile.nextValue()); group->area.x = toInt(infile.nextValue()); group->area.y = toInt(infile.nextValue()); } else if (infile.key == "number") { // @ATTR enemygroup.number|[min(integer), max(integer]|Defines the range of enemies in group. If only one number is given, it's the exact amount. group->numbermin = toInt(infile.nextValue()); group->numbermax = toInt(infile.nextValue(), group->numbermin); } else if (infile.key == "chance") { // @ATTR enemygroup.chance|integer|Percentage of chance float n = toInt(infile.nextValue()) / 100.0f; group->chance = std::min(1.0f, std::max(0.0f, n)); } } void Map::loadNPC(FileParser &infile) { std::string s; if (infile.key == "type") { // @ATTR npc.type|string|Type of NPC npcs.back().id = infile.val; } if (infile.key == "requires_status") { // @ATTR npc.requires_status|string|Status required for NPC load. There can be multiple states, separated by comma while ( (s = infile.nextValue()) != "") npcs.back().requires_status.push_back(s); } if (infile.key == "requires_not_status") { // @ATTR npc.requires_not|string|Status required to be missing for NPC load. There can be multiple states, separated by comma while ( (s = infile.nextValue()) != "") npcs.back().requires_not_status.push_back(s); } else if (infile.key == "location") { // @ATTR npc.location|[x(integer), y(integer)]|Location of NPC npcs.back().pos.x = toInt(infile.nextValue()) + 0.5f; npcs.back().pos.y = toInt(infile.nextValue()) + 0.5f; } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/Map.h�������������������������������������������������������������������������0000664�0000000�0000000�00000005614�12247171015�0015462�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012-2013 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #ifndef MAP_H #define MAP_H #include <vector> #include <queue> #include "FileParser.h" #include "Utils.h" #include "StatBlock.h" #include "EventManager.h" typedef unsigned short maprow[256]; class Map_Group { public: std::string category; Point pos; Point area; int levelmin; int levelmax; int numbermin; int numbermax; float chance; Map_Group() : category("") , pos() , area() , levelmin(0) , levelmax(0) , numbermin(0) , numbermax(0) , chance(1.0f) {} }; class Map_NPC { public: std::string id; FPoint pos; std::vector<std::string> requires_status; std::vector<std::string> requires_not_status; Map_NPC() : id("") , pos() , requires_status() , requires_not_status() {} }; class Map_Enemy { public: std::string type; FPoint pos; int direction; std::queue<FPoint> waypoints; bool wander; SDL_Rect wander_area; bool hero_ally; int summon_power_index; StatBlock* summoner; std::vector<std::string> requires_status; std::vector<std::string> requires_not_status; Map_Enemy(std::string _type="", FPoint _pos=FPoint()) : type(_type) , pos(_pos) , direction(rand() % 8) , waypoints(std::queue<FPoint>()) , wander(false) , hero_ally(false) , summon_power_index(0) , summoner(NULL) , requires_status() , requires_not_status() { wander_area.x = 0; wander_area.y = 0; wander_area.w = 0; wander_area.h = 0; } }; class Map { protected: void loadHeader(FileParser &infile); void loadLayer(FileParser &infile, maprow **cur_layer); void loadEnemy(FileParser &infile); void loadEnemyGroup(FileParser &infile, Map_Group *group); void loadNPC(FileParser &infile); void clearLayers(); void clearQueues(); // map events std::vector<Event> events; std::queue<Map_Group> enemy_groups; std::string filename; std::string tileset; int load(std::string filename); public: Map(); std::string music_filename; std::vector<maprow*> layers; // visible layers in maprenderer std::vector<std::string> layernames; void clearEvents(); // enemy load handling std::queue<Map_Enemy> enemies; // npc load handling std::queue<Map_NPC> npcs; // vars std::string title; short w; short h; FPoint spawn; int spawn_dir; }; #endif // MAP_H ��������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MapCollision.cpp��������������������������������������������������������������0000664�0000000�0000000�00000035121�12247171015�0017665�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /* * MapCollision.h * RPGEngine * * Handle collisions between objects and the map */ #include "AStarNode.h" #include "MapCollision.h" #include "Settings.h" #include "AStarContainer.h" #include <cfloat> #include <math.h> #include <cassert> using namespace std; MapCollision::MapCollision() : map_size(Point()) { memset(colmap, 0, sizeof(colmap)); } void MapCollision::setmap(const unsigned short _colmap[][256], unsigned short w, unsigned short h) { for (int i=0; i<w; i++) for (int j=0; j<h; j++) colmap[i][j] = _colmap[i][j]; map_size.x = w; map_size.y = h; } int sgn(float f) { if (f > 0) return 1; else if (f < 0) return -1; else return 0; } bool MapCollision::small_step(float &x, float &y, float step_x, float step_y, MOVEMENTTYPE movement_type, bool is_hero) { if (is_valid_position(x + step_x, y + step_y, movement_type, is_hero)) { x += step_x; y += step_y; assert(is_valid_position(x,y,movement_type, is_hero)); return true; } else { return false; } } bool MapCollision::small_step_forced_slide_along_grid(float &x, float &y, float step_x, float step_y, MOVEMENTTYPE movement_type, bool is_hero) { if (is_valid_position(x + step_x, y, movement_type, is_hero)) { // slide along wall if (step_x == 0) return true; x += step_x; assert(is_valid_position(x,y,movement_type, is_hero)); } else if (is_valid_position(x, y + step_y, movement_type, is_hero)) { if (step_y == 0) return true; y += step_y; assert(is_valid_position(x,y,movement_type, is_hero)); } else { return false; } return true; } bool MapCollision::small_step_forced_slide(float &x, float &y, float step_x, float step_y, MOVEMENTTYPE movement_type, bool is_hero) { // is there a singular obstacle or corner we can step around? // only works if we are moving straight const float epsilon = 0.01f; if (step_x != 0) { assert(step_y == 0); float dy = y - floor(y); if (is_valid_tile((int)floor(x), (int)floor(y) + 1, movement_type, is_hero) && is_valid_tile((int)floor(x) + sgn(step_x), (int)floor(y) + 1, movement_type, is_hero) && dy > 0.5) { y += 1 - dy + epsilon; x += step_x; } else if (is_valid_tile((int)floor(x), (int)floor(y) - 1, movement_type, is_hero) && is_valid_tile((int)floor(x) + sgn(step_x), (int)floor(y) - 1, movement_type, is_hero) && dy < 0.5) { y -= dy + epsilon; x += step_x; } else { return false; } assert(is_valid_position(x,y,movement_type, is_hero)); } else if (step_y != 0) { assert(step_x == 0); float dx = x - floor(x); if (is_valid_tile((int)floor(x) + 1, (int)floor(y), movement_type, is_hero) && is_valid_tile((int)floor(x) + 1, (int)floor(y) + sgn(step_y), movement_type, is_hero) && dx > 0.5) { x += 1 - dx + epsilon; y += step_y; } else if (is_valid_tile((int)floor(x) - 1, (int)floor(y), movement_type, is_hero) && is_valid_tile((int)floor(x) - 1, (int)floor(y) + sgn(step_y), movement_type, is_hero) && dx < 0.5) { x -= dx + epsilon; y += step_y; } else { return false; } } else { assert(false); } return true; } /** * Process movement for cardinal (90 degree) and ordinal (45 degree) directions * If we encounter an obstacle at 90 degrees, stop. * If we encounter an obstacle at 45 or 135 degrees, slide. */ bool MapCollision::move(float &x, float &y, float _step_x, float _step_y, MOVEMENTTYPE movement_type, bool is_hero) { // when trying to slide against a bottom or right wall, step_x or step_y can become 0 // this causes diag to become false, making this function return false // we try to catch such a scenario and return true early bool force_slide = (_step_x != 0 && _step_y != 0); while (_step_x != 0 || _step_y != 0) { float step_x = 0; if (_step_x > 0) { // find next interesting value, which is either the whole step, or the transition to the next tile step_x = min((float)ceil(x) - x, _step_x); // if we are standing on the edge of a tile (ceil(x) - x == 0), we need to look one tile ahead if (step_x <= MIN_TILE_GAP) step_x = min(1.f, _step_x); } else if (_step_x < 0) { step_x = max((float)floor(x) - x, _step_x); if (step_x == 0) step_x = max(-1.f, _step_x); } float step_y = 0; if (_step_y > 0) { step_y = min((float)ceil(y) - y, _step_y); if (step_y <= MIN_TILE_GAP) step_y = min(1.f, _step_y); } else if (_step_y < 0) { step_y = max((float)floor(y) - y, _step_y); if (step_y == 0) step_y = max(-1.f, _step_y); } _step_x -= step_x; _step_y -= step_y; if (!small_step(x, y, step_x, step_y, movement_type, is_hero)) { if (force_slide) { if (!small_step_forced_slide_along_grid(x, y, step_x, step_y, movement_type, is_hero)) return false; } else { if (!small_step_forced_slide(x, y, step_x, step_y, movement_type, is_hero)) return false; } } } return true; } /** * Determines whether the grid position is outside the map boundary */ bool MapCollision::is_outside_map(const int& tile_x, const int& tile_y) const { return (tile_x < 0 || tile_y < 0 || tile_x >= map_size.x || tile_y >= map_size.y); } /** * A map space is empty if it contains no blocking type * A position outside the map boundary is not empty */ bool MapCollision::is_empty(const float& x, const float& y) const { // map bounds check const int tile_x = (int)floor(x); const int tile_y = (int)floor(y); if (is_outside_map(tile_x, tile_y)) return false; // collision type check return (colmap[tile_x][tile_y] == BLOCKS_NONE || colmap[tile_x][tile_y] == MAP_ONLY || colmap[tile_x][tile_y] == MAP_ONLY_ALT); } /** * A map space is a wall if it contains a wall blocking type (normal or hidden) * A position outside the map boundary is a wall */ bool MapCollision::is_wall(const float& x, const float& y) const { // bounds check const int tile_x = (int)floor(x); const int tile_y = (int)floor(y); if (is_outside_map(tile_x, tile_y)) return true; // collision type check return (colmap[tile_x][tile_y] == BLOCKS_ALL || colmap[tile_x][tile_y] == BLOCKS_ALL_HIDDEN); } /** * Is this a valid tile for an entity with this movement type? */ bool MapCollision::is_valid_tile(const int& tile_x, const int& tile_y, MOVEMENTTYPE movement_type, bool is_hero) const { // outside the map isn't valid if (is_outside_map(tile_x,tile_y)) return false; if(is_hero) { if(colmap[tile_x][tile_y] == BLOCKS_ENEMIES && !ENABLE_ALLY_COLLISION) return true; } else if(colmap[tile_x][tile_y] == BLOCKS_ENEMIES) return false; // occupied by an entity isn't valid if (colmap[tile_x][tile_y] == BLOCKS_ENTITIES) return false; // intangible creatures can be everywhere if (movement_type == MOVEMENT_INTANGIBLE) return true; // flying creatures can't be in walls if (movement_type == MOVEMENT_FLYING) { return (!(colmap[tile_x][tile_y] == BLOCKS_ALL || colmap[tile_x][tile_y] == BLOCKS_ALL_HIDDEN)); } if (colmap[tile_x][tile_y] == MAP_ONLY || colmap[tile_x][tile_y] == MAP_ONLY_ALT) return true; // normal creatures can only be in empty spaces return (colmap[tile_x][tile_y] == BLOCKS_NONE); } /** * Is this a valid position for an entity with this movement type? */ bool MapCollision::is_valid_position(const float& x, const float& y, MOVEMENTTYPE movement_type, bool is_hero) const { return is_valid_tile((int)floor(x), (int)floor(y), movement_type, is_hero); } /** * Does not have the "slide" submovement that move() features * Line can be arbitrary angles. */ bool MapCollision::line_check(const float& x1, const float& y1, const float& x2, const float& y2, int check_type, MOVEMENTTYPE movement_type) { float x = x1; float y = y1; float dx = fabs(x2 - x1); float dy = fabs(y2 - y1); float step_x; float step_y; int steps = (int)max(dx, dy); if (dx > dy) { step_x = 1; step_y = dy / dx; } else { step_y = 1; step_x = dx / dy; } // fix signs if (x1 > x2) step_x = -step_x; if (y1 > y2) step_y = -step_y; if (check_type == CHECK_SIGHT) { for (int i=0; i<steps; i++) { x += step_x; y += step_y; if (is_wall(x, y)) return false; } } else if (check_type == CHECK_MOVEMENT) { for (int i=0; i<steps; i++) { x += step_x; y += step_y; if (!is_valid_position(x, y, movement_type, false)) return false; } } return true; } bool MapCollision::line_of_sight(const float& x1, const float& y1, const float& x2, const float& y2) { return line_check(x1, y1, x2, y2, CHECK_SIGHT, MOVEMENT_NORMAL); } bool MapCollision::line_of_movement(const float& x1, const float& y1, const float& x2, const float& y2, MOVEMENTTYPE movement_type) { if (is_outside_map(x2, y2)) return false; // intangible entities can always move if (movement_type == MOVEMENT_INTANGIBLE) return true; // if the target is blocking, clear it temporarily int tile_x = (int)floor(x2); int tile_y = (int)floor(y2); bool target_blocks = false; int target_blocks_type = colmap[tile_x][tile_y]; if (colmap[tile_x][tile_y] == BLOCKS_ENTITIES || colmap[tile_x][tile_y] == BLOCKS_ENEMIES) { target_blocks = true; unblock(x2,y2); } bool has_movement = line_check(x1, y1, x2, y2, CHECK_MOVEMENT, movement_type); if (target_blocks) block(x2,y2, target_blocks_type == BLOCKS_ENEMIES); return has_movement; } /** * Checks whether the entity in pos 1 is facing the point at pos 2 * based on a 180 degree field of vision */ bool MapCollision::is_facing(const float& x1, const float& y1, char direction, const float& x2, const float& y2) { // 180 degree fov switch (direction) { case 2: //north west return ((x2-x1) < ((-1 * y2)-(-1 * y1))) && (((-1 * x2)-(-1 * x1)) > (y2-y1)); case 3: //north return y2 < y1; case 4: //north east return (((-1 * x2)-(-1 * x1)) < ((-1 * y2)-(-1 * y1))) && ((x2-x1) > (y2-y1)); case 5: //east return x2 > x1; case 6: //south east return ((x2-x1) > ((-1 * y2)-(-1 * y1))) && (((-1 * x2)-(-1 * x1)) < (y2-y1)); case 7: //south return y2 > y1; case 0: //south west return (((-1 * x2)-(-1 * x1)) > ((-1 * y2)-(-1 * y1))) && ((x2-x1) < (y2-y1)); case 1: //west return x2 < x1; } return false; } /** * Compute a path from (x1,y1) to (x2,y2) * Store waypoint inside path * limit is the maximum number of explored node * @return true if a path is found */ bool MapCollision::compute_path(FPoint start_pos, FPoint end_pos, vector<FPoint> &path, MOVEMENTTYPE movement_type, unsigned int limit) { if (is_outside_map(end_pos.x, end_pos.y)) return false; if (limit == 0) limit = 256; // path must be empty if (!path.empty()) path.clear(); // convert start & end to MapCollision precision Point start = map_to_collision(start_pos); Point end = map_to_collision(end_pos); // if the target square has an entity, temporarily clear it to compute the path bool target_blocks = false; int target_blocks_type = colmap[end.x][end.y]; if (colmap[end.x][end.y] == BLOCKS_ENTITIES || colmap[end.x][end.y] == BLOCKS_ENEMIES) { target_blocks = true; unblock(end_pos.x, end_pos.y); } Point current = start; AStarNode* node = new AStarNode(start); node->setActualCost(0); node->setEstimatedCost((float)calcDist(start,end)); node->setParent(current); AStarContainer open(map_size.x, limit); AStarCloseContainer close(map_size.x, limit); open.add(node); while (!open.isEmpty() && (unsigned)close.getSize() < limit) { node = open.get_shortest_f(); current.x = node->getX(); current.y = node->getY(); close.add(node); open.remove(node); if ( current.x == end.x && current.y == end.y) break; //path found ! //limit evaluated nodes to the size of the map list<Point> neighbours = node->getNeighbours(map_size.x, map_size.y); // for every neighbour of current node for (list<Point>::iterator it=neighbours.begin(); it != neighbours.end(); ++it) { Point neighbour = *it; // if neighbour is not free of any collision, skip it if (!is_valid_tile(neighbour.x,neighbour.y,movement_type, false)) continue; // if nabour is already in close, skip it if(close.exists(neighbour)) continue; // if neighbour isn't inside open, add it as a new Node if(!open.exists(neighbour)) { AStarNode* newNode = new AStarNode(neighbour.x,neighbour.y); newNode->setActualCost(node->getActualCost()+(float)calcDist(current,neighbour)); newNode->setParent(current); newNode->setEstimatedCost((float)calcDist(neighbour,end)); open.add(newNode); } // else, update it's cost if better else { AStarNode* i = open.get(neighbour.x, neighbour.y); if (node->getActualCost()+(float)calcDist(current,neighbour) < i->getActualCost()) { Point pos(i->getX(), i->getY()); Point parent_pos(node->getX(), node->getY()); open.updateParent(pos, parent_pos, node->getActualCost()+(float)calcDist(current,neighbour)); } } } } if (current.x != end.x || current.y != end.y) { //couldnt find the target so map a path to the closest node found node = close.get_shortest_h(); current.x = node->getX(); current.y = node->getY(); while (current.x != start.x || current.y != start.y) { path.push_back(collision_to_map(current)); current = close.get(current.x, current.y)->getParent(); } } else { // store path from end to start path.push_back(collision_to_map(end)); while (current.x != start.x || current.y != start.y) { path.push_back(collision_to_map(current)); current = close.get(current.x, current.y)->getParent(); } } // reblock target if needed if (target_blocks) block(end_pos.x, end_pos.y, target_blocks_type == BLOCKS_ENEMIES); return !path.empty(); } void MapCollision::block(const float& map_x, const float& map_y, bool is_ally) { const int tile_x = (int)floor(map_x); const int tile_y = (int)floor(map_y); if (colmap[tile_x][tile_y] == BLOCKS_NONE) { if(is_ally) colmap[tile_x][tile_y] = BLOCKS_ENEMIES; else colmap[tile_x][tile_y] = BLOCKS_ENTITIES; } } void MapCollision::unblock(const float& map_x, const float& map_y) { const int tile_x = (int)floor(map_x); const int tile_y = (int)floor(map_y); if (colmap[tile_x][tile_y] == BLOCKS_ENTITIES || colmap[tile_x][tile_y] == BLOCKS_ENEMIES) { colmap[tile_x][tile_y] = BLOCKS_NONE; } } MapCollision::~MapCollision() { } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MapCollision.h����������������������������������������������������������������0000664�0000000�0000000�00000007311�12247171015�0017332�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /* * MapCollision.h * RPGEngine * * Handle collisions between objects and the map */ #pragma once #ifndef MAP_COLLISION_H #define MAP_COLLISION_H #include "CommonIncludes.h" #include "Utils.h" #include <cstdlib> // collision tile types // The numbers 0..6 are the collision tiles as produced by tiled, // only 7 and 8 deal with entities on the map const int BLOCKS_NONE = 0; const int BLOCKS_ALL = 1; const int BLOCKS_MOVEMENT = 2; const int BLOCKS_ALL_HIDDEN = 3; const int BLOCKS_MOVEMENT_HIDDEN = 4; const int MAP_ONLY = 5; const int MAP_ONLY_ALT = 6; const int BLOCKS_ENTITIES = 7; // hero or enemies are blocking this tile, so any other entity is blocked const int BLOCKS_ENEMIES = 8; // an ally is standing on that tile, so the hero could pass if ENABLE_ALLY_COLLISION is false // collision check types const int CHECK_MOVEMENT = 1; const int CHECK_SIGHT = 2; // movement options typedef enum { MOVEMENT_NORMAL = 0, MOVEMENT_FLYING = 1, // can move through BLOCKS_MOVEMENT (e.g. water) MOVEMENT_INTANGIBLE = 2 // can move through BLOCKS_ALL (e.g. walls) } MOVEMENTTYPE; // this value is used to determine the greatest possible position within a tile before transitioning to the next tile // so if an entity has a position of (1-MIN_TILE_GAP, 0) and moves to the east, they will move to (1,0) const float MIN_TILE_GAP = 0.001f; class MapCollision { private: bool line_check(const float& x1, const float& y1, const float& x2, const float& y2, int check_type, MOVEMENTTYPE movement_type); bool small_step_forced_slide_along_grid( float &x, float &y, float step_x, float step_y, MOVEMENTTYPE movement_type, bool is_hero); bool small_step_forced_slide( float &x, float &y, float step_x, float step_y, MOVEMENTTYPE movement_type, bool is_hero); bool small_step( float &x, float &y, float step_x, float step_y, MOVEMENTTYPE movement_type, bool is_hero); bool is_valid_tile(const int& x, const int& y, MOVEMENTTYPE movement_type, bool is_hero) const; public: MapCollision(); ~MapCollision(); void setmap(const unsigned short _colmap[][256], unsigned short w, unsigned short h); bool move(float &x, float &y, float step_x, float step_y, MOVEMENTTYPE movement_type, bool is_hero); bool is_outside_map(const int& tile_x, const int& tile_y) const; bool is_empty(const float& x, const float& y) const; bool is_wall(const float& x, const float& y) const; bool is_valid_position(const float& x, const float& y, MOVEMENTTYPE movement_type, bool is_hero) const; bool line_of_sight(const float& x1, const float& y1, const float& x2, const float& y2); bool line_of_movement(const float& x1, const float& y1, const float& x2, const float& y2, MOVEMENTTYPE movement_type); bool is_facing(const float& x1, const float& y1, char direction, const float& x2, const float& y2); bool compute_path(FPoint start, FPoint end, std::vector<FPoint> &path, MOVEMENTTYPE movement_type, unsigned int limit = 0); void block(const float& map_x, const float& map_y, bool is_ally); void unblock(const float& map_x, const float& map_y); unsigned short colmap[256][256]; Point map_size; }; #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MapRenderer.cpp���������������������������������������������������������������0000664�0000000�0000000�00000056555�12247171015�0017516�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "CampaignManager.h" #include "CommonIncludes.h" #include "EnemyGroupManager.h" #include "FileParser.h" #include "MapRenderer.h" #include "PowerManager.h" #include "SharedGameResources.h" #include "SharedResources.h" #include "StatBlock.h" #include "UtilsFileSystem.h" #include "UtilsMath.h" #include "UtilsParsing.h" #include "WidgetTooltip.h" #include <stdint.h> #include <limits> #include <math.h> using namespace std; MapRenderer::MapRenderer() : Map() , music(NULL) , tip(new WidgetTooltip()) , tip_pos() , show_tooltip(false) , shakycam() , backgroundsurface(NULL) , backgroundsurfaceoffset() , cam() , map_change(false) , teleportation(false) , teleport_destination() , respawn_point() , cutscene(false) , cutscene_file("") , log_msg("") , shaky_cam_ticks(0) , stash(false) , stash_pos() , enemies_cleared(false) , repaint_background(false) , index_objectlayer(0) { } void MapRenderer::clearQueues() { Map::clearQueues(); loot.clear(); } bool MapRenderer::enemyGroupPlaceEnemy(float x, float y, Map_Group &g) { if (collider.is_empty(x, y)) { Enemy_Level enemy_lev = enemyg->getRandomEnemy(g.category, g.levelmin, g.levelmax); if (!enemy_lev.type.empty()) { Map_Enemy group_member = Map_Enemy(enemy_lev.type, FPoint(x, y)); collider.block(x, y, false); enemies.push(group_member); } return true; } return false; } void MapRenderer::pushEnemyGroup(Map_Group g) { // activate at all? float activate_chance = (rand() % 100) / 100.0f; if (activate_chance > g.chance) { return; } // The algorithm tries to place the enemies at random locations. // However if a location is not possible (unwalkable or there is already an entity), // then try again. // This could result in an infinite loop if there were more enemies than // actual places, so have an upper bound of tries. // random number of enemies int enemies_to_spawn = randBetween(g.numbermin, g.numbermax); // pick an upper bound, which is definitely larger than threetimes the enemy number to spawn. int allowed_misses = 5 * g.numbermax; while (enemies_to_spawn && allowed_misses) { float x = (g.pos.x + (rand() % g.area.x)) + 0.5f; float y = (g.pos.y + (rand() % g.area.y)) + 0.5f; if (enemyGroupPlaceEnemy(x, y, g)) enemies_to_spawn--; else allowed_misses--; } if (enemies_to_spawn) { // now that the fast method of spawning enemies doesn't work, but we // still have enemies to place, do not place them randomly, but at the // first free spot for (int x = g.pos.x; x < g.pos.x + g.area.x && enemies_to_spawn; x++) for (int y = g.pos.y; y < g.pos.y + g.area.y && enemies_to_spawn; y++) if (enemyGroupPlaceEnemy(x, y, g)) enemies_to_spawn--; } if (enemies_to_spawn) { fprintf(stderr, "Could not spawn all enemies in group at %s (x=%d,y=%d,w=%d,h=%d), %d missing (min=%d max=%d)\n", filename.c_str(), g.pos.x, g.pos.y, g.area.x, g.area.y, enemies_to_spawn, g.numbermin, g.numbermax); } } /** * No guarantee that maps will use all layers * Clear all tile layers (e.g. when loading a map) */ void MapRenderer::clearLayers() { Map::clearLayers(); SDL_FreeSurface(backgroundsurface); backgroundsurface = 0; index_objectlayer = 0; } int MapRenderer::load(std::string fname) { /* unload sounds */ snd->reset(); while (!sids.empty()) { snd->unload(sids.back()); sids.pop_back(); } show_tooltip = false; Map::load(fname); loadMusic(); for (unsigned i = 0; i < layers.size(); ++i) { if (layernames[i] == "collision") { collider.setmap(layers[i], w, h); layernames.erase(layernames.begin() + i); delete[] layers[i]; layers.erase(layers.begin() + i); } } for (unsigned i = 0; i < layers.size(); ++i) if (layernames[i] == "object") index_objectlayer = i; while (!enemy_groups.empty()) { pushEnemyGroup(enemy_groups.front()); enemy_groups.pop(); } tset.load(this->tileset); // some events automatically trigger when the map loads // e.g. change map state based on campaign status executeOnLoadEvents(); return 0; } void MapRenderer::loadMusic() { // keep playing if already the correct track if (played_music_filename == music_filename) return; played_music_filename = music_filename; if (music) { Mix_HaltMusic(); Mix_FreeMusic(music); music = NULL; } if (AUDIO && MUSIC_VOLUME) { music = Mix_LoadMUS(mods->locate(played_music_filename).c_str()); if(!music) fprintf(stderr, "Mix_LoadMUS: %s\n", Mix_GetError()); } if (music) { Mix_VolumeMusic(MUSIC_VOLUME); Mix_PlayMusic(music, -1); } } void MapRenderer::logic() { // handle camera shaking timer if (shaky_cam_ticks > 0) shaky_cam_ticks--; // handle tile set logic e.g. animations tset.logic(); // handle event cooldowns vector<Event>::iterator it; for (it = events.begin(); it < events.end(); ++it) { if ((*it).cooldown_ticks > 0) (*it).cooldown_ticks--; } } bool priocompare(const Renderable &r1, const Renderable &r2) { return r1.prio < r2.prio; } /** * Sort in the same order as the tiles are drawn * Depends upon the map implementation */ void calculatePriosIso(vector<Renderable> &r) { for (vector<Renderable>::iterator it = r.begin(); it != r.end(); ++it) { const unsigned tilex = (int)floor(it->map_pos.x); const unsigned tiley = (int)floor(it->map_pos.y); const int commax = (float)(it->map_pos.x - tilex) * (2<<16); const int commay = (float)(it->map_pos.y - tiley) * (2<<16); it->prio += (((uint64_t)(tilex + tiley)) << 54) + (((uint64_t)tilex) << 42) + ((commax + commay) << 16); } } void calculatePriosOrtho(vector<Renderable> &r) { for (vector<Renderable>::iterator it = r.begin(); it != r.end(); ++it) { const unsigned tilex = (int)floor(it->map_pos.x); const unsigned tiley = (int)floor(it->map_pos.y); const int commay = 1024 * it->map_pos.y; it->prio += (((uint64_t)tiley) << 48) + (((uint64_t)tilex) << 32) + (commay << 16); } } void MapRenderer::render(vector<Renderable> &r, vector<Renderable> &r_dead) { if (shaky_cam_ticks == 0) { shakycam.x = cam.x; shakycam.y = cam.y; } else { shakycam.x = cam.x + (rand() % 16 - 8) * 0.0078125f; shakycam.y = cam.y + (rand() % 16 - 8) * 0.0078125f; } if (TILESET_ORIENTATION == TILESET_ORTHOGONAL) { calculatePriosOrtho(r); calculatePriosOrtho(r_dead); std::sort(r.begin(), r.end(), priocompare); std::sort(r_dead.begin(), r_dead.end(), priocompare); renderOrtho(r, r_dead); } else { calculatePriosIso(r); calculatePriosIso(r_dead); std::sort(r.begin(), r.end(), priocompare); std::sort(r_dead.begin(), r_dead.end(), priocompare); renderIso(r, r_dead); } } void MapRenderer::createBackgroundSurface() { SDL_FreeSurface(backgroundsurface); backgroundsurface = createSurface( VIEW_W + 2 * movedistance_to_rerender * TILE_W * tset.max_size_x, VIEW_H + 2 * movedistance_to_rerender * TILE_H * tset.max_size_y); // background has no alpha: SDL_SetColorKey(backgroundsurface, 0, 0); } void MapRenderer::drawRenderable(vector<Renderable>::iterator r_cursor) { if (r_cursor->sprite) { SDL_Rect dest; Point p = map_to_screen(r_cursor->map_pos.x, r_cursor->map_pos.y, shakycam.x, shakycam.y); dest.x = p.x - r_cursor->offset.x; dest.y = p.y - r_cursor->offset.y; SDL_BlitSurface(r_cursor->sprite, &r_cursor->src, screen, &dest); } } void MapRenderer::renderIsoLayer(SDL_Surface *wheretorender, Point offset, const unsigned short layerdata[256][256]) { int_fast16_t i; // first index of the map array int_fast16_t j; // second index of the map array SDL_Rect dest; const Point upperleft = floor(screen_to_map(0, 0, shakycam.x, shakycam.y)); const int_fast16_t max_tiles_width = (VIEW_W / TILE_W) + 2 * tset.max_size_x; const int_fast16_t max_tiles_height = ((2 * VIEW_H / TILE_H) + 2 * tset.max_size_y) * 2; j = upperleft.y - tset.max_size_y + tset.max_size_x; i = upperleft.x - tset.max_size_y - tset.max_size_x; for (uint_fast16_t y = max_tiles_height ; y; --y) { int_fast16_t tiles_width = 0; // make sure the isometric corners are not rendered: // corner north west, upper left (i < 0) if (i < -1) { j += i + 1; tiles_width -= i + 1; i = -1; } // corner north east, upper right (j > mapheight) const int_fast16_t d = j - h; if (d >= 0) { j -= d; tiles_width += d; i += d; } // lower right (south east) corner is covered by (j+i-w+1) // lower left (south west) corner is caught by having 0 in there, so j>0 const int_fast16_t j_end = std::max(static_cast<int_fast16_t>(j+i-w+1), std::max(static_cast<int_fast16_t>(j - max_tiles_width), static_cast<int_fast16_t>(0))); Point p = map_to_screen(i, j, shakycam.x, shakycam.y); p = center_tile(p); // draw one horizontal line while (j > j_end) { --j; ++i; ++tiles_width; p.x += TILE_W; if (const uint_fast16_t current_tile = layerdata[i][j]) { dest.x = p.x - tset.tiles[current_tile].offset.x + offset.x; dest.y = p.y - tset.tiles[current_tile].offset.y + offset.y; // no need to set w and h in dest, as it is ignored // by SDL_BlitSurface SDL_BlitSurface(tset.sprites, &(tset.tiles[current_tile].src), wheretorender, &dest); } } j += tiles_width; i -= tiles_width; // Go one line deeper, the starting position goes zig-zag if (y % 2) i++; else j++; } } void MapRenderer::renderIsoBackObjects(vector<Renderable> &r) { vector<Renderable>::iterator it; for (it = r.begin(); it != r.end(); ++it) drawRenderable(it); } void MapRenderer::renderIsoFrontObjects(vector<Renderable> &r) { SDL_Rect dest; const Point upperleft = floor(screen_to_map(0, 0, shakycam.x, shakycam.y)); const int_fast16_t max_tiles_width = (VIEW_W / TILE_W) + 2 * tset.max_size_x; const int_fast16_t max_tiles_height = ((VIEW_H / TILE_H) + 2 * tset.max_size_y)*2; vector<Renderable>::iterator r_cursor = r.begin(); vector<Renderable>::iterator r_end = r.end(); // object layer int_fast16_t j = upperleft.y - tset.max_size_y + tset.max_size_x; int_fast16_t i = upperleft.x - tset.max_size_y - tset.max_size_x; while (r_cursor != r_end && ((int)(r_cursor->map_pos.x) + (int)(r_cursor->map_pos.y) < i + j || (int)(r_cursor->map_pos.x) < i)) // implicit floor ++r_cursor; if (index_objectlayer >= layers.size()) return; maprow *objectlayer = layers[index_objectlayer]; for (uint_fast16_t y = max_tiles_height ; y; --y) { int_fast16_t tiles_width = 0; // make sure the isometric corners are not rendered: if (i < -1) { j += i + 1; tiles_width -= i + 1; i = -1; } const int_fast16_t d = j - h; if (d >= 0) { j -= d; tiles_width += d; i += d; } const int_fast16_t j_end = std::max(static_cast<int_fast16_t>(j+i-w+1), std::max(static_cast<int_fast16_t>(j - max_tiles_width), static_cast<int_fast16_t>(0))); // draw one horizontal line Point p = map_to_screen(i, j, shakycam.x, shakycam.y); p = center_tile(p); while (j > j_end) { --j; ++i; ++tiles_width; p.x += TILE_W; if (const uint_fast16_t current_tile = objectlayer[i][j]) { dest.x = p.x - tset.tiles[current_tile].offset.x; dest.y = p.y - tset.tiles[current_tile].offset.y; SDL_BlitSurface(tset.sprites, &(tset.tiles[current_tile].src), screen, &dest); } // some renderable entities go in this layer while (r_cursor != r_end && ((int)r_cursor->map_pos.x == i && (int)r_cursor->map_pos.y == j)) { // implicit floor by int cast drawRenderable(r_cursor); ++r_cursor; } } j += tiles_width; i -= tiles_width; if (y % 2) i++; else j++; while (r_cursor != r_end && ((int)r_cursor->map_pos.x + (int)r_cursor->map_pos.y < i + j || (int)r_cursor->map_pos.x <= i)) // implicit floor by int cast ++r_cursor; } } void MapRenderer::renderIso(vector<Renderable> &r, vector<Renderable> &r_dead) { const Point nulloffset(0, 0); if (ANIMATED_TILES) { for (unsigned i = 0; i < index_objectlayer; ++i) renderIsoLayer(screen, nulloffset, layers[i]); } else { if (fabs(shakycam.x - backgroundsurfaceoffset.x) > movedistance_to_rerender || fabs(shakycam.y - backgroundsurfaceoffset.y) > movedistance_to_rerender || repaint_background) { if (!backgroundsurface) createBackgroundSurface(); repaint_background = false; backgroundsurfaceoffset = shakycam; SDL_FillRect(backgroundsurface, 0, 0); Point off(VIEW_W_HALF, VIEW_H_HALF); for (unsigned i = 0; i < index_objectlayer; ++i) renderIsoLayer(backgroundsurface, off, layers[i]); } Point p = map_to_screen(shakycam.x, shakycam.y , backgroundsurfaceoffset.x, backgroundsurfaceoffset.y); SDL_Rect src; src.x = p.x; src.y = p.y; src.w = 2 * VIEW_W; src.h = 2 * VIEW_H; SDL_BlitSurface(backgroundsurface, &src, screen , 0); } renderIsoBackObjects(r_dead); renderIsoFrontObjects(r); for (unsigned i = index_objectlayer + 1; i < layers.size(); ++i) renderIsoLayer(screen, nulloffset, layers[i]); checkTooltip(); } void MapRenderer::renderOrthoLayer(const unsigned short layerdata[256][256]) { const Point upperleft = floor(screen_to_map(0, 0, shakycam.x, shakycam.y)); short int startj = max(0, upperleft.y); short int starti = max(0, upperleft.x); const short max_tiles_width = min(w, static_cast<short int>(starti + (VIEW_W / TILE_W) + 2 * tset.max_size_x)); const short max_tiles_height = min(h, static_cast<short int>(startj + (VIEW_H / TILE_H) + 2 * tset.max_size_y)); short int i; short int j; for (j = startj; j < max_tiles_height; j++) { Point p = map_to_screen(starti, j, shakycam.x, shakycam.y); p = center_tile(p); for (i = starti; i < max_tiles_width; i++) { if (const unsigned short current_tile = layerdata[i][j]) { SDL_Rect dest; dest.x = p.x - tset.tiles[current_tile].offset.x; dest.y = p.y - tset.tiles[current_tile].offset.y; SDL_BlitSurface(tset.sprites, &(tset.tiles[current_tile].src), screen, &dest); } p.x += TILE_W; } } } void MapRenderer::renderOrthoBackObjects(std::vector<Renderable> &r) { // some renderables are drawn above the background and below the objects vector<Renderable>::iterator it; for (it = r.begin(); it != r.end(); ++it) drawRenderable(it); } void MapRenderer::renderOrthoFrontObjects(std::vector<Renderable> &r) { short int i; short int j; SDL_Rect dest; vector<Renderable>::iterator r_cursor = r.begin(); vector<Renderable>::iterator r_end = r.end(); const Point upperleft = floor(screen_to_map(0, 0, shakycam.x, shakycam.y)); short int startj = max(0, upperleft.y); short int starti = max(0, upperleft.x); const short max_tiles_width = min(w, static_cast<short int>(starti + (VIEW_W / TILE_W) + 2 * tset.max_size_x)); const short max_tiles_height = min(h, static_cast<short int>(startj + (VIEW_H / TILE_H) + 2 * tset.max_size_y)); while (r_cursor != r_end && (int)(r_cursor->map_pos.y) < startj) ++r_cursor; if (index_objectlayer >= layers.size()) return; maprow *objectlayer = layers[index_objectlayer]; for (j = startj; j < max_tiles_height; j++) { Point p = map_to_screen(starti, j, shakycam.x, shakycam.y); p = center_tile(p); for (i = starti; i<max_tiles_width; i++) { if (const unsigned short current_tile = objectlayer[i][j]) { dest.x = p.x - tset.tiles[current_tile].offset.x; dest.y = p.y - tset.tiles[current_tile].offset.y; SDL_BlitSurface(tset.sprites, &(tset.tiles[current_tile].src), screen, &dest); } p.x += TILE_W; while (r_cursor != r_end && (int)(r_cursor->map_pos.y) == j && (int)(r_cursor->map_pos.x) < i) // implicit floor ++r_cursor; // some renderable entities go in this layer while (r_cursor != r_end && (int)(r_cursor->map_pos.y) == j && (int)(r_cursor->map_pos.x) == i) // implicit floor drawRenderable(r_cursor++); } while (r_cursor != r_end && (int)(r_cursor->map_pos.y) <= j) // implicit floor ++r_cursor; } } void MapRenderer::renderOrtho(vector<Renderable> &r, vector<Renderable> &r_dead) { unsigned index = 0; while (index < index_objectlayer) renderOrthoLayer(layers[index++]); renderOrthoBackObjects(r_dead); renderOrthoFrontObjects(r); index++; while (index < layers.size()) renderOrthoLayer(layers[index++]); //render event tooltips checkTooltip(); } void MapRenderer::executeOnLoadEvents() { vector<Event>::iterator it; // loop in reverse because we may erase elements for (it = events.end(); it != events.begin(); ) { --it; // skip inactive events if (!EventManager::isActive(*it)) continue; if ((*it).type == "on_load") { if (EventManager::executeEvent(*it)) it = events.erase(it); } } } void MapRenderer::executeOnMapExitEvents() { vector<Event>::iterator it; // We're leaving the map, so the events of this map are removed anyway in // the next frame (Reminder: We're about to load a new map ;), // so we will ignore the events keep_after_trigger value and do not delete // any event in this loop for (it = events.begin(); it != events.end(); ++it) { // skip inactive events if (!EventManager::isActive(*it)) continue; if ((*it).type == "on_mapexit") EventManager::executeEvent(*it); // ignore repeat value } } void MapRenderer::checkEvents(FPoint loc) { Point maploc; maploc.x = (int)floor(loc.x); maploc.y = (int)floor(loc.y); vector<Event>::iterator it; // loop in reverse because we may erase elements for (it = events.end(); it != events.begin(); ) { --it; // skip inactive events if (!EventManager::isActive(*it)) continue; if ((*it).type == "on_clear") { if (enemies_cleared && EventManager::executeEvent(*it)) it = events.erase(it); continue; } bool inside = maploc.x >= (*it).location.x && maploc.y >= (*it).location.y && maploc.x <= (*it).location.x + (*it).location.w-1 && maploc.y <= (*it).location.y + (*it).location.h-1; if ((*it).type == "on_leave") { if (inside) { if (!(*it).getComponent("wasInsideEventArea")) { (*it).components.push_back(Event_Component()); (*it).components.back().type = string("wasInsideEventArea"); } } else { if ((*it).getComponent("wasInsideEventArea")) { (*it).deleteAllComponents("wasInsideEventArea"); if (EventManager::executeEvent(*it)) it = events.erase(it); } } } else { if (inside) if (EventManager::executeEvent(*it)) it = events.erase(it); } } } /** * Some events have a hotspot (rectangle screen area) where the user can click * to trigger the event. * * The hero must be within range (INTERACT_RANGE) to activate an event. * * This function checks valid mouse clicks against all clickable events, and * executes */ void MapRenderer::checkHotspots() { if (NO_MOUSE) return; show_tooltip = false; vector<Event>::iterator it; // work backwards through events because events can be erased in the loop. // this prevents the iterator from becoming invalid. for (it = events.end(); it != events.begin(); ) { --it; for (int x=it->hotspot.x; x < it->hotspot.x + it->hotspot.w; ++x) { for (int y=it->hotspot.y; y < it->hotspot.y + it->hotspot.h; ++y) { bool matched = false; for (unsigned index = 0; index <= index_objectlayer; ++index) { maprow *current_layer = layers[index]; Point p = map_to_screen(x, y, shakycam.x, shakycam.y); p = center_tile(p); if (const short current_tile = current_layer[x][y]) { // first check if mouse pointer is in rectangle of that tile: SDL_Rect dest; dest.x = p.x - tset.tiles[current_tile].offset.x; dest.y = p.y - tset.tiles[current_tile].offset.y; dest.w = tset.tiles[current_tile].src.w; dest.h = tset.tiles[current_tile].src.h; if (isWithin(dest, inpt->mouse)) { // Now that the mouse is within the rectangle of the tile, we can check for // pixel precision. We need to have checked the rectangle first, because // otherwise the pixel precise check might hit a neighbouring tile in the // tileset. We need to calculate the point relative to the Point p1; p1.x = inpt->mouse.x - dest.x + tset.tiles[current_tile].src.x; p1.y = inpt->mouse.y - dest.y + tset.tiles[current_tile].src.y; matched |= checkPixel(p1, tset.sprites); tip_pos.x = dest.x + dest.w/2; tip_pos.y = dest.y; } } } if (matched) { // skip inactive events if (!EventManager::isActive(*it)) continue; // skip events without hotspots if ((*it).hotspot.h == 0) continue; // skip events on cooldown if ((*it).cooldown_ticks != 0) continue; // new tooltip? createTooltip((*it).getComponent("tooltip")); if ((((*it).reachable_from.w == 0 && (*it).reachable_from.h == 0) || isWithin((*it).reachable_from, floor(cam))) && calcDist(cam, (*it).center) < INTERACT_RANGE) { // only check events if the player is clicking // and allowed to click if (!inpt->pressing[MAIN1]) return; else if (inpt->lock[MAIN1]) return; inpt->lock[MAIN1] = true; if (EventManager::executeEvent(*it)) it = events.erase(it); } return; } else show_tooltip = false; } } } } void MapRenderer::checkNearestEvent() { if (NO_MOUSE) show_tooltip = false; vector<Event>::iterator it; vector<Event>::iterator nearest = events.end(); float best_distance = std::numeric_limits<float>::max(); // loop in reverse because we may erase elements for (it = events.end(); it != events.begin(); ) { --it; // skip inactive events if (!EventManager::isActive(*it)) continue; // skip events without hotspots if ((*it).hotspot.h == 0) continue; // skip events on cooldown if ((*it).cooldown_ticks != 0) continue; float distance = calcDist(cam, (*it).center); if ((((*it).reachable_from.w == 0 && (*it).reachable_from.h == 0) || isWithin((*it).reachable_from, floor(cam))) && distance < INTERACT_RANGE && distance < best_distance) { best_distance = distance; nearest = it; } } if (nearest != events.end()) { if (NO_MOUSE) { // new tooltip? createTooltip((*nearest).getComponent("tooltip")); tip_pos = map_to_screen((*nearest).center.x, (*nearest).center.y, shakycam.x, shakycam.y); tip_pos.y -= TILE_H; } if (inpt->pressing[ACCEPT] && !inpt->lock[ACCEPT]) { if (inpt->pressing[ACCEPT]) inpt->lock[ACCEPT] = true; if(EventManager::executeEvent(*nearest)) events.erase(nearest); } } } void MapRenderer::checkTooltip() { if (show_tooltip) tip->render(tip_buf, tip_pos, STYLE_TOPLABEL); } void MapRenderer::createTooltip(Event_Component *ec) { if (ec && !ec->s.empty() && TOOLTIP_CONTEXT != TOOLTIP_MENU) { show_tooltip = true; if (!tip_buf.compareFirstLine(ec->s)) { tip_buf.clear(); tip_buf.addText(ec->s); } TOOLTIP_CONTEXT = TOOLTIP_MAP; } else if (TOOLTIP_CONTEXT != TOOLTIP_MENU) { TOOLTIP_CONTEXT = TOOLTIP_NONE; } } MapRenderer::~MapRenderer() { if (music != NULL) { Mix_HaltMusic(); Mix_FreeMusic(music); } tip_buf.clear(); clearLayers(); clearEvents(); clearQueues(); delete tip; /* unload sounds */ snd->reset(); while (!sids.empty()) { snd->unload(sids.back()); sids.pop_back(); } } ���������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MapRenderer.h�����������������������������������������������������������������0000664�0000000�0000000�00000011150�12247171015�0017141�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MapRenderer * * Map data structure and rendering * This class is capable of rendering isometric and orthogonal maps. */ #pragma once #ifndef MAP_RENDERER_H #define MAP_RENDERER_H #include "CommonIncludes.h" #include "GameStatePlay.h" #include "Map.h" #include "MapCollision.h" #include "Settings.h" #include "TileSet.h" #include "Utils.h" #include "StatBlock.h" #include "TooltipData.h" #include <queue> class FileParser; class WidgetTooltip; // TODO: Move these Map_* classes to its own file. class MapRenderer : public Map { private: Mix_Music *music; WidgetTooltip *tip; TooltipData tip_buf; Point tip_pos; bool show_tooltip; bool enemyGroupPlaceEnemy(float x, float y, Map_Group &g); void pushEnemyGroup(Map_Group g); std::string played_music_filename; void clearQueues(); // When the animated tiles are switched off, the background is // not rendered all the time but everytime you have moved away too much. // then the background is completely rendered, else it is just blit // onto screen. units in tiles: static const short movedistance_to_rerender = 4; // some events are automatically triggered when the map is loaded void executeOnLoadEvents(); void drawRenderable(std::vector<Renderable>::iterator r_cursor); // renders one layer into the given sdl surface with offset // offset in screen/surface coordinates. void renderIsoLayer(SDL_Surface *wheretorender, Point offset, const unsigned short layerdata[][256]); // renders only objects void renderIsoBackObjects(std::vector<Renderable> &r); // renders interleaved objects and layer void renderIsoFrontObjects(std::vector<Renderable> &r); void renderIso(std::vector<Renderable> &r, std::vector<Renderable> &r_dead); void renderOrthoLayer(const unsigned short layerdata[][256]); void renderOrthoBackObjects(std::vector<Renderable> &r); void renderOrthoFrontObjects(std::vector<Renderable> &r); void renderOrtho(std::vector<Renderable> &r, std::vector<Renderable> &r_dead); void clearLayers(); void createTooltip(Event_Component *ec); FPoint shakycam; TileSet tset; // in case of animated tiles switched off, prerender background into this layer SDL_Surface* backgroundsurface; // only called if the background surface is actually used, i.e. ANIMATED_TILES = false; void createBackgroundSurface(); // point where the backgroundsurface was rendered. same coordinates as shakycam FPoint backgroundsurfaceoffset; public: // functions MapRenderer(); ~MapRenderer(); MapRenderer(const MapRenderer ©); // not implemented int load(std::string filename); void logic(); void render(std::vector<Renderable> &r, std::vector<Renderable> &r_dead); void checkEvents(FPoint loc); void checkHotspots(); void checkNearestEvent(); void checkTooltip(); // some events are triggered on exiting the map void executeOnMapExitEvents(); // cam(x,y) is where on the map the camera is pointing FPoint cam; // indicates that the map was changed by an event, so the GameStatePlay // will tell the mini map to update. bool map_change; MapCollision collider; // event-created loot or items std::vector<Event_Component> loot; // teleport handling bool teleportation; FPoint teleport_destination; std::string teleport_mapname; std::string respawn_map; FPoint respawn_point; // cutscene handling bool cutscene; std::string cutscene_file; // message handling std::string log_msg; // shaky cam int shaky_cam_ticks; // stash handling bool stash; FPoint stash_pos; // enemy clear bool enemies_cleared; // event talker std::string event_npc; // map soundids std::vector<SoundManager::SoundID> sids; void loadMusic(); // force a rendering of the background in the next render step. bool repaint_background; /** * The index of the layer, which mixes with the objects on screen. Layers * before that are painted below objects; Layers after are painted on top. */ unsigned index_objectlayer; }; #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/Menu.cpp����������������������������������������������������������������������0000664�0000000�0000000�00000003731�12247171015�0016202�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 kitano Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class Menu * * The base class for Menu objects */ #include "Menu.h" #include "Settings.h" Menu::Menu() : background(NULL) , visible(false) , sfx_open(0) , sfx_close(0) { } Menu::~Menu() { } void Menu::align() { SDL_Rect temp = window_area; if (alignment == "topleft") { window_area.x = 0+temp.x; window_area.y = 0+temp.y; } else if (alignment == "top") { window_area.x = (VIEW_W_HALF-temp.w/2)+temp.x; window_area.y = 0+temp.y; } else if (alignment == "topright") { window_area.x = (VIEW_W-temp.w)+temp.x; window_area.y = 0+temp.y; } else if (alignment == "left") { window_area.x = 0+temp.x; window_area.y = (VIEW_H_HALF-temp.h/2)+temp.y; } else if (alignment == "center") { window_area.x = (VIEW_W_HALF-temp.w/2)+temp.x; window_area.y = (VIEW_H_HALF-temp.h/2)+temp.y; } else if (alignment == "right") { window_area.x = (VIEW_W-temp.w)+temp.x; window_area.y = (VIEW_H_HALF-temp.h/2)+temp.y; } else if (alignment == "bottomleft") { window_area.x = 0+temp.x; window_area.y = (VIEW_H-temp.h)+temp.y; } else if (alignment == "bottom") { window_area.x = (VIEW_W_HALF-temp.w/2)+temp.x; window_area.y = (VIEW_H-temp.h)+temp.y; } else if (alignment == "bottomright") { window_area.x = (VIEW_W-temp.w)+temp.x; window_area.y = (VIEW_H-temp.h)+temp.y; } } ���������������������������������������flare-engine-0.19/src/Menu.h������������������������������������������������������������������������0000664�0000000�0000000�00000002154�12247171015�0015645�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 kitano Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class Menu * * The base class for Menu objects */ #pragma once #ifndef MENU_H #define MENU_H #include "CommonIncludes.h" #include "SoundManager.h" class Menu { protected: SDL_Surface *background; public: Menu(); virtual ~Menu(); bool visible; SDL_Rect window_area; std::string alignment; virtual void align(); virtual void render() = 0; SoundManager::SoundID sfx_open; SoundManager::SoundID sfx_close; }; #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuActionBar.cpp�������������������������������������������������������������0000664�0000000�0000000�00000043737�12247171015�0017777�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuActionBar * * Handles the config, display, and usage of the 0-9 hotkeys, mouse buttons, and menu calls */ #include "CommonIncludes.h" #include "FileParser.h" #include "Menu.h" #include "MenuActionBar.h" #include "SharedResources.h" #include "Settings.h" #include "StatBlock.h" #include "TooltipData.h" #include "UtilsParsing.h" #include "WidgetSlot.h" #include "WidgetLabel.h" #include "SharedGameResources.h" #include <climits> using namespace std; MenuActionBar::MenuActionBar(Avatar *_hero, SDL_Surface *_icons) { hero = _hero; icons = _icons; src.x = 0; src.y = 0; src.w = ICON_SIZE; src.h = ICON_SIZE; drag_prev_slot = -1; last_mouse.x = 0; last_mouse.y = 0; clear(); for (unsigned int i=0; i<16; i++) { labels[i] = new WidgetLabel(); } loadGraphics(); tablist = TabList(HORIZONTAL, ACTIONBAR_BACK, ACTIONBAR_FORWARD, ACTIONBAR); for (unsigned int i=0; i<12; i++) { slots[i] = new WidgetSlot(icons, -1, ACTIONBAR); slots[i]->continuous = true; tablist.add(slots[i]); } for (unsigned int i=0; i<4; i++) { menus[i] = new WidgetSlot(icons, -1, ACTIONBAR); tablist.add(menus[i]); } } void MenuActionBar::update() { // Read data from config file FileParser infile; if (infile.open("menus/actionbar.txt")) { while (infile.next()) { infile.val = infile.val + ','; if (infile.key == "slot1") { slots[0]->pos.x = window_area.x+eatFirstInt(infile.val, ','); slots[0]->pos.y = window_area.y+eatFirstInt(infile.val, ','); slots[0]->pos.w = eatFirstInt(infile.val, ','); slots[0]->pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot2") { slots[1]->pos.x = window_area.x+eatFirstInt(infile.val, ','); slots[1]->pos.y = window_area.y+eatFirstInt(infile.val, ','); slots[1]->pos.w = eatFirstInt(infile.val, ','); slots[1]->pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot3") { slots[2]->pos.x = window_area.x+eatFirstInt(infile.val, ','); slots[2]->pos.y = window_area.y+eatFirstInt(infile.val, ','); slots[2]->pos.w = eatFirstInt(infile.val, ','); slots[2]->pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot4") { slots[3]->pos.x = window_area.x+eatFirstInt(infile.val, ','); slots[3]->pos.y = window_area.y+eatFirstInt(infile.val, ','); slots[3]->pos.w = eatFirstInt(infile.val, ','); slots[3]->pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot5") { slots[4]->pos.x = window_area.x+eatFirstInt(infile.val, ','); slots[4]->pos.y = window_area.y+eatFirstInt(infile.val, ','); slots[4]->pos.w = eatFirstInt(infile.val, ','); slots[4]->pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot6") { slots[5]->pos.x = window_area.x+eatFirstInt(infile.val, ','); slots[5]->pos.y = window_area.y+eatFirstInt(infile.val, ','); slots[5]->pos.w = eatFirstInt(infile.val, ','); slots[5]->pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot7") { slots[6]->pos.x = window_area.x+eatFirstInt(infile.val, ','); slots[6]->pos.y = window_area.y+eatFirstInt(infile.val, ','); slots[6]->pos.w = eatFirstInt(infile.val, ','); slots[6]->pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot8") { slots[7]->pos.x = window_area.x+eatFirstInt(infile.val, ','); slots[7]->pos.y = window_area.y+eatFirstInt(infile.val, ','); slots[7]->pos.w = eatFirstInt(infile.val, ','); slots[7]->pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot9") { slots[8]->pos.x = window_area.x+eatFirstInt(infile.val, ','); slots[8]->pos.y = window_area.y+eatFirstInt(infile.val, ','); slots[8]->pos.w = eatFirstInt(infile.val, ','); slots[8]->pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot10") { slots[9]->pos.x = window_area.x+eatFirstInt(infile.val, ','); slots[9]->pos.y = window_area.y+eatFirstInt(infile.val, ','); slots[9]->pos.w = eatFirstInt(infile.val, ','); slots[9]->pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot_M1") { slots[10]->pos.x = window_area.x+eatFirstInt(infile.val, ','); slots[10]->pos.y = window_area.y+eatFirstInt(infile.val, ','); slots[10]->pos.w = eatFirstInt(infile.val, ','); slots[10]->pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot_M2") { slots[11]->pos.x = window_area.x+eatFirstInt(infile.val, ','); slots[11]->pos.y = window_area.y+eatFirstInt(infile.val, ','); slots[11]->pos.w = eatFirstInt(infile.val, ','); slots[11]->pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "char_menu") { menus[MENU_CHARACTER]->pos.x = window_area.x+eatFirstInt(infile.val, ','); menus[MENU_CHARACTER]->pos.y = window_area.y+eatFirstInt(infile.val, ','); menus[MENU_CHARACTER]->pos.w = eatFirstInt(infile.val, ','); menus[MENU_CHARACTER]->pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "inv_menu") { menus[MENU_INVENTORY]->pos.x = window_area.x+eatFirstInt(infile.val, ','); menus[MENU_INVENTORY]->pos.y = window_area.y+eatFirstInt(infile.val, ','); menus[MENU_INVENTORY]->pos.w = eatFirstInt(infile.val, ','); menus[MENU_INVENTORY]->pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "powers_menu") { menus[MENU_POWERS]->pos.x = window_area.x+eatFirstInt(infile.val, ','); menus[MENU_POWERS]->pos.y = window_area.y+eatFirstInt(infile.val, ','); menus[MENU_POWERS]->pos.w = eatFirstInt(infile.val, ','); menus[MENU_POWERS]->pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "log_menu") { menus[MENU_LOG]->pos.x = window_area.x+eatFirstInt(infile.val, ','); menus[MENU_LOG]->pos.y = window_area.y+eatFirstInt(infile.val, ','); menus[MENU_LOG]->pos.w = eatFirstInt(infile.val, ','); menus[MENU_LOG]->pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "numberArea") { numberArea.x = window_area.x+eatFirstInt(infile.val, ','); numberArea.w = eatFirstInt(infile.val, ','); numberArea.h = eatFirstInt(infile.val, ','); } else if (infile.key == "mouseArea") { mouseArea.x = window_area.x+eatFirstInt(infile.val, ','); mouseArea.w = eatFirstInt(infile.val, ','); mouseArea.h = eatFirstInt(infile.val, ','); } else if (infile.key == "menuArea") { menuArea.x = window_area.x+eatFirstInt(infile.val, ','); menuArea.w = eatFirstInt(infile.val, ','); menuArea.h = eatFirstInt(infile.val, ','); } } infile.close(); } // screen areas occupied by the three main sections numberArea.y = mouseArea.y = menuArea.y = window_area.y; // set keybinding labels for (unsigned int i=0; i<10; i++) { if (inpt->binding[i+6] < 8) labels[i]->set(slots[i]->pos.x+slots[i]->pos.w, slots[i]->pos.y+slots[i]->pos.h-font->getFontHeight(), JUSTIFY_RIGHT, VALIGN_TOP, inpt->mouse_button[inpt->binding[i+6]-1], font->getColor("menu_normal")); else labels[i]->set(slots[i]->pos.x+slots[i]->pos.w, slots[i]->pos.y+slots[i]->pos.h-font->getFontHeight(), JUSTIFY_RIGHT, VALIGN_TOP, SDL_GetKeyName((SDLKey)inpt->binding[i+6]), font->getColor("menu_normal")); } for (unsigned int i=0; i<2; i++) { if (inpt->binding[i+20] < 8) labels[i+10]->set(slots[i+10]->pos.x+slots[i+10]->pos.w, slots[i+10]->pos.y+slots[i+10]->pos.h-font->getFontHeight(), JUSTIFY_RIGHT, VALIGN_TOP, inpt->mouse_button[inpt->binding[i+20]-1], font->getColor("menu_normal")); else labels[i+10]->set(slots[i+10]->pos.x+slots[i+10]->pos.w, slots[i+10]->pos.y+slots[i+10]->pos.h-font->getFontHeight(), JUSTIFY_RIGHT, VALIGN_TOP, SDL_GetKeyName((SDLKey)inpt->binding[i+20]), font->getColor("menu_normal")); } for (unsigned int i=0; i<4; i++) { if (inpt->binding[i+16] < 8) labels[i+12]->set(menus[i]->pos.x+menus[i]->pos.w, menus[i]->pos.y+menus[i]->pos.h-font->getFontHeight(), JUSTIFY_RIGHT, VALIGN_TOP, inpt->mouse_button[inpt->binding[i+16]-1], font->getColor("menu_normal")); else labels[i+12]->set(menus[i]->pos.x+menus[i]->pos.w, menus[i]->pos.y+menus[i]->pos.h-font->getFontHeight(), JUSTIFY_RIGHT, VALIGN_TOP, SDL_GetKeyName((SDLKey)inpt->binding[i+16]), font->getColor("menu_normal")); } } void MenuActionBar::clear() { // clear action bar for (int i=0; i<12; i++) { hotkeys[i] = 0; actionbar[i] = 0; slot_item_count[i] = -1; slot_enabled[i] = true; locked[i] = false; } // clear menu notifications for (int i=0; i<4; i++) requires_attention[i] = false; } void MenuActionBar::loadGraphics() { emptyslot = loadGraphicSurface("images/menus/slot_empty.png"); background = loadGraphicSurface("images/menus/actionbar_trim.png"); disabled = loadGraphicSurface("images/menus/disabled.png"); attention = loadGraphicSurface("images/menus/attention_glow.png"); } // Renders the "needs attention" icon over the appropriate log menu void MenuActionBar::renderAttention(int menu_id) { SDL_Rect dest; // x-value is 12 hotkeys and 4 empty slots over dest.x = window_area.x + (menu_id * ICON_SIZE) + ICON_SIZE*15; dest.y = window_area.y+3; dest.w = dest.h = ICON_SIZE; SDL_BlitSurface(attention, NULL, screen, &dest); // put an asterisk on this icon if in colorblind mode if (COLORBLIND) { WidgetLabel label; label.set(dest.x + 2, dest.y + 2, JUSTIFY_LEFT, VALIGN_TOP, "*", font->getColor("menu_normal")); label.render(); } } void MenuActionBar::logic() { if (NO_MOUSE) { tablist.logic(); } } void MenuActionBar::render() { SDL_Rect dest; SDL_Rect trimsrc; dest = window_area; trimsrc.x = 0; trimsrc.y = 0; trimsrc.w = window_area.w; trimsrc.h = window_area.h; SDL_BlitSurface(background, &trimsrc, screen, &dest); // draw hotkeyed icons src.x = src.y = 0; src.w = src.h = ICON_SIZE; for (int i=0; i<12; i++) { if (hotkeys[i] != 0) { const Power &power = powers->getPower(hotkeys[i]); slot_enabled[i] = (hero->hero_cooldown[hotkeys[i]] == 0) && (slot_item_count[i] != 0) && !hero->stats.effects.stun && hero->stats.alive && hero->stats.canUsePower(power, hotkeys[i]); //see if the slot should be greyed out unsigned icon_offset = 0;/* !slot_enabled[i] ? ICON_DISABLED_OFFSET : (hero->activated_powerslot == i ? ICON_HIGHLIGHT_OFFSET : 0); */ slots[i]->setIcon(power.icon + icon_offset); if (slot_item_count[i] > -1) { slots[i]->setAmount(slot_item_count[i]); } else { slots[i]->setAmount(0,0); } slots[i]->render(); } else { dest.x = slots[i]->pos.x; dest.y = slots[i]->pos.y; dest.h = dest.w = ICON_SIZE; SDL_BlitSurface(emptyslot, &src, screen, &dest); slots[i]->renderSelection(); } } for (int i=0; i<4; i++) menus[i]->render(); renderCooldowns(); // render log attention notifications for (int i=0; i<4; i++) if (requires_attention[i]) renderAttention(i); // draw hotkey labels if (SHOW_HOTKEYS) { for (int i=0; i<16; i++) { labels[i]->render(); } } } /** * Display a notification for any power on cooldown * Also displays disabled powers */ void MenuActionBar::renderCooldowns() { SDL_Rect item_src; SDL_Rect item_dest; for (int i=0; i<12; i++) { if (!slot_enabled[i]) { item_src.x = 0; item_src.y = 0; item_src.h = ICON_SIZE; item_src.w = ICON_SIZE; // Wipe from bottom to top if (hero->hero_cooldown[hotkeys[i]] && powers->powers[hotkeys[i]].cooldown) { item_src.h = (ICON_SIZE * hero->hero_cooldown[hotkeys[i]]) / powers->powers[hotkeys[i]].cooldown; } // SDL_BlitSurface will write to these Rects, so make a copy item_dest.x = slots[i]->pos.x; item_dest.y = slots[i]->pos.y; item_dest.w = slots[i]->pos.w; item_dest.h = slots[i]->pos.h; SDL_BlitSurface(disabled, &item_src, screen, &item_dest); slots[i]->renderSelection(); } } } /** * On mouseover, show tooltip for buttons */ TooltipData MenuActionBar::checkTooltip(Point mouse) { TooltipData tip; if (isWithin(menus[MENU_CHARACTER]->pos, mouse)) { if (COLORBLIND && requires_attention[MENU_CHARACTER]) tip.addText(msg->get("Character") + " (*)"); else tip.addText(msg->get("Character")); return tip; } if (isWithin(menus[MENU_INVENTORY]->pos, mouse)) { if (COLORBLIND && requires_attention[MENU_INVENTORY]) tip.addText(msg->get("Inventory") + " (*)"); else tip.addText(msg->get("Inventory")); return tip; } if (isWithin(menus[MENU_POWERS]->pos, mouse)) { if (COLORBLIND && requires_attention[MENU_POWERS]) tip.addText(msg->get("Powers") + " (*)"); else tip.addText(msg->get("Powers")); return tip; } if (isWithin(menus[MENU_LOG]->pos, mouse)) { if (COLORBLIND && requires_attention[MENU_LOG]) tip.addText(msg->get("Log") + " (*)"); else tip.addText(msg->get("Log")); return tip; } for (int i=0; i<12; i++) { if (hotkeys[i] != 0) { if (isWithin(slots[i]->pos, mouse)) { tip.addText(powers->powers[hotkeys[i]].name); } } } return tip; } /** * After dragging a power or item onto the action bar, set as new hotkey */ void MenuActionBar::drop(Point mouse, int power_index, bool rearranging) { for (int i=0; i<12; i++) { if (isWithin(slots[i]->pos, mouse)) { if (rearranging) { if ((locked[i] && !locked[drag_prev_slot]) || (!locked[i] && locked[drag_prev_slot])) { locked[i] = !locked[i]; locked[drag_prev_slot] = !locked[drag_prev_slot]; } hotkeys[drag_prev_slot] = hotkeys[i]; } else if (locked[i]) return; hotkeys[i] = power_index; return; } } } /** * Return the power to the last clicked on slot */ void MenuActionBar::actionReturn(int power_index) { drop(last_mouse, power_index, 0); } /** * CTRL-click a hotkey to clear it */ void MenuActionBar::remove(Point mouse) { for (int i=0; i<12; i++) { if (isWithin(slots[i]->pos, mouse)) { if (locked[i]) return; hotkeys[i] = 0; return; } } } /** * If pressing an action key (keyboard or mouseclick) and the power is enabled, * return that power's ID. */ int MenuActionBar::checkAction() { int current = tablist.getCurrent(); // check click and hotkey actions if ((inpt->pressing[BAR_1] || (inpt->pressing[ACTIONBAR_USE] && current == 0) || (!NO_MOUSE && slots[0]->checkClick() == ACTIVATED)) && slot_enabled[0]) return hotkeys[0]; if ((inpt->pressing[BAR_2] || (inpt->pressing[ACTIONBAR_USE] && current == 1) || (!NO_MOUSE && slots[1]->checkClick() == ACTIVATED)) && slot_enabled[1]) return hotkeys[1]; if ((inpt->pressing[BAR_3] || (inpt->pressing[ACTIONBAR_USE] && current == 2) || (!NO_MOUSE && slots[2]->checkClick() == ACTIVATED)) && slot_enabled[2]) return hotkeys[2]; if ((inpt->pressing[BAR_4] || (inpt->pressing[ACTIONBAR_USE] && current == 3) || (!NO_MOUSE && slots[3]->checkClick() == ACTIVATED)) && slot_enabled[3]) return hotkeys[3]; if ((inpt->pressing[BAR_5] || (inpt->pressing[ACTIONBAR_USE] && current == 4) || (!NO_MOUSE && slots[4]->checkClick() == ACTIVATED)) && slot_enabled[4]) return hotkeys[4]; if ((inpt->pressing[BAR_6] || (inpt->pressing[ACTIONBAR_USE] && current == 5) || (!NO_MOUSE && slots[5]->checkClick() == ACTIVATED)) && slot_enabled[5]) return hotkeys[5]; if ((inpt->pressing[BAR_7] || (inpt->pressing[ACTIONBAR_USE] && current == 6) || (!NO_MOUSE && slots[6]->checkClick() == ACTIVATED)) && slot_enabled[6]) return hotkeys[6]; if ((inpt->pressing[BAR_8] || (inpt->pressing[ACTIONBAR_USE] && current == 7) || (!NO_MOUSE && slots[7]->checkClick() == ACTIVATED)) && slot_enabled[7]) return hotkeys[7]; if ((inpt->pressing[BAR_9] || (inpt->pressing[ACTIONBAR_USE] && current == 8) || (!NO_MOUSE && slots[8]->checkClick() == ACTIVATED)) && slot_enabled[8]) return hotkeys[8]; if ((inpt->pressing[BAR_0] || (inpt->pressing[ACTIONBAR_USE] && current == 9) || (!NO_MOUSE && slots[9]->checkClick() == ACTIVATED)) && slot_enabled[9]) return hotkeys[9]; if ((inpt->pressing[MAIN1] || (inpt->pressing[ACTIONBAR_USE] && current == 10) || (!NO_MOUSE && slots[10]->checkClick() == ACTIVATED)) && slot_enabled[10] && !inpt->lock[MAIN1]) return hotkeys[10]; if ((inpt->pressing[MAIN2] || (inpt->pressing[ACTIONBAR_USE] && current == 11) || (!NO_MOUSE && slots[11]->checkClick() == ACTIVATED)) && slot_enabled[11] && !inpt->lock[MAIN2]) return hotkeys[11]; return 0; } /** * If clicking while a menu is open, assume the player wants to rearrange the action bar */ int MenuActionBar::checkDrag(Point mouse) { int power_index; for (int i=0; i<12; i++) { if (isWithin(slots[i]->pos, mouse)) { drag_prev_slot = i; power_index = hotkeys[i]; hotkeys[i] = 0; last_mouse = mouse; return power_index; } } return 0; } /** * if clicking a menu, act as if the player pressed that menu's hotkey */ void MenuActionBar::checkMenu(bool &menu_c, bool &menu_i, bool &menu_p, bool &menu_l) { if (menus[MENU_CHARACTER]->checkClick()) { menu_c = true; } else if (menus[MENU_INVENTORY]->checkClick()) { menu_i = true; } else if (menus[MENU_POWERS]->checkClick()) { menu_p = true; } else if (menus[MENU_LOG]->checkClick()) { menu_l = true; } } /** * Set all hotkeys at once e.g. when loading a game */ void MenuActionBar::set(int power_id[12]) { for (int i=0; i<12; i++) hotkeys[i] = power_id[i]; } void MenuActionBar::resetSlots() { for (int i=0; i<12; i++) { slots[i]->checked = false; slots[i]->pressed = false; } } MenuActionBar::~MenuActionBar() { SDL_FreeSurface(emptyslot); SDL_FreeSurface(background); SDL_FreeSurface(disabled); SDL_FreeSurface(attention); for (unsigned i = 0; i < 16; i++) delete labels[i]; for (unsigned i = 0; i < 12; i++) delete slots[i]; for (unsigned int i=0; i<4; i++) delete menus[i]; } ���������������������������������flare-engine-0.19/src/MenuActionBar.h���������������������������������������������������������������0000664�0000000�0000000�00000005067�12247171015�0017436�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class ActionBar * * Handles the config, display, and usage of the 0-9 hotkeys, mouse buttons, and menu calls */ #pragma once #ifndef MENU_ACTION_BAR_H #define MENU_ACTION_BAR_H #include "CommonIncludes.h" #include "Avatar.h" #include "Menu.h" #include "Utils.h" #include "WidgetLabel.h" class StatBlock; class TooltipData; class WidgetLabel; class WidgetSlot; const int MENU_CHARACTER = 0; const int MENU_INVENTORY = 1; const int MENU_POWERS = 2; const int MENU_LOG = 3; class MenuActionBar : public Menu { private: void renderCooldowns(); SDL_Surface *emptyslot; SDL_Surface *icons; SDL_Surface *disabled; SDL_Surface *attention; Avatar *hero; SDL_Rect src; WidgetLabel *labels[16]; Point last_mouse; public: MenuActionBar(Avatar *hero, SDL_Surface *icons); ~MenuActionBar(); void loadGraphics(); void renderAttention(int menu_id); void logic(); void render(); int checkAction(); int checkDrag(Point mouse); void checkMenu(bool &menu_c, bool &menu_i, bool &menu_p, bool &menu_l); void drop(Point mouse, int power_index, bool rearranging); void actionReturn(int power_index); void remove(Point mouse); void set(int power_id[12]); void clear(); void update(); void resetSlots(); TooltipData checkTooltip(Point mouse); int hotkeys[12]; // refer to power_index in PowerManager int actionbar[12]; // temp for shapeshifting bool locked[12]; // if slot is locked, you cannot drop it WidgetSlot *slots[12]; // hotkey slots WidgetSlot *menus[4]; // menu buttons int slot_item_count[12]; // -1 means this power isn't item based. 0 means out of items. 1+ means sufficient items. bool slot_enabled[12]; bool requires_attention[4]; // these store the area occupied by these hotslot sections. // useful for detecting mouse interactions on those locations SDL_Rect numberArea; SDL_Rect mouseArea; SDL_Rect menuArea; int drag_prev_slot; TabList tablist; }; #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuActiveEffects.cpp���������������������������������������������������������0000664�0000000�0000000�00000006415�12247171015�0020640�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Justin Jacobs This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * MenuActiveEffects * * Handles the display of active effects (buffs/debuffs) */ #include "CommonIncludes.h" #include "FileParser.h" #include "MenuActiveEffects.h" #include "Menu.h" #include "ModManager.h" #include "Settings.h" #include "SharedResources.h" #include "StatBlock.h" #include "UtilsFileSystem.h" #include "UtilsParsing.h" using namespace std; MenuActiveEffects::MenuActiveEffects(SDL_Surface *_icons) { stats = NULL; icons = _icons; orientation = 0; // horizontal // Load config settings FileParser infile; if(infile.open("menus/activeeffects.txt")) { while(infile.next()) { infile.val = infile.val + ','; if(infile.key == "orientation") { int orient = eatFirstInt(infile.val,','); if (orient == 1) orientation = true; else orientation = false; } } infile.close(); } loadGraphics(); } void MenuActiveEffects::loadGraphics() { timer = loadGraphicSurface("images/menus/disabled.png"); } void MenuActiveEffects::renderIcon(int icon_id, int index, int current, int max) { if (icon_id > -1) { SDL_Rect pos,src,overlay; if (orientation == 0) { pos.x = window_area.x + (index * ICON_SIZE); pos.y = window_area.y; } else if (orientation == 1) { pos.x = window_area.x; pos.y = window_area.y + (index * ICON_SIZE); } int columns = icons->w / ICON_SIZE; src.x = (icon_id % columns) * ICON_SIZE; src.y = (icon_id / columns) * ICON_SIZE; src.w = src.h = ICON_SIZE; SDL_BlitSurface(icons,&src,screen,&pos); if (max > 0) { overlay.x = 0; overlay.y = (ICON_SIZE * current) / max; overlay.w = ICON_SIZE; overlay.h = ICON_SIZE - overlay.y; SDL_BlitSurface(timer,&overlay,screen,&pos); } } } void MenuActiveEffects::update(StatBlock *_stats) { stats = _stats; } void MenuActiveEffects::render() { int count=-1; // Step through the list of effects and render those that are active for (unsigned int i=0; i<stats->effects.effect_list.size(); i++) { std::string type = stats->effects.effect_list[i].type; int icon = stats->effects.effect_list[i].icon; int ticks = stats->effects.effect_list[i].ticks; int duration = stats->effects.effect_list[i].duration; int magnitude = stats->effects.effect_list[i].magnitude; int magnitude_max = stats->effects.effect_list[i].magnitude_max; if (icon >= 0) count++; if (type == "shield") renderIcon(icon,count,magnitude,magnitude_max); else if (type == "heal" || type == "block") renderIcon(icon,count,0,0); else if (ticks >= 0 && duration >= 0) renderIcon(icon,count,ticks,duration); } } MenuActiveEffects::~MenuActiveEffects() { SDL_FreeSurface(timer); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuActiveEffects.h�����������������������������������������������������������0000664�0000000�0000000�00000002416�12247171015�0020302�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Justin Jacobs This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * MenuActiveEffects * * Handles the display of active effects (buffs/debuffs) */ #pragma once #ifndef MENU_ACTIVE_EFFECTS_H #define MENU_ACTIVE_EFFECTS_H #include "CommonIncludes.h" #include "Menu.h" #include "Utils.h" class StatBlock; class MenuActiveEffects : public Menu { private: SDL_Surface *icons; SDL_Surface *timer; StatBlock *stats; bool orientation; void renderIcon(int icon_id, int index, int current, int max); public: MenuActiveEffects(SDL_Surface *_icons); ~MenuActiveEffects(); void loadGraphics(); void update(StatBlock *_stats); void render(); }; #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuCharacter.cpp�������������������������������������������������������������0000664�0000000�0000000�00000056522�12247171015�0020025�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuCharacter */ #include "FileParser.h" #include "Menu.h" #include "MenuCharacter.h" #include "SharedResources.h" #include "Settings.h" #include "StatBlock.h" #include "UtilsParsing.h" #include "WidgetButton.h" #include "WidgetListBox.h" using namespace std; MenuCharacter::MenuCharacter(StatBlock *_stats) { stats = _stats; skill_points = 0; visible = false; newPowerNotification = false; for (int i=0; i<CSTAT_COUNT; i++) { cstat[i].label = new WidgetLabel(); cstat[i].value = new WidgetLabel(); cstat[i].hover.x = cstat[i].hover.y = 0; cstat[i].hover.w = cstat[i].hover.h = 0; cstat[i].visible = true; } for (int i=0; i<STATLIST_COUNT; i++) { show_stat[i] = true; } statlist_rows = 10; statlist_scrollbar_offset = 0; closeButton = new WidgetButton("images/menus/buttons/button_x.png"); // Upgrade buttons for (int i=0; i<4; i++) { upgradeButton[i] = new WidgetButton("images/menus/buttons/upgrade.png"); upgradeButton[i]->enabled = false; show_upgrade[i] = true; } physical_up = false; mental_up = false; offense_up = false; defense_up = false; // menu title labelCharacter = new WidgetLabel(); // unspent points labelUnspent = new WidgetLabel(); // Load config settings FileParser infile; if (infile.open("menus/character.txt")) { while(infile.next()) { infile.val = infile.val + ','; if(infile.key == "close") { close_pos.x = eatFirstInt(infile.val,','); close_pos.y = eatFirstInt(infile.val,','); } else if(infile.key == "caption") { title = eatLabelInfo(infile.val); } else if(infile.key == "upgrade_physical") { upgrade_pos[0].x = eatFirstInt(infile.val,','); upgrade_pos[0].y = eatFirstInt(infile.val,','); } else if(infile.key == "upgrade_mental") { upgrade_pos[1].x = eatFirstInt(infile.val,','); upgrade_pos[1].y = eatFirstInt(infile.val,','); } else if(infile.key == "upgrade_offense") { upgrade_pos[2].x = eatFirstInt(infile.val,','); upgrade_pos[2].y = eatFirstInt(infile.val,','); } else if(infile.key == "upgrade_defense") { upgrade_pos[3].x = eatFirstInt(infile.val,','); upgrade_pos[3].y = eatFirstInt(infile.val,','); } else if(infile.key == "statlist") { statlist_pos.x = eatFirstInt(infile.val,','); statlist_pos.y = eatFirstInt(infile.val,','); } else if (infile.key == "statlist_rows") { statlist_rows = eatFirstInt(infile.val,','); } else if (infile.key == "statlist_scrollbar_offset") { statlist_scrollbar_offset = eatFirstInt(infile.val,','); } else if(infile.key == "label_name") { label_pos[0] = eatLabelInfo(infile.val); cstat[CSTAT_NAME].visible = !label_pos[0].hidden; } else if(infile.key == "label_level") { label_pos[1] = eatLabelInfo(infile.val); cstat[CSTAT_LEVEL].visible = !label_pos[1].hidden; } else if(infile.key == "label_physical") { label_pos[2] = eatLabelInfo(infile.val); cstat[CSTAT_PHYSICAL].visible = !label_pos[2].hidden; } else if(infile.key == "label_mental") { label_pos[3] = eatLabelInfo(infile.val); cstat[CSTAT_MENTAL].visible = !label_pos[3].hidden; } else if(infile.key == "label_offense") { label_pos[4] = eatLabelInfo(infile.val); cstat[CSTAT_OFFENSE].visible = !label_pos[4].hidden; } else if(infile.key == "label_defense") { label_pos[5] = eatLabelInfo(infile.val); cstat[CSTAT_DEFENSE].visible = !label_pos[5].hidden; } else if(infile.key == "name") { value_pos[0].x = eatFirstInt(infile.val,','); value_pos[0].y = eatFirstInt(infile.val,','); value_pos[0].w = eatFirstInt(infile.val,','); value_pos[0].h = eatFirstInt(infile.val,','); } else if(infile.key == "level") { value_pos[1].x = eatFirstInt(infile.val,','); value_pos[1].y = eatFirstInt(infile.val,','); value_pos[1].w = eatFirstInt(infile.val,','); value_pos[1].h = eatFirstInt(infile.val,','); } else if(infile.key == "physical") { value_pos[2].x = eatFirstInt(infile.val,','); value_pos[2].y = eatFirstInt(infile.val,','); value_pos[2].w = eatFirstInt(infile.val,','); value_pos[2].h = eatFirstInt(infile.val,','); } else if(infile.key == "mental") { value_pos[3].x = eatFirstInt(infile.val,','); value_pos[3].y = eatFirstInt(infile.val,','); value_pos[3].w = eatFirstInt(infile.val,','); value_pos[3].h = eatFirstInt(infile.val,','); } else if(infile.key == "offense") { value_pos[4].x = eatFirstInt(infile.val,','); value_pos[4].y = eatFirstInt(infile.val,','); value_pos[4].w = eatFirstInt(infile.val,','); value_pos[4].h = eatFirstInt(infile.val,','); } else if(infile.key == "defense") { value_pos[5].x = eatFirstInt(infile.val,','); value_pos[5].y = eatFirstInt(infile.val,','); value_pos[5].w = eatFirstInt(infile.val,','); value_pos[5].h = eatFirstInt(infile.val,','); } else if(infile.key == "unspent") { unspent_pos = eatLabelInfo(infile.val); } else if (infile.key == "show_upgrade_physical") { if (eatFirstInt(infile.val,',') == 0) show_upgrade[0] = false; } else if (infile.key == "show_upgrade_mental") { if (eatFirstInt(infile.val,',') == 0) show_upgrade[1] = false; } else if (infile.key == "show_upgrade_offense") { if (eatFirstInt(infile.val,',') == 0) show_upgrade[2] = false; } else if (infile.key == "show_upgrade_defense") { if (eatFirstInt(infile.val,',') == 0) show_upgrade[3] = false; } else if (infile.key == "show_maxhp") { if (eatFirstInt(infile.val,',') == 0) show_stat[0] = false; } else if (infile.key == "show_hpregen") { if (eatFirstInt(infile.val,',') == 0) show_stat[1] = false; } else if (infile.key == "show_maxmp") { if (eatFirstInt(infile.val,',') == 0) show_stat[2] = false; } else if (infile.key == "show_mpregen") { if (eatFirstInt(infile.val,',') == 0) show_stat[3] = false; } else if (infile.key == "show_accuracy") { if (eatFirstInt(infile.val,',') == 0) show_stat[4] = false; } else if (infile.key == "show_avoidance") { if (eatFirstInt(infile.val,',') == 0) show_stat[5] = false; } else if (infile.key == "show_melee") { if (eatFirstInt(infile.val,',') == 0) show_stat[6] = false; } else if (infile.key == "show_ranged") { if (eatFirstInt(infile.val,',') == 0) show_stat[7] = false; } else if (infile.key == "show_mental") { if (eatFirstInt(infile.val,',') == 0) show_stat[8] = false; } else if (infile.key == "show_crit") { if (eatFirstInt(infile.val,',') == 0) show_stat[9] = false; } else if (infile.key == "show_absorb") { if (eatFirstInt(infile.val,',') == 0) show_stat[10] = false; } else if (infile.key == "show_poise") { if (eatFirstInt(infile.val,',') == 0) show_stat[11] = false; } else if (infile.key == "show_bonus_xp") { if (eatFirstInt(infile.val,',') == 0) show_stat[12] = false; } else if (infile.key == "show_bonus_currency") { if (eatFirstInt(infile.val,',') == 0) show_stat[13] = false; } else if (infile.key == "show_bonus_itemfind") { if (eatFirstInt(infile.val,',') == 0) show_stat[14] = false; } else if (infile.key == "show_bonus_stealth") { if (eatFirstInt(infile.val,',') == 0) show_stat[15] = false; } else if (infile.key == "show_resists") { if (eatFirstInt(infile.val,',') == 0) show_stat[16] = false; } } infile.close(); } // stat list statList = new WidgetListBox(STATLIST_COUNT-1+stats->vulnerable.size(), statlist_rows, "images/menus/buttons/listbox_char.png"); tablist.add(statList); statList->can_select = false; statList->scrollbar_offset = statlist_scrollbar_offset; background = loadGraphicSurface("images/menus/character.png"); } void MenuCharacter::update() { // close button closeButton->pos.x = window_area.x + close_pos.x; closeButton->pos.y = window_area.y + close_pos.y; // menu title labelCharacter->set(window_area.x+title.x, window_area.y+title.y, title.justify, title.valign, msg->get("Character"), font->getColor("menu_normal"), title.font_style); // upgrade buttons for (int i=0; i<4; i++) { upgradeButton[i]->pos.x = window_area.x+upgrade_pos[i].x; upgradeButton[i]->pos.y = window_area.y+upgrade_pos[i].y; } // stat list statList->pos.x = window_area.x+statlist_pos.x; statList->pos.y = window_area.y+statlist_pos.y; // setup static labels cstat[CSTAT_NAME].label->set(window_area.x+label_pos[0].x, window_area.y+label_pos[0].y, label_pos[0].justify, label_pos[0].valign, msg->get("Name"), font->getColor("menu_normal"), label_pos[0].font_style); cstat[CSTAT_LEVEL].label->set(window_area.x+label_pos[1].x, window_area.y+label_pos[1].y, label_pos[1].justify, label_pos[1].valign, msg->get("Level"), font->getColor("menu_normal"), label_pos[1].font_style); cstat[CSTAT_PHYSICAL].label->set(window_area.x+label_pos[2].x, window_area.y+label_pos[2].y, label_pos[2].justify, label_pos[2].valign, msg->get("Physical"), font->getColor("menu_normal"), label_pos[2].font_style); cstat[CSTAT_MENTAL].label->set(window_area.x+label_pos[3].x, window_area.y+label_pos[3].y, label_pos[3].justify, label_pos[3].valign, msg->get("Mental"), font->getColor("menu_normal"), label_pos[3].font_style); cstat[CSTAT_OFFENSE].label->set(window_area.x+label_pos[4].x, window_area.y+label_pos[4].y, label_pos[4].justify, label_pos[4].valign, msg->get("Offense"), font->getColor("menu_normal"), label_pos[4].font_style); cstat[CSTAT_DEFENSE].label->set(window_area.x+label_pos[5].x, window_area.y+label_pos[5].y, label_pos[5].justify, label_pos[5].valign, msg->get("Defense"), font->getColor("menu_normal"), label_pos[5].font_style); // setup hotspot locations cstat[CSTAT_NAME].setHover(window_area.x+value_pos[0].x, window_area.y+value_pos[0].y, value_pos[0].w, value_pos[0].h); cstat[CSTAT_LEVEL].setHover(window_area.x+value_pos[1].x, window_area.y+value_pos[1].y, value_pos[1].w, value_pos[1].h); cstat[CSTAT_PHYSICAL].setHover(window_area.x+value_pos[2].x, window_area.y+value_pos[2].y, value_pos[2].w, value_pos[2].h); cstat[CSTAT_MENTAL].setHover(window_area.x+value_pos[3].x, window_area.y+value_pos[3].y, value_pos[3].w, value_pos[3].h); cstat[CSTAT_OFFENSE].setHover(window_area.x+value_pos[4].x, window_area.y+value_pos[4].y, value_pos[4].w, value_pos[4].h); cstat[CSTAT_DEFENSE].setHover(window_area.x+value_pos[5].x, window_area.y+value_pos[5].y, value_pos[5].w, value_pos[5].h); } /** * Rebuild all stat values and tooltip info */ void MenuCharacter::refreshStats() { stats->refresh_stats = false; stringstream ss; // update stat text cstat[CSTAT_NAME].value->set(window_area.x+value_pos[0].x+4, window_area.y+value_pos[0].y+value_pos[0].h/2, JUSTIFY_LEFT, VALIGN_CENTER, stats->name, font->getColor("menu_normal")); ss.str(""); ss << stats->level; cstat[CSTAT_LEVEL].value->set(window_area.x+value_pos[1].x+value_pos[1].w/2, window_area.y+value_pos[1].y+value_pos[1].h/2, JUSTIFY_CENTER, VALIGN_CENTER, ss.str(), font->getColor("menu_normal")); ss.str(""); ss << stats->get_physical(); cstat[CSTAT_PHYSICAL].value->set(window_area.x+value_pos[2].x+value_pos[2].w/2, window_area.y+value_pos[2].y+value_pos[2].h/2, JUSTIFY_CENTER, VALIGN_CENTER, ss.str(), bonusColor(stats->physical_additional)); ss.str(""); ss << stats->get_mental(); cstat[CSTAT_MENTAL].value->set(window_area.x+value_pos[3].x+value_pos[3].w/2, window_area.y+value_pos[3].y+value_pos[3].h/2, JUSTIFY_CENTER, VALIGN_CENTER, ss.str(), bonusColor(stats->mental_additional)); ss.str(""); ss << stats->get_offense(); cstat[CSTAT_OFFENSE].value->set(window_area.x+value_pos[4].x+value_pos[4].w/2, window_area.y+value_pos[4].y+value_pos[4].h/2, JUSTIFY_CENTER, VALIGN_CENTER, ss.str(), bonusColor(stats->offense_additional)); ss.str(""); ss << stats->get_defense(); cstat[CSTAT_DEFENSE].value->set(window_area.x+value_pos[5].x+value_pos[5].w/2, window_area.y+value_pos[5].y+value_pos[5].h/2, JUSTIFY_CENTER, VALIGN_CENTER, ss.str(), bonusColor(stats->defense_additional)); ss.str(""); if (skill_points > 0) ss << skill_points << " " << msg->get("points remaining"); else ss.str(""); labelUnspent->set(window_area.x+unspent_pos.x, window_area.y+unspent_pos.y, unspent_pos.justify, unspent_pos.valign, ss.str(), font->getColor("menu_bonus"), unspent_pos.font_style); // scrolling stat list int visible_stats = 0; if (show_stat[0]) { ss.str(""); ss << msg->get("Max HP:") << " " << stats->get(STAT_HP_MAX); statList->set(visible_stats++, ss.str(), statTooltip(STAT_HP_MAX)); } if (show_stat[1]) { ss.str(""); ss << msg->get("HP Regen:") << " " << stats->get(STAT_HP_REGEN); statList->set(visible_stats++, ss.str(), msg->get("Ticks of HP regen per minute. ") + statTooltip(STAT_HP_REGEN)); } if (show_stat[2]) { ss.str(""); ss << msg->get("Max MP:") << " " << stats->get(STAT_MP_MAX); statList->set(visible_stats++, ss.str(), statTooltip(STAT_MP_MAX)); } if (show_stat[3]) { ss.str(""); ss << msg->get("MP Regen:") << " " << stats->get(STAT_MP_REGEN); statList->set(visible_stats++, ss.str(), msg->get("Ticks of MP regen per minute. ") + statTooltip(STAT_MP_REGEN)); } if (show_stat[4]) { ss.str(""); ss << msg->get("Accuracy:") << " " << stats->get(STAT_ACCURACY) << "%"; statList->set(visible_stats++, ss.str(), statTooltip(STAT_ACCURACY)); } if (show_stat[5]) { ss.str(""); ss << msg->get("Avoidance:") << " " << stats->get(STAT_AVOIDANCE) << "%"; statList->set(visible_stats++, ss.str(), statTooltip(STAT_AVOIDANCE)); } if (show_stat[6]) { ss.str(""); ss << msg->get("Melee Damage:") << " "; if (stats->get(STAT_DMG_MELEE_MIN) == stats->get(STAT_DMG_MELEE_MAX)) ss << stats->get(STAT_DMG_MELEE_MIN); else ss << stats->get(STAT_DMG_MELEE_MIN) << "-" << stats->get(STAT_DMG_MELEE_MAX); statList->set(visible_stats++, ss.str(),""); } if (show_stat[7]) { ss.str(""); ss << msg->get("Ranged Damage:") << " "; if (stats->get(STAT_DMG_RANGED_MIN) == stats->get(STAT_DMG_RANGED_MAX)) ss << stats->get(STAT_DMG_RANGED_MIN); else ss << stats->get(STAT_DMG_RANGED_MIN) << "-" << stats->get(STAT_DMG_RANGED_MAX); statList->set(visible_stats++, ss.str(),""); } if (show_stat[8]) { ss.str(""); ss << msg->get("Mental Damage:") << " "; if (stats->get(STAT_DMG_MENT_MIN) == stats->get(STAT_DMG_MENT_MAX)) ss << stats->get(STAT_DMG_MENT_MIN); else ss << stats->get(STAT_DMG_MENT_MIN) << "-" << stats->get(STAT_DMG_MENT_MAX); statList->set(visible_stats++, ss.str(),""); } if (show_stat[9]) { ss.str(""); ss << msg->get("Crit:") << " " << stats->get(STAT_CRIT) << "%"; statList->set(visible_stats++, ss.str(), statTooltip(STAT_CRIT)); } if (show_stat[10]) { ss.str(""); ss << msg->get("Absorb:") << " "; if (stats->get(STAT_ABS_MIN) == stats->get(STAT_ABS_MAX)) ss << stats->get(STAT_ABS_MIN); else ss << stats->get(STAT_ABS_MIN) << "-" << stats->get(STAT_ABS_MAX); statList->set(visible_stats++, ss.str(),""); } if (show_stat[11]) { ss.str(""); ss << msg->get("Poise: ") << stats->get(STAT_POISE) << "%"; statList->set(visible_stats++, ss.str(), msg->get("Reduces your chance of stumbling when hit") + statTooltip(STAT_POISE)); } if (show_stat[12]) { ss.str(""); ss << msg->get("Bonus XP: ") << stats->get(STAT_XP_GAIN) << "%"; statList->set(visible_stats++, ss.str(), msg->get("Increases the XP gained per kill") + statTooltip(STAT_XP_GAIN)); } if (show_stat[13]) { ss.str(""); ss << msg->get("Bonus") << " " << CURRENCY << ": " << stats->get(STAT_CURRENCY_FIND) << "%"; statList->set(visible_stats++, ss.str(), msg->get("Increases the %s found per drop",CURRENCY) + statTooltip(STAT_CURRENCY_FIND)); } if (show_stat[14]) { ss.str(""); ss << msg->get("Bonus Item Find: ") << stats->get(STAT_ITEM_FIND)<< "%"; statList->set(visible_stats++, ss.str(), msg->get("Increases the chance that an enemy will drop an item when killed") + statTooltip(STAT_ITEM_FIND)); } if (show_stat[15]) { ss.str(""); ss << msg->get("Stealth: ") << stats->get(STAT_STEALTH) << "%"; statList->set(visible_stats++, ss.str(), msg->get("Increases your ability to move undetected") + statTooltip(STAT_STEALTH)); } if (show_stat[16]) { for (unsigned int j=0; j<stats->vulnerable.size(); j++) { ss.str(""); ss << msg->get(ELEMENTS[j].description) << ": " << (100 - stats->vulnerable[j]) << "%"; statList->set(visible_stats++, ss.str(),""); } } statList->refresh(); // update tool tips cstat[CSTAT_NAME].tip.clear(); cstat[CSTAT_NAME].tip.addText(msg->get(stats->character_class)); cstat[CSTAT_LEVEL].tip.clear(); cstat[CSTAT_LEVEL].tip.addText(msg->get("XP: %d", stats->xp)); if (stats->level < (int)stats->xp_table.size()) { cstat[CSTAT_LEVEL].tip.addText(msg->get("Next: %d", stats->xp_table[stats->level])); } cstat[CSTAT_PHYSICAL].tip.clear(); cstat[CSTAT_PHYSICAL].tip.addText(msg->get("Physical (P) increases melee weapon proficiency and total HP.")); cstat[CSTAT_PHYSICAL].tip.addText(msg->get("base (%d), bonus (%d)", stats->physical_character, stats->physical_additional)); cstat[CSTAT_MENTAL].tip.clear(); cstat[CSTAT_MENTAL].tip.addText(msg->get("Mental (M) increases mental weapon proficiency and total MP.")); cstat[CSTAT_MENTAL].tip.addText(msg->get("base (%d), bonus (%d)", stats->mental_character, stats->mental_additional)); cstat[CSTAT_OFFENSE].tip.clear(); cstat[CSTAT_OFFENSE].tip.addText(msg->get("Offense (O) increases ranged weapon proficiency and accuracy.")); cstat[CSTAT_OFFENSE].tip.addText(msg->get("base (%d), bonus (%d)", stats->offense_character, stats->offense_additional)); cstat[CSTAT_DEFENSE].tip.clear(); cstat[CSTAT_DEFENSE].tip.addText(msg->get("Defense (D) increases armor proficiency and avoidance.")); cstat[CSTAT_DEFENSE].tip.addText(msg->get("base (%d), bonus (%d)", stats->defense_character, stats->defense_additional)); } /** * Color-coding for positive/negative/no bonus */ SDL_Color MenuCharacter::bonusColor(int stat) { if (stat > 0) return font->getColor("menu_bonus"); if (stat < 0) return font->getColor("menu_penalty"); return font->getColor("menu_label"); } /** * Create tooltip text showing the per_* values of a stat */ std::string MenuCharacter::statTooltip(int stat) { std::string tooltip_text; if (stats->per_level[stat] > 0) tooltip_text += msg->get("Each level grants %d. ", stats->per_level[stat]); if (stats->per_physical[stat] > 0) tooltip_text += msg->get("Each point of Physical grants %d. ", stats->per_physical[stat]); if (stats->per_mental[stat] > 0) tooltip_text += msg->get("Each point of Mental grants %d. ", stats->per_mental[stat]); if (stats->per_offense[stat] > 0) tooltip_text += msg->get("Each point of Offense grants %d. ", stats->per_offense[stat]); if (stats->per_defense[stat] > 0) tooltip_text += msg->get("Each point of Defense grants %d. ", stats->per_defense[stat]); return tooltip_text; } void MenuCharacter::logic() { if (!visible) return; if (NO_MOUSE) { tablist.logic(); } if (closeButton->checkClick()) { visible = false; snd->play(sfx_close); } // upgrade buttons for (int i=0; i<4; i++) { upgradeButton[i]->enabled = false; tablist.remove(upgradeButton[i]); } int spent = stats->physical_character + stats->mental_character + stats->offense_character + stats->defense_character -4; skill_points = (stats->level * stats->stat_points_per_level) - spent; if (stats->hp > 0 && spent < (stats->level * stats->stat_points_per_level) && spent < stats->max_spendable_stat_points) { if (stats->physical_character < stats->max_points_per_stat && show_upgrade[0]) { upgradeButton[0]->enabled = true; tablist.add(upgradeButton[0]); } if (stats->mental_character < stats->max_points_per_stat && show_upgrade[1]) { upgradeButton[1]->enabled = true; tablist.add(upgradeButton[1]); } if (stats->offense_character < stats->max_points_per_stat && show_upgrade[2]) { upgradeButton[2]->enabled = true; tablist.add(upgradeButton[2]); } if (stats->defense_character < stats->max_points_per_stat && show_upgrade[3]) { upgradeButton[3]->enabled = true; tablist.add(upgradeButton[3]); } } if (upgradeButton[0]->checkClick()) physical_up = true; if (upgradeButton[1]->checkClick()) mental_up = true; if (upgradeButton[2]->checkClick()) offense_up = true; if (upgradeButton[3]->checkClick()) defense_up = true; statList->checkClick(); if (stats->refresh_stats) refreshStats(); } void MenuCharacter::render() { if (!visible) return; SDL_Rect src; SDL_Rect dest; // background dest = window_area; src.x = 0; src.y = 0; src.w = window_area.w; src.h = window_area.h; SDL_BlitSurface(background, &src, screen, &dest); // close button closeButton->render(); // title labelCharacter->render(); // unspent points labelUnspent->render(); // labels and values for (int i=0; i<CSTAT_COUNT; i++) { if (cstat[i].visible) { cstat[i].label->render(); cstat[i].value->render(); } } // upgrade buttons for (int i=0; i<4; i++) { if (upgradeButton[i]->enabled) upgradeButton[i]->render(); } statList->render(); } /** * Display various mouseovers tooltips depending on cursor location */ TooltipData MenuCharacter::checkTooltip() { for (int i=0; i<CSTAT_COUNT; i++) { if (isWithin(cstat[i].hover, inpt->mouse) && !cstat[i].tip.isEmpty() && cstat[i].visible) return cstat[i].tip; } return statList->checkTooltip(inpt->mouse); } /** * User might click this menu to upgrade a stat. Check for this situation. * Return true if a stat was upgraded. */ bool MenuCharacter::checkUpgrade() { int spent = stats->physical_character + stats->mental_character + stats->offense_character + stats->defense_character -4; skill_points = (stats->level * stats->stat_points_per_level) - spent; // check to see if there are skill points available if (spent < (stats->level * stats->stat_points_per_level) && spent < stats->max_spendable_stat_points) { // physical if (physical_up) { stats->physical_character++; stats->recalc(); // equipment applied by MenuManager newPowerNotification = true; //TODO: Only show if a NEW power is unlocked... physical_up = false; return true; } // mental else if (mental_up) { stats->mental_character++; stats->recalc(); // equipment applied by MenuManager newPowerNotification = true; mental_up = false; return true; } // offense else if (offense_up) { stats->offense_character++; stats->recalc(); // equipment applied by MenuManager newPowerNotification = true; offense_up = false; return true; } // defense else if (defense_up) { stats->defense_character++; stats->recalc(); // equipment applied by MenuManager newPowerNotification = true; defense_up = false; return true; } } return false; } MenuCharacter::~MenuCharacter() { SDL_FreeSurface(background); delete closeButton; delete labelCharacter; delete labelUnspent; for (int i=0; i<CSTAT_COUNT; i++) { delete cstat[i].label; delete cstat[i].value; } for (int i=0; i<4; i++) { delete upgradeButton[i]; } delete statList; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuCharacter.h���������������������������������������������������������������0000664�0000000�0000000�00000004524�12247171015�0017465�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuCharacter */ #pragma once #ifndef MENU_CHARACTER_H #define MENU_CHARACTER_H #include "CommonIncludes.h" #include "WidgetLabel.h" #include "TooltipData.h" class StatBlock; class WidgetButton; class WidgetLabel; class WidgetListBox; const int CSTAT_NAME = 0; const int CSTAT_LEVEL = 1; const int CSTAT_PHYSICAL = 2; const int CSTAT_MENTAL = 3; const int CSTAT_OFFENSE = 4; const int CSTAT_DEFENSE = 5; const int CSTAT_COUNT = 6; const int STATLIST_COUNT = 17; class CharStat { public: WidgetLabel *label; WidgetLabel *value; SDL_Rect hover; TooltipData tip; bool visible; void setHover(int x, int y, int w, int h) { hover.x=x; hover.y=y; hover.w=w; hover.h=h; } }; class MenuCharacter : public Menu { private: StatBlock *stats; WidgetButton *closeButton; WidgetButton *upgradeButton[4]; WidgetLabel *labelCharacter; WidgetLabel *labelUnspent; WidgetListBox *statList; CharStat cstat[CSTAT_COUNT]; void loadGraphics(); SDL_Color bonusColor(int stat); std::string statTooltip(int stat); int skill_points; bool physical_up; bool mental_up; bool offense_up; bool defense_up; // label and widget positions Point close_pos; LabelInfo title; Point upgrade_pos[4]; Point statlist_pos; int statlist_rows; int statlist_scrollbar_offset; LabelInfo unspent_pos; LabelInfo label_pos[CSTAT_COUNT]; SDL_Rect value_pos[CSTAT_COUNT]; bool show_upgrade[4]; bool show_stat[STATLIST_COUNT]; public: MenuCharacter(StatBlock *stats); ~MenuCharacter(); void update(); void logic(); void render(); void refreshStats(); TooltipData checkTooltip(); bool checkUpgrade(); int getUnspent() { return skill_points; } bool newPowerNotification; TabList tablist; }; #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuConfirm.cpp���������������������������������������������������������������0000664�0000000�0000000�00000005505�12247171015�0017521�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "MenuConfirm.h" #include "Settings.h" #include "SharedResources.h" using namespace std; MenuConfirm::MenuConfirm(const string& _buttonMsg, const string& _boxMsg) : Menu() { confirmClicked = false; cancelClicked = false; hasConfirmButton = true; if (_buttonMsg == "") hasConfirmButton = false; // Text to display in confirmation box boxMsg = _boxMsg; if (hasConfirmButton) { buttonConfirm = new WidgetButton("images/menus/buttons/button_default.png"); buttonConfirm->label = _buttonMsg; tablist.add(buttonConfirm); } buttonClose = new WidgetButton("images/menus/buttons/button_x.png"); tablist.add(buttonClose); background = loadGraphicSurface("images/menus/confirm_bg.png"); } void MenuConfirm::update() { if (hasConfirmButton) { buttonConfirm->pos.x = window_area.x + window_area.w/2 - buttonConfirm->pos.w/2; buttonConfirm->pos.y = window_area.y + window_area.h/2; buttonConfirm->refresh(); label.set(window_area.x + window_area.w/2, window_area.y + window_area.h - (buttonConfirm->pos.h * 2), JUSTIFY_CENTER, VALIGN_TOP, boxMsg, font->getColor("menu_normal")); } else { label.set(window_area.x + window_area.w/2, window_area.y + (window_area.h / 4), JUSTIFY_CENTER, VALIGN_TOP, boxMsg, font->getColor("menu_normal")); } buttonClose->pos.x = window_area.x + window_area.w; buttonClose->pos.y = window_area.y; } void MenuConfirm::logic() { if (visible) { tablist.logic(); confirmClicked = false; } if (visible && hasConfirmButton) { if(buttonConfirm->checkClick()) { confirmClicked = true; } if(buttonClose->checkClick()) { visible = false; cancelClicked = true; } } else if (visible && !hasConfirmButton) { if(buttonClose->checkClick()) { visible = false; cancelClicked = true; } } } void MenuConfirm::render() { SDL_Rect src; // background src.x = 0; src.y = 0; src.w = window_area.w; src.h = window_area.h; SDL_BlitSurface(background, &src, screen, &window_area); label.render(); if (hasConfirmButton) buttonConfirm->render(); buttonClose->render(); } MenuConfirm::~MenuConfirm() { if (hasConfirmButton) delete buttonConfirm; delete buttonClose; SDL_FreeSurface(background); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuConfirm.h�����������������������������������������������������������������0000664�0000000�0000000�00000002272�12247171015�0017164�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #pragma once #ifndef MENU_CONFIRM_H #define MENU_CONFIRM_H #include "CommonIncludes.h" #include "Menu.h" #include "WidgetButton.h" class MenuConfirm : public Menu { protected: WidgetButton *buttonConfirm; WidgetButton *buttonClose; WidgetLabel label; TabList tablist; std::string boxMsg; bool hasConfirmButton; public: MenuConfirm(const std::string&, const std::string&); ~MenuConfirm(); void update(); void logic(); virtual void render(); bool confirmClicked; bool cancelClicked; }; #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuEnemy.cpp�����������������������������������������������������������������0000664�0000000�0000000�00000007002�12247171015�0017173�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Pavel Kirpichyov (Cheshire) This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * MenuEnemy * * Handles the display of the Enemy bar on the HUD */ #include "CommonIncludes.h" #include "Enemy.h" #include "Menu.h" #include "MenuEnemy.h" #include "SharedResources.h" #include "WidgetLabel.h" #include "FileParser.h" #include "UtilsParsing.h" #include "UtilsFileSystem.h" using namespace std; MenuEnemy::MenuEnemy() { custom_text_pos = false; // Load config settings FileParser infile; if(infile.open("menus/enemy.txt")) { while(infile.next()) { infile.val = infile.val + ','; if(infile.key == "pos") { bar_pos.x = eatFirstInt(infile.val,','); bar_pos.y = eatFirstInt(infile.val,','); bar_pos.w = eatFirstInt(infile.val,','); bar_pos.h = eatFirstInt(infile.val,','); } else if(infile.key == "text_pos") { custom_text_pos = true; text_pos = eatLabelInfo(infile.val); } } infile.close(); } loadGraphics(); enemy = NULL; timeout = 0; color_normal = font->getColor("menu_normal"); } void MenuEnemy::loadGraphics() { background = loadGraphicSurface("images/menus/enemy_bar.png"); bar_hp = loadGraphicSurface("images/menus/enemy_bar_hp.png"); } void MenuEnemy::handleNewMap() { enemy = NULL; } void MenuEnemy::logic() { // after a fixed amount of time, hide the enemy display if (timeout > 0) timeout--; if (timeout == 0) enemy = NULL; } void MenuEnemy::render() { if (enemy == NULL) return; if (enemy->stats.corpse && enemy->stats.corpse_ticks == 0) return; SDL_Rect src; SDL_Rect dest; int hp_bar_length; // draw trim/background dest.x = window_area.x+bar_pos.x; dest.y = window_area.y+bar_pos.y; dest.w = bar_pos.w; dest.h = bar_pos.h; SDL_BlitSurface(background, NULL, screen, &dest); if (enemy->stats.get(STAT_HP_MAX) == 0) hp_bar_length = 0; else hp_bar_length = (enemy->stats.hp * 100) / enemy->stats.get(STAT_HP_MAX); // draw hp bar src.x = 0; src.y = 0; src.h = bar_pos.h; src.w = hp_bar_length; SDL_BlitSurface(bar_hp, &src, screen, &dest); stringstream ss; ss.str(""); if (enemy->stats.hp > 0) ss << enemy->stats.hp << "/" << enemy->stats.get(STAT_HP_MAX); else ss << msg->get("Dead"); if (!text_pos.hidden) { WidgetLabel label; if (custom_text_pos) { label.set(window_area.x+text_pos.x, window_area.y+text_pos.y, text_pos.justify, text_pos.valign, msg->get("%s level %d", enemy->stats.level, enemy->stats.name), color_normal, text_pos.font_style); } else { label.set(window_area.x+bar_pos.x+bar_pos.w/2, window_area.y+bar_pos.y, JUSTIFY_CENTER, VALIGN_BOTTOM, msg->get("%s level %d", enemy->stats.level, enemy->stats.name), color_normal); } label.render(); label.set(window_area.x+bar_pos.x+bar_pos.w/2, window_area.y+bar_pos.y+bar_pos.h/2, JUSTIFY_CENTER, VALIGN_CENTER, ss.str(), color_normal); label.render(); } //SDL_UpdateRects(screen, 1, &dest); } MenuEnemy::~MenuEnemy() { SDL_FreeSurface(background); SDL_FreeSurface(bar_hp); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuEnemy.h�������������������������������������������������������������������0000664�0000000�0000000�00000002265�12247171015�0016646�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Pavel Kirpichyov (Cheshire) This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * MenuEnemy * * Handles the display of the Enemy info of the screen */ #pragma once #ifndef MENU_ENEMY_H #define MENU_ENEMY_H #include "CommonIncludes.h" #include "Settings.h" #include "WidgetLabel.h" class Enemy; class MenuEnemy : public Menu { private: SDL_Surface *bar_hp; SDL_Rect bar_pos; LabelInfo text_pos; bool custom_text_pos; SDL_Color color_normal; public: MenuEnemy(); ~MenuEnemy(); Enemy *enemy; void loadGraphics(); void handleNewMap(); void logic(); void render(); int timeout; }; #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuExit.cpp������������������������������������������������������������������0000664�0000000�0000000�00000004136�12247171015�0017034�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 kitano This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuExit */ #include "MenuExit.h" #include "SharedResources.h" #include "Settings.h" MenuExit::MenuExit() : Menu() { exitClicked = false; buttonExit = new WidgetButton("images/menus/buttons/button_default.png"); buttonExit->label = msg->get("Exit"); buttonClose = new WidgetButton("images/menus/buttons/button_x.png"); background = loadGraphicSurface("images/menus/confirm_bg.png"); tablist.add(buttonExit); tablist.add(buttonClose); } void MenuExit::update() { buttonExit->pos.x = VIEW_W_HALF - buttonExit->pos.w/2; buttonExit->pos.y = VIEW_H/2; buttonExit->refresh(); buttonClose->pos.x = window_area.x + window_area.w; buttonClose->pos.y = window_area.y; label.set(window_area.x + window_area.w/2, window_area.y + window_area.h - (buttonExit->pos.h * 2), JUSTIFY_CENTER, VALIGN_TOP, msg->get("Save and exit to title?"), font->getColor("menu_normal")); } void MenuExit::logic() { if (visible) { if (NO_MOUSE) { tablist.logic(); } if (buttonExit->checkClick()) { exitClicked = true; } if (buttonClose->checkClick()) { visible = false; } } } void MenuExit::render() { if (visible) { SDL_Rect src; // background src.x = 0; src.y = 0; src.w = window_area.w; src.h = window_area.h; SDL_BlitSurface(background, &src, screen, &window_area); label.render(); buttonExit->render(); buttonClose->render(); } } MenuExit::~MenuExit() { delete buttonExit; delete buttonClose; SDL_FreeSurface(background); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuExit.h��������������������������������������������������������������������0000664�0000000�0000000�00000002163�12247171015�0016477�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 kitano This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuExit */ #pragma once #ifndef MENU_EXIT_h #define MENU_EXIT_H #include "CommonIncludes.h" #include "Menu.h" #include "WidgetButton.h" class MenuExit : public Menu { protected: void loadGraphics(); WidgetButton *buttonExit; WidgetButton *buttonClose; WidgetLabel label; TabList tablist; bool exitClicked; public: MenuExit(); ~MenuExit(); void update(); void logic(); virtual void render(); bool isExitRequested() { return exitClicked; } }; #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuHUDLog.cpp����������������������������������������������������������������0000664�0000000�0000000�00000006122�12247171015�0017202�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuHUDLog */ #include "Menu.h" #include "MenuHUDLog.h" #include "SharedResources.h" #include "Settings.h" using namespace std; MenuHUDLog::MenuHUDLog() { list_area.x = 224; list_area.y = 416; font->setFont("font_regular"); paragraph_spacing = font->getLineHeight()/2; color_normal = font->getColor("menu_normal"); } /** * Calculate how long a given message should remain on the HUD * Formula: minimum time plus x frames per character */ int MenuHUDLog::calcDuration(const string& s) { // 5 seconds plus an extra second per 10 letters return MAX_FRAMES_PER_SEC * 5 + s.length() * (MAX_FRAMES_PER_SEC/10); } /** * Perform one frame of logic * Age messages */ void MenuHUDLog::logic() { for (unsigned i=0; i<msg_age.size(); i++) { if (msg_age[i] > 0) msg_age[i]--; else remove(i); } } /** * New messages appear on the screen for a brief time */ void MenuHUDLog::render() { SDL_Rect dest; dest.x = window_area.x; dest.y = window_area.y; // go through new messages for (int i = msg_age.size() - 1; i >= 0; i--) { if (msg_age[i] > 0 && dest.y > 64) { dest.y -= msg_buffer[i]->h + paragraph_spacing; SDL_BlitSurface(msg_buffer[i], NULL, screen, &dest); } else return; // no more new messages } } /** * Add a new message to the log */ void MenuHUDLog::add(const string& s) { // add new message log_msg.push_back(s); msg_age.push_back(calcDuration(s)); // force HUD messages to vanish in order if (msg_age.size() > 1) { const int last = msg_age.size()-1; if (msg_age[last] < msg_age[last-1]) msg_age[last] = msg_age[last-1]; } // render the log entry and store it in a buffer font->setFont("font_regular"); Point size = font->calc_size(s, window_area.w); msg_buffer.push_back(createAlphaSurface(size.x, size.y)); font->renderShadowed(s, 0, 0, JUSTIFY_LEFT, msg_buffer.back(), window_area.w, color_normal); } /** * Remove the given message from the list */ void MenuHUDLog::remove(int msg_index) { SDL_FreeSurface(msg_buffer.at(msg_index)); msg_buffer.erase(msg_buffer.begin()+msg_index); msg_age.erase(msg_age.begin()+msg_index); log_msg.erase(log_msg.begin()+msg_index); } void MenuHUDLog::clear() { for (unsigned i=0; i<msg_buffer.size(); i++) { SDL_FreeSurface(msg_buffer[i]); } msg_buffer.clear(); msg_age.clear(); log_msg.clear(); } MenuHUDLog::~MenuHUDLog() { for (unsigned i=0; i<msg_buffer.size(); i++) { SDL_FreeSurface(msg_buffer[i]); } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuHUDLog.h������������������������������������������������������������������0000664�0000000�0000000�00000002301�12247171015�0016642�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuHUDLog */ #pragma once #ifndef MENU_HUD_LOG_H #define MENU_HUD_LOG_H #include "CommonIncludes.h" #include "Utils.h" class MenuHUDLog : public Menu { private: int calcDuration(const std::string& s); std::vector<std::string> log_msg; std::vector<int> msg_age; std::vector<SDL_Surface*> msg_buffer; int paragraph_spacing; SDL_Color color_normal; public: MenuHUDLog(); ~MenuHUDLog(); void logic(); void render(); void add(const std::string& s); void remove(int msg_index); void clear(); Point list_area; }; #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuInventory.cpp�������������������������������������������������������������0000664�0000000�0000000�00000071771�12247171015�0020131�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuInventory */ #include "CommonIncludes.h" #include "FileParser.h" #include "Menu.h" #include "MenuInventory.h" #include "Settings.h" #include "SharedGameResources.h" #include "SharedResources.h" #include "StatBlock.h" #include "UtilsParsing.h" #include "WidgetButton.h" using namespace std; MenuInventory::MenuInventory(StatBlock *_stats) { stats = _stats; MAX_EQUIPPED = 4; MAX_CARRIED = 64; visible = false; background = loadGraphicSurface("images/menus/inventory.png"); currency = 0; drag_prev_src = -1; changed_equipment = true; changed_artifact = true; log_msg = ""; drop_stack.item = 0; drop_stack.quantity = 0; closeButton = new WidgetButton("images/menus/buttons/button_x.png"); // Load config settings SDL_Rect equipment_slot; FileParser infile; if(infile.open("menus/inventory.txt")) { while(infile.next()) { infile.val = infile.val + ','; if(infile.key == "close") { close_pos.x = eatFirstInt(infile.val,','); close_pos.y = eatFirstInt(infile.val,','); } else if(infile.key == "equipment_slot") { equipment_slot.x = eatFirstInt(infile.val,','); equipment_slot.y = eatFirstInt(infile.val,','); equipment_slot.w = equipment_slot.h = eatFirstInt(infile.val,','); equipped_area.push_back(equipment_slot); slot_type.push_back(eatFirstString(infile.val,',')); } else if(infile.key == "slot_name") { slot_desc.push_back(eatFirstString(infile.val,',')); } else if(infile.key == "carried_area") { carried_area.x = eatFirstInt(infile.val,','); carried_area.y = eatFirstInt(infile.val,','); } else if (infile.key == "carried_cols") { carried_cols = eatFirstInt(infile.val,','); } else if (infile.key == "carried_rows") { carried_rows = eatFirstInt(infile.val,','); } else if (infile.key == "caption") { title = eatLabelInfo(infile.val); } else if (infile.key == "currency") { currency_lbl = eatLabelInfo(infile.val); } else if (infile.key == "help") { help_pos.x = eatFirstInt(infile.val,','); help_pos.y = eatFirstInt(infile.val,','); help_pos.w = eatFirstInt(infile.val,','); help_pos.h = eatFirstInt(infile.val,','); } } infile.close(); } MAX_EQUIPPED = equipped_area.size(); MAX_CARRIED = carried_cols * carried_rows; color_normal = font->getColor("menu_normal"); color_high = font->getColor("menu_bonus"); } void MenuInventory::update() { for (int i=0; i<MAX_EQUIPPED; i++) { equipped_area[i].x += window_area.x; equipped_area[i].y += window_area.y; } carried_area.x += window_area.x; carried_area.y += window_area.y; carried_area.w = carried_cols*ICON_SIZE; carried_area.h = carried_rows*ICON_SIZE; inventory[EQUIPMENT].init(MAX_EQUIPPED, equipped_area, slot_type); inventory[CARRIED].init(MAX_CARRIED, carried_area, ICON_SIZE, carried_cols); closeButton->pos.x = window_area.x+close_pos.x; closeButton->pos.y = window_area.y+close_pos.y; for (int i = 0; i < MAX_EQUIPPED; i++) { tablist.add(inventory[EQUIPMENT].slots[i]); } for (int i = 0; i < MAX_CARRIED; i++) { tablist.add(inventory[CARRIED].slots[i]); } } void MenuInventory::logic() { // if the player has just died, the penalty is half his current currency. if (stats->death_penalty && DEATH_PENALTY) { std::string death_message = ""; // remove a % of currency if (DEATH_PENALTY_CURRENCY > 0) { if (currency > 0) removeCurrency((currency * DEATH_PENALTY_CURRENCY) / 100); death_message += msg->get("Lost %d%% of %s. ", DEATH_PENALTY_CURRENCY, CURRENCY); } // remove a % of either total xp or xp since the last level if (DEATH_PENALTY_XP > 0) { if (stats->xp > 0) stats->xp -= (stats->xp * DEATH_PENALTY_XP) / 100; death_message += msg->get("Lost %d%% of total XP. ", DEATH_PENALTY_XP); } else if (DEATH_PENALTY_XP_CURRENT > 0) { if (stats->xp - stats->xp_table[stats->level-1] > 0) stats->xp -= ((stats->xp - stats->xp_table[stats->level-1]) * DEATH_PENALTY_XP_CURRENT) / 100; death_message += msg->get("Lost %d%% of current level XP. ", DEATH_PENALTY_XP_CURRENT); } // prevent down-leveling from removing too much xp if (stats->xp < stats->xp_table[stats->level-1]) stats->xp = stats->xp_table[stats->level-1]; // remove a random carried item if (DEATH_PENALTY_ITEM) { std::vector<int> removable_items; removable_items.clear(); for (int i=0; i < MAX_EQUIPPED; i++) { if (inventory[EQUIPMENT][i].item > 0) { if (items->items[inventory[EQUIPMENT][i].item].type != "quest") removable_items.push_back(inventory[EQUIPMENT][i].item); } } for (int i=0; i < MAX_CARRIED; i++) { if (inventory[CARRIED][i].item > 0) { if (items->items[inventory[CARRIED][i].item].type != "quest") removable_items.push_back(inventory[CARRIED][i].item); } } if (!removable_items.empty()) { int random_item = rand() % removable_items.size(); remove(removable_items[random_item]); death_message += msg->get("Lost %s.",items->items[removable_items[random_item]].name); } } log_msg = death_message; stats->death_penalty = false; } // a copy of currency is kept in stats, to help with various situations stats->currency = currency = getCurrency(); // check close button if (visible) { if (NO_MOUSE) { tablist.logic(); } if (closeButton->checkClick()) { visible = false; snd->play(sfx_close); } if (drag_prev_src == -1) { clearHighlight(); } } } void MenuInventory::render() { if (!visible) return; // background SDL_Rect dest = window_area; SDL_BlitSurface(background, NULL, screen, &dest); // close button closeButton->render(); // text overlay WidgetLabel label; if (!title.hidden) { label.set(window_area.x+title.x, window_area.y+title.y, title.justify, title.valign, msg->get("Inventory"), color_normal, title.font_style); label.render(); } if (!currency_lbl.hidden) { label.set(window_area.x+currency_lbl.x, window_area.y+currency_lbl.y, currency_lbl.justify, currency_lbl.valign, msg->get("%d %s", currency, CURRENCY), color_normal, currency_lbl.font_style); label.render(); } inventory[EQUIPMENT].render(); inventory[CARRIED].render(); } int MenuInventory::areaOver(Point position) { if (isWithin(carried_area, position)) { return CARRIED; } else { for (unsigned int i=0; i<equipped_area.size(); i++) { if (isWithin(equipped_area[i], position)) { return EQUIPMENT; } } } return -1; } /** * If mousing-over an item with a tooltip, return that tooltip data. * * @param mouse The x,y screen coordinates of the mouse cursor */ TooltipData MenuInventory::checkTooltip(Point position) { int area; int slot; TooltipData tip; area = areaOver(position); if (area == -1) { if (position.x >= window_area.x + help_pos.x && position.y >= window_area.y+help_pos.y && position.x < window_area.x+help_pos.x+help_pos.w && position.y < window_area.y+help_pos.y+help_pos.h) { tip.addText(msg->get("Use SHIFT to move only one item.")); tip.addText(msg->get("CTRL-click a carried item to sell it.")); } return tip; } slot = inventory[area].slotOver(position); if (slot == -1) return tip; if (inventory[area][slot].item > 0) { tip = inventory[area].checkTooltip(position, stats, PLAYER_INV); } else if (area == EQUIPMENT && inventory[area][slot].item == 0) { tip.addText(msg->get(slot_desc[slot])); } return tip; } /** * Click-start dragging in the inventory */ ItemStack MenuInventory::click(Point position) { ItemStack item; item.item = 0; item.quantity = 0; drag_prev_src = areaOver(position); if( drag_prev_src > -1) { item = inventory[drag_prev_src].click(position); // if dragging equipment, prepare to change stats/sprites if (drag_prev_src == EQUIPMENT) { if (stats->humanoid) { updateEquipment( inventory[EQUIPMENT].drag_prev_slot); } else { itemReturn(item); item.item = 0; item.quantity = 0; } } else if (drag_prev_src == CARRIED && !inpt->pressing[CTRL] && !inpt->pressing[MAIN2]) { inventory[EQUIPMENT].highlightMatching(items->items[item.item].type); } } return item; } /** * Return dragged item to previous slot */ void MenuInventory::itemReturn( ItemStack stack) { if (drag_prev_src == -1) return; inventory[drag_prev_src].itemReturn( stack); // if returning equipment, prepare to change stats/sprites if (drag_prev_src == EQUIPMENT) { updateEquipment(inventory[EQUIPMENT].drag_prev_slot); } drag_prev_src = -1; } /** * Dragging and dropping an item can be used to rearrange the inventory * and equip items */ void MenuInventory::drop(Point position, ItemStack stack) { items->playSound(stack.item); int area = areaOver(position); if (area == -1) { // not dropped into a slot. Just return it to the previous slot. itemReturn(stack); return; } int slot = inventory[area].slotOver(position); if (slot == -1) { // not dropped into a slot. Just return it to the previous slot. itemReturn(stack); return; } int drag_prev_slot = inventory[drag_prev_src].drag_prev_slot; if (area == EQUIPMENT) { // dropped onto equipped item // make sure the item is going to the correct slot // note: equipment slots 0-3 correspond with item types 0-3 // also check to see if the hero meets the requirements if (drag_prev_src == CARRIED && slot_type[slot] == items->items[stack.item].type && requirementsMet(stack.item) && stats->humanoid) { if( inventory[area][slot].item == stack.item) { // Merge the stacks add(stack, area, slot, false); } else if( inventory[drag_prev_src][drag_prev_slot].item == 0) { // Swap the two stacks itemReturn( inventory[area][slot]); inventory[area][slot] = stack; updateEquipment( slot); } else { itemReturn( stack); } } else { // equippable items only belong to one slot, for the moment itemReturn( stack); // cancel } } else if (area == CARRIED) { // dropped onto carried item if (drag_prev_src == CARRIED) { if (slot != drag_prev_slot) { if( inventory[area][slot].item == stack.item) { // Merge the stacks add(stack, area, slot, false); } else if( inventory[area][slot].item == 0) { // Drop the stack inventory[area][slot] = stack; } else if( inventory[drag_prev_src][drag_prev_slot].item == 0) { // Check if the previous slot is free (could still be used if SHIFT was used). // Swap the two stacks itemReturn( inventory[area][slot]); inventory[area][slot] = stack; } else { itemReturn( stack); } } else { itemReturn( stack); // cancel } } else { // note: equipment slots 0-3 correspond with item types 0-3 // also check to see if the hero meets the requirements if (inventory[area][slot].item == stack.item || drag_prev_src == -1) { // Merge the stacks add(stack, area, slot, false); } else if( inventory[area][slot].item == 0) { // Drop the stack inventory[area][slot] = stack; } else if( inventory[EQUIPMENT][drag_prev_slot].item == 0 && inventory[CARRIED][slot].item != stack.item && items->items[inventory[CARRIED][slot].item].type == slot_type[drag_prev_slot] && requirementsMet(inventory[CARRIED][slot].item) ) { // The whole equipped stack is dropped on an empty carried slot or on a wearable item // Swap the two stacks itemReturn( inventory[area][slot]); inventory[area][slot] = stack; } else { itemReturn( stack); // cancel } } } drag_prev_src = -1; } /** * Right-clicking on a usable item in the inventory causes it to activate. * e.g. drink a potion * e.g. equip an item */ void MenuInventory::activate(Point position) { ItemStack stack; Point nullpt; nullpt.x = nullpt.y = 0; // clicked a carried item int slot = inventory[CARRIED].slotOver(position); if (slot == -1) return; // can't interact with quest items if (items->items[inventory[CARRIED][slot].item].type == "quest") { return; } // use a consumable item else if (items->items[inventory[CARRIED][slot].item].type == "consumable") { //don't use untransform item if hero is not transformed if (powers->powers[items->items[inventory[CARRIED][slot].item].power].spawn_type == "untransform" && !stats->transformed) return; //check for power cooldown if (pc->hero_cooldown[items->items[inventory[CARRIED][slot].item].power] > 0) return; else pc->hero_cooldown[items->items[inventory[CARRIED][slot].item].power] = powers->powers[items->items[inventory[CARRIED][slot].item].power].cooldown; // if this item requires targeting it can't be used this way if (!powers->powers[items->items[inventory[CARRIED][slot].item].power].requires_targeting) { unsigned used_item_count = powers->used_items.size(); unsigned used_equipped_item_count = powers->used_equipped_items.size(); powers->activate(items->items[inventory[CARRIED][slot].item].power, stats, nullpt); // Remove any used items from the queue of items to be removed. We will destroy the items here. if (used_item_count < powers->used_items.size()) powers->used_items.pop_back(); if (used_equipped_item_count < powers->used_equipped_items.size()) powers->used_equipped_items.pop_back(); inventory[CARRIED].substract(slot); } else { // let player know this can only be used from the action bar log_msg = msg->get("This item can only be used from the action bar."); } } // equip an item else if (stats->humanoid) { int equip_slot = -1; // find first empty(or just first) slot for item to equip for (int i = 0; i < MAX_EQUIPPED; i++) { // first check for first empty if ((slot_type[i] == items->items[inventory[CARRIED][slot].item].type) && (inventory[EQUIPMENT].storage[i].item == 0)) { equip_slot = i; } } if (equip_slot == -1) { // if empty not found, use just first for (int i = 0; i < MAX_EQUIPPED; i++) { if (slot_type[i] == items->items[inventory[CARRIED][slot].item].type) { equip_slot = i; break; } } } if (equip_slot != -1) { if (requirementsMet(inventory[CARRIED][slot].item)) { stack = click(position); if( inventory[EQUIPMENT][equip_slot].item == stack.item) { // Merge the stacks add(stack, EQUIPMENT, equip_slot, false); } else if( inventory[EQUIPMENT][equip_slot].item == 0) { // Drop the stack inventory[EQUIPMENT][equip_slot] = stack; } else { if( inventory[CARRIED][slot].item == 0) { // Don't forget this slot may have been emptied by the click() // Swap the two stacks itemReturn( inventory[EQUIPMENT][equip_slot]); } else { // Drop the equipped item anywhere add( inventory[EQUIPMENT][equip_slot]); } inventory[EQUIPMENT][equip_slot] = stack; } updateEquipment( equip_slot); items->playSound(inventory[EQUIPMENT][equip_slot].item); } } else fprintf(stderr, "Can't find equip slot, corresponding to type %s\n", items->items[inventory[CARRIED][slot].item].type.c_str()); } drag_prev_src = -1; } /** * Insert item into first available carried slot, preferably in the optionnal specified slot * * @param ItemStack Stack of items * @param area Area number where it will try to store the item * @param slot Slot number where it will try to store the item */ void MenuInventory::add(ItemStack stack, int area, int slot, bool play_sound) { if (stack.quantity < 1) return; if (play_sound) items->playSound(stack.item); if (stack.item != 0) { if (area < 0) { area = CARRIED; } int max_quantity = items->items[stack.item].max_quantity; if (slot > -1 && inventory[area][slot].item != 0 && inventory[area][slot].item != stack.item) { // the proposed slot isn't available, search for another one slot = -1; } if (area == CARRIED) { // first search of stack to complete if the item is stackable if (slot == -1 && max_quantity > 1) { int i = 0; while (i < MAX_CARRIED && (inventory[area][i].item != stack.item || inventory[area][i].quantity >= max_quantity)) ++i; if (i < MAX_CARRIED) slot = i; } // then an empty slot if (slot == -1) { int i = 0; while (inventory[area][i].item != 0 && i < MAX_CARRIED) i++; if (i < MAX_CARRIED) slot = i; } } if (slot != -1) { // Add int quantity_added = min( stack.quantity, max_quantity - inventory[area][slot].quantity); inventory[area][slot].item = stack.item; inventory[area][slot].quantity += quantity_added; stack.quantity -= quantity_added; // Add back the remaining if( stack.quantity > 0) { if( drag_prev_src > -1) { itemReturn( stack); } else { add(stack, CARRIED, -1, false); } } } else { // No available slot, drop drop_stack.item = stack.item; drop_stack.quantity = stack.quantity; } } drag_prev_src = -1; } /** * Remove one given item from the player's inventory. */ void MenuInventory::remove(int item) { if( !inventory[CARRIED].remove(item)) { inventory[EQUIPMENT].remove(item); applyEquipment(inventory[EQUIPMENT].storage); } } /** * Remove an equipped item from the player's inventory. */ void MenuInventory::removeEquipped(int item) { inventory[EQUIPMENT].remove(item); applyEquipment(inventory[EQUIPMENT].storage); } /** * Add currency item */ void MenuInventory::addCurrency(int count) { ItemStack stack; stack.item = CURRENCY_ID; stack.quantity = count; add(stack, CARRIED, -1, false); } /** * Remove currency item */ void MenuInventory::removeCurrency(int count) { for (int i=0; i<count; i++) { inventory[CARRIED].remove(CURRENCY_ID); } } /** * Count the number of currency items in the inventory */ int MenuInventory::getCurrency() { return getItemCountCarried(CURRENCY_ID); } /** * Check if there is enough currency to buy the given stack, and if so remove it from the current total and add the stack. * (Handle the drop into the equipment area, but add() don't handle it well in all circonstances. MenuManager::logic() allow only into the carried area.) */ bool MenuInventory::buy(ItemStack stack, int tab) { int value_each; if (tab == VENDOR_BUY) value_each = items->items[stack.item].price; else value_each = items->items[stack.item].getSellPrice(); int count = value_each * stack.quantity; if( getCurrency() >= count) { removeCurrency(count); items->playSound(CURRENCY_ID); return true; } else { return false; } } /** * Similar to sell(), but for use with stash */ bool MenuInventory::stashAdd(ItemStack stack) { // items that have no price cannot be stored if (items->items[stack.item].price == 0) return false; drag_prev_src = -1; return true; } /** * Sell a specific stack of items */ bool MenuInventory::sell(ItemStack stack) { // can't sell currency if (stack.item == CURRENCY_ID) return false; // items that have no price cannot be sold if (items->items[stack.item].price == 0) return false; int value_each = items->items[stack.item].getSellPrice(); int value = value_each * stack.quantity; addCurrency(value); items->playSound(CURRENCY_ID); drag_prev_src = -1; return true; } /** * Cannot pick up new items if the inventory is full. * Full means no more carrying capacity (equipped capacity is ignored) */ bool MenuInventory::full(ItemStack stack) { return inventory[CARRIED].full(stack); } /** * An alternative version of the above full() function * This one only checks for a single item * It's primarily used when checking LootManager pickups */ bool MenuInventory::full(int item) { return inventory[CARRIED].full(item); } /** * Get the number of the specified item carried (not equipped) */ int MenuInventory::getItemCountCarried(int item) { return inventory[CARRIED].count(item); } /** * Check to see if the given item is equipped */ bool MenuInventory::isItemEquipped(int item) { return inventory[EQUIPMENT].contain(item); } /** * Check requirements on an item */ bool MenuInventory::requirementsMet(int item) { if (items->items[item].req_stat == REQUIRES_PHYS) { return (stats->get_physical() >= items->items[item].req_val); } else if (items->items[item].req_stat == REQUIRES_MENT) { return (stats->get_mental() >= items->items[item].req_val); } else if (items->items[item].req_stat == REQUIRES_OFF) { return (stats->get_offense() >= items->items[item].req_val); } else if (items->items[item].req_stat == REQUIRES_DEF) { return (stats->get_defense() >= items->items[item].req_val); } // otherwise there is no requirement, so it is usable. return true; } void MenuInventory::updateEquipment(int slot) { if (slot == -1) { //FIXME What todo here //return; changed_equipment = true; } else if (slot_type[slot] != "artifact") { changed_equipment = true; } else { changed_artifact = true; } } /** * Given the equipped items, calculate the hero's stats */ void MenuInventory::applyEquipment(ItemStack *equipped) { const vector<Item> &pc_items = items->items; int item_id; // calculate bonuses to basic stats, added by items bool checkRequired = true; while(checkRequired) { checkRequired = false; stats->offense_additional = stats->defense_additional = stats->physical_additional = stats->mental_additional = 0; for (int i = 0; i < MAX_EQUIPPED; i++) { item_id = equipped[i].item; const Item &item = pc_items[item_id]; unsigned bonus_counter = 0; while (bonus_counter < item.bonus_stat.size() && item.bonus_stat[bonus_counter] != "") { if (item.bonus_stat[bonus_counter] == "offense") stats->offense_additional += item.bonus_val[bonus_counter]; else if (item.bonus_stat[bonus_counter] == "defense") stats->defense_additional += item.bonus_val[bonus_counter]; else if (item.bonus_stat[bonus_counter] == "physical") stats->physical_additional += item.bonus_val[bonus_counter]; else if (item.bonus_stat[bonus_counter] == "mental") stats->mental_additional += item.bonus_val[bonus_counter]; else if (item.bonus_stat[bonus_counter] == "all basic stats") { stats->offense_additional += item.bonus_val[bonus_counter]; stats->defense_additional += item.bonus_val[bonus_counter]; stats->physical_additional += item.bonus_val[bonus_counter]; stats->mental_additional += item.bonus_val[bonus_counter]; } bonus_counter++; } } // calculate bonuses. added by item sets vector<int> set; vector<int> quantity; vector<int>::iterator it; for (int i=0; i<MAX_EQUIPPED; i++) { item_id = equipped[i].item; it = find(set.begin(), set.end(), items->items[item_id].set); if (items->items[item_id].set > 0 && it != set.end()) { quantity[distance(set.begin(), it)] += 1; } else if (items->items[item_id].set > 0) { set.push_back(items->items[item_id].set); quantity.push_back(1); } } // calculate bonuses to basic stats, added by item sets ItemSet temp_set; for (unsigned k=0; k<set.size(); k++) { temp_set = items->item_sets[set[k]]; for (unsigned bonus_counter=0; bonus_counter<temp_set.bonus.size(); bonus_counter++) { if (temp_set.bonus[bonus_counter].requirement != quantity[k]) continue; if (temp_set.bonus[bonus_counter].bonus_stat == "offense") stats->offense_additional += temp_set.bonus[bonus_counter].bonus_val; else if (temp_set.bonus[bonus_counter].bonus_stat == "defense") stats->defense_additional += temp_set.bonus[bonus_counter].bonus_val; else if (temp_set.bonus[bonus_counter].bonus_stat == "physical") stats->physical_additional += temp_set.bonus[bonus_counter].bonus_val; else if (temp_set.bonus[bonus_counter].bonus_stat == "mental") stats->mental_additional += temp_set.bonus[bonus_counter].bonus_val; else if (temp_set.bonus[bonus_counter].bonus_stat == "all basic stats") { stats->offense_additional += temp_set.bonus[bonus_counter].bonus_val; stats->defense_additional += temp_set.bonus[bonus_counter].bonus_val; stats->physical_additional += temp_set.bonus[bonus_counter].bonus_val; stats->mental_additional += temp_set.bonus[bonus_counter].bonus_val; } } } // check that each equipped item fit requirements for (int i = 0; i < MAX_EQUIPPED; i++) { if (!requirementsMet(equipped[i].item)) { add(equipped[i]); equipped[i].item = 0; equipped[i].quantity = 0; checkRequired = true; } } } // defaults for (unsigned i=0; i<stats->powers_list_items.size(); ++i) { int id = stats->powers_list_items[i]; // stats->hp > 0 is hack to keep on_death revive passives working if (powers->powers[id].passive && stats->hp > 0) stats->effects.removeEffectPassive(id); } stats->powers_list_items.clear(); // reset wielding vars stats->equip_flags.clear(); // remove all effects and bonuses added by items stats->effects.clearItemEffects(); applyItemStats(equipped); applyItemSetBonuses(equipped); // update stat display stats->refresh_stats = true; } void MenuInventory::applyItemStats(ItemStack *equipped) { const vector<Item> &pc_items = items->items; // reset additional values stats->dmg_melee_min_add = stats->dmg_melee_max_add = 0; stats->dmg_ment_min_add = stats->dmg_ment_max_add = 0; stats->dmg_ranged_min_add = stats->dmg_ranged_max_add = 0; stats->absorb_min_add = stats->absorb_max_add = 0; // apply stats from all items for (int i=0; i<MAX_EQUIPPED; i++) { int item_id = equipped[i].item; const Item &item = pc_items[item_id]; // apply base stats stats->dmg_melee_min_add += item.dmg_melee_min; stats->dmg_melee_max_add += item.dmg_melee_max; stats->dmg_ranged_min_add += item.dmg_ranged_min; stats->dmg_ranged_max_add += item.dmg_ranged_max; stats->dmg_ment_min_add += item.dmg_ment_min; stats->dmg_ment_max_add += item.dmg_ment_max; // apply power mod if (find(item.equip_flags.begin(), item.equip_flags.end(), "melee") != item.equip_flags.end()) { if (item.power_mod != 0) { stats->melee_weapon_power = item.power_mod; } } if (find(item.equip_flags.begin(), item.equip_flags.end(), "ranged") != item.equip_flags.end()) { if (item.power_mod != 0) { stats->ranged_weapon_power = item.power_mod; } } if (find(item.equip_flags.begin(), item.equip_flags.end(), "mental") != item.equip_flags.end()) { if (item.power_mod != 0) { stats->mental_weapon_power = item.power_mod; } } // set equip flags for (unsigned j=0; j<item.equip_flags.size(); ++j) { stats->equip_flags.insert(item.equip_flags[j]); } // apply absorb bonus stats->absorb_min_add += item.abs_min; stats->absorb_max_add += item.abs_max; // apply various bonuses unsigned bonus_counter = 0; while (bonus_counter < item.bonus_stat.size() && item.bonus_stat[bonus_counter] != "") { std::string id = item.bonus_stat[bonus_counter]; if (powers->effects.find(id) != powers->effects.end()) stats->effects.addEffect(id, powers->effects[id].icon, 0, item.bonus_val[bonus_counter], powers->effects[id].type, powers->effects[id].animation, powers->effects[id].additive, true, -1, powers->effects[id].render_above, 0, SOURCE_TYPE_HERO); bonus_counter++; } // add item powers if (item.power > 0) { stats->powers_list_items.push_back(item.power); if (stats->effects.triggered_others) powers->activateSinglePassive(stats,item.power); } } } void MenuInventory::applyItemSetBonuses(ItemStack *equipped) { // calculate bonuses. added by item sets vector<int> set; vector<int> quantity; vector<int>::iterator it; for (int i=0; i<MAX_EQUIPPED; i++) { int item_id = equipped[i].item; it = find(set.begin(), set.end(), items->items[item_id].set); if (items->items[item_id].set > 0 && it != set.end()) { quantity[distance(set.begin(), it)] += 1; } else if (items->items[item_id].set > 0) { set.push_back(items->items[item_id].set); quantity.push_back(1); } } // apply item set bonuses ItemSet temp_set; for (unsigned k=0; k<set.size(); k++) { temp_set = items->item_sets[set[k]]; unsigned bonus_counter = 0; for (bonus_counter=0; bonus_counter<temp_set.bonus.size(); bonus_counter++) { if (temp_set.bonus[bonus_counter].requirement != quantity[k]) continue; std::string id = temp_set.bonus[bonus_counter].bonus_stat; if (powers->effects.find(id) != powers->effects.end()) stats->effects.addEffect(id, powers->effects[id].icon, 0, temp_set.bonus[bonus_counter].bonus_val, powers->effects[id].type, powers->effects[id].animation, powers->effects[id].additive, true, -1, powers->effects[id].render_above, 0, SOURCE_TYPE_HERO); } } } int MenuInventory::getEquippedCount() { return (int)equipped_area.size(); } int MenuInventory::getCarriedRows() { return carried_rows; } void MenuInventory::clearHighlight() { inventory[EQUIPMENT].highlightClear(); inventory[CARRIED].highlightClear(); } MenuInventory::~MenuInventory() { SDL_FreeSurface(background); delete closeButton; } �������flare-engine-0.19/src/MenuInventory.h���������������������������������������������������������������0000664�0000000�0000000�00000005445�12247171015�0017571�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuInventory */ #pragma once #ifndef MENU_INVENTORY_H #define MENU_INVENTORY_H #include "CommonIncludes.h" #include "MenuItemStorage.h" #include "WidgetLabel.h" class StatBlock; class WidgetButton; const int EQUIPMENT = 0; const int CARRIED = 1; class MenuInventory : public Menu { private: StatBlock *stats; void loadGraphics(); int areaOver(Point position); void updateEquipment(int slot); WidgetButton *closeButton; int MAX_EQUIPPED; int MAX_CARRIED; // label and widget positions Point close_pos; LabelInfo title; LabelInfo currency_lbl; SDL_Rect help_pos; int carried_cols; int carried_rows; SDL_Color color_normal; SDL_Color color_high; public: MenuInventory(StatBlock *stats); ~MenuInventory(); void update(); void logic(); void render(); TooltipData checkTooltip(Point position); ItemStack click(Point position); void itemReturn(ItemStack stack); void drop(Point position, ItemStack stack); void activate(Point position); void add( ItemStack stack, int area = CARRIED, int slot = -1, bool play_sound = true); void remove(int item); void removeEquipped(int item); void addCurrency(int count); void removeCurrency(int count); int getCurrency(); bool buy(ItemStack stack, int tab); bool sell(ItemStack stack); bool stashAdd(ItemStack stack); bool full(ItemStack stack); bool full(int item); int getItemCountCarried(int item); bool isItemEquipped(int item); bool requirementsMet(int item); void applyEquipment(ItemStack *equipped); void applyItemStats(ItemStack *equipped); void applyItemSetBonuses(ItemStack *equipped); int getEquippedCount(); int getCarriedRows(); void clearHighlight(); SDL_Rect carried_area; std::vector<SDL_Rect> equipped_area; std::vector<std::string> slot_type; std::vector<std::string> slot_desc; MenuItemStorage inventory[2]; int currency; int drag_prev_src; // the following two are separate because artifacts don't display on the hero. // so we only update the hero sprites when non-artifact changes occur. bool changed_equipment; bool changed_artifact; std::string log_msg; ItemStack drop_stack; TabList tablist; }; #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuItemStorage.cpp�����������������������������������������������������������0000664�0000000�0000000�00000013012�12247171015�0020337�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuItemStorage */ #include "MenuItemStorage.h" #include "Settings.h" #include "SharedResources.h" #include "SharedGameResources.h" using namespace std; MenuItemStorage::MenuItemStorage() : icons(NULL) , grid_area() , nb_cols(0) , slot_type() , drag_prev_slot(-1) , slots() , highlight(NULL) , highlight_image(NULL) { } void MenuItemStorage::init(int _slot_number, SDL_Rect _area, int _icon_size, int _nb_cols) { ItemStorage::init( _slot_number); icons = items->getIcons(); grid_area = _area; for (int i = 0; i < _slot_number; i++) { WidgetSlot *slot = new WidgetSlot(icons); slots.push_back(slot); } nb_cols = _nb_cols; highlight = new bool[_slot_number]; for (int i=0; i<_slot_number; i++) { highlight[i] = false; slots[i]->pos.x = grid_area.x + (i % nb_cols * _icon_size); slots[i]->pos.y = grid_area.y + (i / nb_cols * _icon_size); slots[i]->pos.h = slots[i]->pos.w = _icon_size; } loadGraphics(); } /** * Overloaded function for case, if slot positions are predefined */ void MenuItemStorage::init(int _slot_number, vector<SDL_Rect> _area, vector<string> _slot_type) { ItemStorage::init( _slot_number); icons = items->getIcons(); for (int i = 0; i < _slot_number; i++) { WidgetSlot *slot = new WidgetSlot(icons); slot->pos = _area[i]; slots.push_back(slot); } nb_cols = 0; slot_type = _slot_type; highlight = new bool[_slot_number]; for (int i=0; i<_slot_number; i++) { highlight[i] = false; } loadGraphics(); } void MenuItemStorage::loadGraphics() { highlight_image = loadGraphicSurface("images/menus/attention_glow.png", "Couldn't load icon highlight image"); } void MenuItemStorage::render() { for (int i=0; i<slot_number; i++) { if (storage[i].item > 0) { slots[i]->setIcon(items->items[storage[i].item].icon); slots[i]->setAmount(storage[i].quantity, items->items[storage[i].item].max_quantity); } else { slots[i]->setIcon(-1); } slots[i]->render(); if (highlight[i]) renderHighlight(slots[i]->pos.x, slots[i]->pos.y, slots[i]->pos.w); } } void MenuItemStorage::renderHighlight(int x, int y, int _icon_size) { if (_icon_size == ICON_SIZE) { SDL_Rect dest; dest.x = x; dest.y = y; SDL_BlitSurface(highlight_image,NULL,screen,&dest); } } int MenuItemStorage::slotOver(Point position) { if (isWithin(grid_area, position) && nb_cols > 0) { return (position.x - grid_area.x) / slots[0]->pos.w + (position.y - grid_area.y) / slots[0]->pos.w * nb_cols; } else if (nb_cols == 0) { for (unsigned int i=0; i<slots.size(); i++) { if (isWithin(slots[i]->pos, position)) return i; } } return -1; } TooltipData MenuItemStorage::checkTooltip(Point position, StatBlock *stats, int context) { TooltipData tip; int slot = slotOver(position); if (slot > -1 && storage[slot].item > 0) { return items->getTooltip(storage[slot], stats, context); } return tip; } ItemStack MenuItemStorage::click(Point position) { ItemStack item; drag_prev_slot = slotOver(position); if (drag_prev_slot == -1) { // FIXME: What if mouse is over one slot and focused is another slot for (unsigned int i=0; i<slots.size(); i++) { if (slots[i]->in_focus) { drag_prev_slot = i; break; } } } if (drag_prev_slot > -1) { item = storage[drag_prev_slot]; if (inpt->pressing[SHIFT] || NO_MOUSE) { item.quantity = 1; } substract( drag_prev_slot, item.quantity); return item; } else { item.item = 0; item.quantity = 0; return item; } } void MenuItemStorage::itemReturn(ItemStack stack) { add( stack, drag_prev_slot); drag_prev_slot = -1; } /** * Sort storage array, so items order matches slots order */ void MenuItemStorage::fillEquipmentSlots() { // create temporary arrays int *equip_item = new int[slot_number]; int *equip_quantity = new int[slot_number];; // initialize arrays for (int i=0; i<slot_number; i++) { equip_item[i] = storage[i].item; equip_quantity[i] = storage[i].quantity; } // clean up storage[] for (int i=0; i<slot_number; i++) { storage[i].item = 0; storage[i].quantity = 0; } // fill slots with items for (int i=0; i<slot_number; i++) { for (int j=0; j<slot_number; j++) { // search for empty slot with needed type. If item is not NULL, put it there if (items->items[equip_item[i]].type == slot_type[j] && equip_item[i] > 0 && storage[j].item == 0) { storage[j].item = equip_item[i]; storage[j].quantity = (equip_quantity[i] > 0) ? equip_quantity[i] : 1; break; } } } delete [] equip_item; delete [] equip_quantity; } void MenuItemStorage::highlightMatching(string type) { for (int i=0; i<slot_number; i++) { if (slot_type[i] == type) highlight[i] = true; } } void MenuItemStorage::highlightClear() { for (int i=0; i<slot_number; i++) { highlight[i] = false; } } MenuItemStorage::~MenuItemStorage() { delete[] highlight; SDL_FreeSurface(highlight_image); for (unsigned i=0; i<slots.size(); i++) delete slots[i]; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuItemStorage.h�������������������������������������������������������������0000664�0000000�0000000�00000003375�12247171015�0020017�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuItemStorage */ #pragma once #ifndef MENU_ITEM_STORAGE_H #define MENU_ITEM_STORAGE_H #include "CommonIncludes.h" #include "ItemManager.h" #include "ItemStorage.h" #include "WidgetSlot.h" class TooltipData; class MenuItemStorage : public ItemStorage { protected: SDL_Surface *icons; void loadGraphics(); void renderHighlight(int x, int y, int _icon_size); SDL_Rect grid_area; int nb_cols; public: MenuItemStorage(); void init(int _slot_number, SDL_Rect _area, int icon_size, int nb_cols); void init(int _slot_number, std::vector<SDL_Rect> _area, std::vector<std::string> _slot_type); ~MenuItemStorage(); // rendering void render(); int slotOver(Point position); TooltipData checkTooltip(Point position, StatBlock *stats, int context); ItemStack click(Point position); void itemReturn(ItemStack stack); void fillEquipmentSlots(); void highlightMatching(std::string type); void highlightClear(); std::vector<std::string> slot_type; int drag_prev_slot; std::vector<WidgetSlot*> slots; bool * highlight; SDL_Surface * highlight_image; }; #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuLog.cpp�������������������������������������������������������������������0000664�0000000�0000000�00000013777�12247171015�0016657�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuLog */ #include "FileParser.h" #include "Menu.h" #include "MenuLog.h" #include "ModManager.h" #include "Settings.h" #include "UtilsParsing.h" #include "WidgetButton.h" #include "WidgetScrollBox.h" #include "WidgetTabControl.h" using namespace std; MenuLog::MenuLog() { visible = false; tab_content_indent = 4; // Load config settings FileParser infile; if(infile.open("menus/log.txt")) { while(infile.next()) { infile.val = infile.val + ','; if(infile.key == "caption") { title = eatLabelInfo(infile.val); } else if(infile.key == "close") { close_pos.x = eatFirstInt(infile.val,','); close_pos.y = eatFirstInt(infile.val,','); } else if(infile.key == "tab_area") { tab_area.x = eatFirstInt(infile.val,','); tab_area.y = eatFirstInt(infile.val,','); tab_area.w = eatFirstInt(infile.val,','); tab_area.h = eatFirstInt(infile.val,','); } } infile.close(); } // Store the amount of displayed log messages on each log, and the maximum. for (unsigned i=0; i<LOG_TYPE_COUNT; i++) { log_count[i] = 0; msg_buffer[i] = new WidgetScrollBox(tab_area.w,tab_area.h); msg_buffer[i]->line_height = font->getLineHeight(); tablist.add(msg_buffer[i]); } // Initialize the tab control. tabControl = new WidgetTabControl(LOG_TYPE_COUNT); // Define the header. tabControl->setTabTitle(LOG_TYPE_MESSAGES, msg->get("Notes")); tabControl->setTabTitle(LOG_TYPE_QUESTS, msg->get("Quests")); font->setFont("font_regular"); paragraph_spacing = font->getLineHeight()/2; background = loadGraphicSurface("images/menus/log.png"); closeButton = new WidgetButton("images/menus/buttons/button_x.png"); color_normal = font->getColor("menu_normal"); } void MenuLog::update() { tabControl->setMainArea(window_area.x + tab_area.x, window_area.y + tab_area.y, tab_area.w, tab_area.h); tabControl->updateHeader(); closeButton->pos.x = window_area.x + close_pos.x; closeButton->pos.y = window_area.y + close_pos.y; for (unsigned i=0; i<LOG_TYPE_COUNT; i++) { msg_buffer[i]->pos.x = window_area.x+tab_area.x; msg_buffer[i]->pos.y = window_area.y+tab_area.y+tabControl->getTabHeight(); } } /** * Perform one frame of logic. */ void MenuLog::logic() { if(!visible) return; if (NO_MOUSE) { tablist.logic(); } // make shure keyboard navigation leads us to correct tab for (unsigned i = 0; i < LOG_TYPE_COUNT; i++) { if (msg_buffer[i]->in_focus) { tabControl->setActiveTab(i); break; } } if (closeButton->checkClick()) { visible = false; snd->play(sfx_close); } tabControl->logic(); int active_log = tabControl->getActiveTab(); msg_buffer[active_log]->logic(); } /** * Render graphics for this frame when the menu is open */ void MenuLog::render() { if (!visible) return; SDL_Rect src,dest; // Background. dest = window_area; src.x = 0; src.y = 0; src.w = window_area.w; src.h = window_area.h; SDL_BlitSurface(background, &src, screen, &window_area); // Close button. closeButton->render(); // Text overlay. if (!title.hidden) { WidgetLabel label; label.set(window_area.x+title.x, window_area.y+title.y, title.justify, title.valign, msg->get("Log"), color_normal, title.font_style); label.render(); } // Tab control. tabControl->render(); // Display latest log messages for the active tab. int total_size = tab_content_indent; int active_log = tabControl->getActiveTab(); if (msg_buffer[active_log]->update) { msg_buffer[active_log]->refresh(); font->setFont("font_regular"); for (unsigned int i = log_msg[active_log].size(); i > 0; i--) { int widthLimit = tabControl->getContentArea().w; Point size = font->calc_size(log_msg[active_log][i-1], widthLimit); font->renderShadowed(log_msg[active_log][i-1], tab_content_indent, total_size, JUSTIFY_LEFT, msg_buffer[active_log]->contents, widthLimit, color_normal); total_size+=size.y+paragraph_spacing; } } msg_buffer[active_log]->update = false; msg_buffer[active_log]->render(); } void MenuLog::refresh(int log_type) { int y = tab_content_indent; font->setFont("font_regular"); for (unsigned int i=0; i<log_msg[log_type].size(); i++) { int widthLimit = tabControl->getContentArea().w; Point size = font->calc_size(log_msg[log_type][i], widthLimit); y+=size.y+paragraph_spacing; } y+=tab_content_indent; msg_buffer[log_type]->resize(y); } /** * Add a new message to the log. */ void MenuLog::add(const string& s, int log_type) { // If we have too many messages, remove the oldest ones while (log_msg[log_type].size() >= MAX_LOG_MESSAGES) { log_msg[log_type].erase(log_msg[log_type].begin()); } // Add the new message. log_msg[log_type].push_back(s); msg_buffer[log_type]->update = true; refresh(log_type); log_count[log_type]++; } /** * Remove log message with the given identifier. */ void MenuLog::remove(int msg_index, int log_type) { log_msg[log_type][msg_index].erase(); msg_buffer[log_type]->update = true; refresh(log_type); log_count[log_type]--; } void MenuLog::clear(int log_type) { log_count[log_type] = 0; log_msg[log_type].clear(); msg_buffer[log_type]->update = true; refresh(log_type); } void MenuLog::clear() { for (unsigned i=0; i<LOG_TYPE_COUNT; i++) { clear(i); } } MenuLog::~MenuLog() { for (unsigned i=0; i<LOG_TYPE_COUNT; i++) { log_count[i] = 0; delete msg_buffer[i]; } SDL_FreeSurface(background); delete closeButton; delete tabControl; } �flare-engine-0.19/src/MenuLog.h���������������������������������������������������������������������0000664�0000000�0000000�00000003362�12247171015�0016311�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuLog */ #pragma once #ifndef MENU_LOG_H #define MENU_LOG_H #include "CommonIncludes.h" #include "Utils.h" #include "WidgetLabel.h" class WidgetButton; class WidgetScrollBox; class WidgetTabControl; const unsigned int MAX_LOG_MESSAGES = 32; const unsigned LOG_TYPE_COUNT = 2; const int LOG_TYPE_QUESTS = 0; const int LOG_TYPE_MESSAGES = 1; class MenuLog : public Menu { private: WidgetButton *closeButton; WidgetTabControl *tabControl; void loadGraphics(); std::vector<std::string> log_msg[LOG_TYPE_COUNT]; WidgetScrollBox *msg_buffer[LOG_TYPE_COUNT]; int log_count[LOG_TYPE_COUNT]; std::string tab_labels[LOG_TYPE_COUNT]; SDL_Rect tab_rect[LOG_TYPE_COUNT]; int paragraph_spacing; LabelInfo title; Point close_pos; int tab_content_indent; SDL_Rect tab_area; SDL_Color tab_bg; SDL_Color color_normal; public: MenuLog(); ~MenuLog(); void update(); void logic(); void render(); void refresh(int log_type); void add(const std::string& s, int log_type); void remove(int msg_index, int log_type); void clear(int log_type); void clear(); TabList tablist; }; #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuManager.cpp���������������������������������������������������������������0000664�0000000�0000000�00000122335�12247171015�0017477�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuManager */ #include "FileParser.h" #include "UtilsParsing.h" #include "UtilsFileSystem.h" #include "Menu.h" #include "MenuManager.h" #include "MenuActionBar.h" #include "MenuCharacter.h" #include "MenuStatBar.h" #include "MenuHUDLog.h" #include "MenuInventory.h" #include "MenuMiniMap.h" #include "MenuNPCActions.h" #include "MenuPowers.h" #include "MenuEnemy.h" #include "MenuVendor.h" #include "MenuTalker.h" #include "MenuExit.h" #include "MenuActiveEffects.h" #include "MenuStash.h" #include "MenuLog.h" #include "ModManager.h" #include "NPC.h" #include "SharedResources.h" #include "WidgetTooltip.h" #include "SharedGameResources.h" MenuManager::MenuManager(StatBlock *_stats) : icons(NULL) , stats(_stats) , tip_buf() , keyb_tip_buf_vendor() , keyb_tip_buf_stash() , keyb_tip_buf_pow() , keyb_tip_buf_inv() , keyb_tip_buf_act() , key_lock(false) , mouse_dragging(0) , keyboard_dragging(0) , drag_stack() , drag_power(0) , drag_src(0) , done(false) , act_drag_hover(false) , keydrag_pos(Point()) /*std::vector<Menu*> menus;*/ , inv(NULL) , pow(NULL) , chr(NULL) , log(NULL) , hudlog(NULL) , act(NULL) , hp(NULL) , mp(NULL) , xp(NULL) , tip(NULL) , mini(NULL) , npc(NULL) , enemy(NULL) , vendor(NULL) , talker(NULL) , exit(NULL) , effects(NULL) , stash(NULL) , pause(false) , menus_open(false) , drop_stack() { loadIcons(); hp = new MenuStatBar("hp"); menus.push_back(hp); // menus[0] mp = new MenuStatBar("mp"); menus.push_back(mp); // menus[1] xp = new MenuStatBar("xp"); menus.push_back(xp); // menus[2] effects = new MenuActiveEffects(icons); menus.push_back(effects); // menus[3] hudlog = new MenuHUDLog(); menus.push_back(hudlog); // menus[4] act = new MenuActionBar(pc, icons); menus.push_back(act); // menus[5] enemy = new MenuEnemy(); menus.push_back(enemy); // menus[6] vendor = new MenuVendor(stats); menus.push_back(vendor); // menus[7] talker = new MenuTalker(this); menus.push_back(talker); // menus[8] exit = new MenuExit(); menus.push_back(exit); // menus[9] mini = new MenuMiniMap(); menus.push_back(mini); // menus[10] chr = new MenuCharacter(stats); menus.push_back(chr); // menus[11] inv = new MenuInventory(stats); menus.push_back(inv); // menus[12] pow = new MenuPowers(stats, icons, act); menus.push_back(pow); // menus[13] log = new MenuLog(); menus.push_back(log); // menus[14] stash = new MenuStash(stats); menus.push_back(stash); // menus[15] npc = new MenuNPCActions(); menus.push_back(npc); // menus[16] tip = new WidgetTooltip(); // Load the menu layout and sound effects from menus/menus.txt FileParser infile; if (infile.open("menus/menus.txt")) { int menu_index = -1; while (infile.next()) { if (infile.key == "id") { /* finalize previously parsed menu */ if (menu_index != -1) menus[menu_index]->align(); if (infile.val == "hp") menu_index = 0; else if (infile.val == "mp") menu_index = 1; else if (infile.val == "xp") menu_index = 2; else if (infile.val == "effects") menu_index = 3; else if (infile.val == "hudlog") menu_index = 4; else if (infile.val == "actionbar") menu_index = 5; else if (infile.val == "enemy") menu_index = 6; else if (infile.val == "vendor") menu_index = 7; else if (infile.val == "talker") menu_index = 8; else if (infile.val == "exit") menu_index = 9; else if (infile.val == "minimap") menu_index = 10; else if (infile.val == "character") menu_index = 11; else if (infile.val == "inventory") menu_index = 12; else if (infile.val == "powers") menu_index = 13; else if (infile.val == "log") menu_index = 14; else if (infile.val == "stash") menu_index = 15; else if (infile.val == "npc") menu_index = 16; else menu_index = -1; } if (menu_index == -1) continue; if (infile.key == "layout") { infile.val = infile.val + ','; int x = eatFirstInt(infile.val, ','); int y = eatFirstInt(infile.val, ','); int w = eatFirstInt(infile.val, ','); int h = eatFirstInt(infile.val, ','); menus[menu_index]->window_area.x = x; menus[menu_index]->window_area.y = y; menus[menu_index]->window_area.w = w; menus[menu_index]->window_area.h = h; } else if (infile.key == "align") { menus[menu_index]->alignment = infile.val; } else if (infile.key == "soundfx_open") { menus[menu_index]->sfx_open = snd->load(infile.val, "MenuManager open tab"); } else if (infile.key == "soundfx_close") { menus[menu_index]->sfx_close = snd->load(infile.val, "MenuManager close tab"); } } infile.close(); } // Some menus need to be updated to apply their new dimensions act->update(); vendor->update(); vendor->buyback_stock.init(NPC_VENDOR_MAX_STOCK); talker->update(); exit->update(); chr->update(); inv->update(); pow->update(); log->update(); stash->update(); pause = false; mouse_dragging = false; keyboard_dragging = false; drag_stack.item = 0; drag_stack.quantity = 0; drag_power = 0; drag_src = 0; drop_stack.item = 0; drop_stack.quantity = 0; done = false; closeAll(); // make sure all togglable menus start closed } /** * Icon set shared by all menus */ void MenuManager::loadIcons() { icons = loadGraphicSurface("images/icons/icons.png", "Couldn't load icons"); } void MenuManager::renderIcon(int icon_id, int x, int y) { SDL_Rect src; SDL_Rect dest; dest.x = x; dest.y = y; src.w = src.h = dest.w = dest.h = ICON_SIZE; int columns = icons->w / ICON_SIZE; src.x = (icon_id % columns) * ICON_SIZE; src.y = (icon_id / columns) * ICON_SIZE; SDL_BlitSurface(icons, &src, screen, &dest); } void MenuManager::handleKeyboardNavigation() { // switching between menus if (drag_src == 0) { const int VENDOR_ROWS = vendor->getRowsCount() * 2; //Vendor Menu has two tabs const int STASH_ROWS = stash->getRowsCount(); const int INVENTORY_ROWS = inv->getCarriedRows(); const int EQUIPPED_SLOTS = inv->getEquippedCount(); // left -> right if (inv->visible || pow->visible) { if (vendor->visible && vendor->tablist.getCurrent() != -1 && !vendor->tablist.isLocked()) { if (((vendor->tablist.getCurrent() + 1) % (vendor->tablist.size()/VENDOR_ROWS) == 0) && inpt->pressing[RIGHT] && !inpt->lock[RIGHT]) { inpt->lock[RIGHT] = true; vendor->tablist.lock(); vendor->tablist.defocus(); inv->tablist.unlock(); inv->tablist.getNext(); } } else if (stash->visible && stash->tablist.getCurrent() != -1 && !stash->tablist.isLocked()) { if (((stash->tablist.getCurrent() + 1) % (stash->tablist.size()/STASH_ROWS) == 0) && inpt->pressing[RIGHT] && !inpt->lock[RIGHT]) { inpt->lock[RIGHT] = true; stash->tablist.lock(); stash->tablist.defocus(); inv->tablist.unlock(); inv->tablist.getNext(); } } else if (chr->visible && chr->tablist.getCurrent() != -1 && !chr->tablist.isLocked()) { if ((chr->tablist.getCurrent() + 1 == (int)chr->tablist.size()) && inpt->pressing[RIGHT] && !inpt->lock[RIGHT]) { inpt->lock[RIGHT] = true; chr->tablist.lock(); chr->tablist.defocus(); if (inv->visible) { inv->tablist.unlock(); inv->tablist.getNext(); } else if (pow->visible) { pow->tablist.unlock(); pow->tablist.getNext(); } } } else if (log->visible && log->tablist.getCurrent() != -1 && !log->tablist.isLocked()) { if (inpt->pressing[RIGHT] && !inpt->lock[RIGHT]) { inpt->lock[RIGHT] = true; log->tablist.lock(); log->tablist.defocus(); if (inv->visible) { inv->tablist.unlock(); inv->tablist.getNext(); } else if (pow->visible) { pow->tablist.unlock(); pow->tablist.getNext(); } } } } // right -> left if (vendor->visible || stash->visible || chr->visible || log->visible) { if (inv->visible && (inv->tablist.getCurrent() - EQUIPPED_SLOTS) >= 0 && !inv->tablist.isLocked()) { if (((inv->tablist.getCurrent() - EQUIPPED_SLOTS + 1) % ((inv->tablist.size() - EQUIPPED_SLOTS)/INVENTORY_ROWS) == 1) && inpt->pressing[LEFT] && !inpt->lock[LEFT]) { inpt->lock[LEFT] = true; inv->tablist.lock(); inv->tablist.defocus(); if (stash->visible) { stash->tablist.unlock(); stash->tablist.getPrev(); } else if (vendor->visible) { vendor->tablist.unlock(); vendor->tablist.getPrev(); } else if (chr->visible) { chr->tablist.unlock(); chr->tablist.getNext(); } else if (log->visible) { log->tablist.unlock(); log->tablist.getNext(); } } } else if (pow->visible && pow->tablist.getCurrent() != -1 && !pow->tablist.isLocked()) { if (pow->tablist.getCurrent() == 0 && inpt->pressing[LEFT] && !inpt->lock[LEFT]) { inpt->lock[LEFT] = true; pow->tablist.lock(); pow->tablist.defocus(); if (chr->visible) { chr->tablist.unlock(); chr->tablist.getNext(); } else if (log->visible) { log->tablist.unlock(); log->tablist.getNext(); } } } } } // unlock menus if only one side is showing if (!inv->visible && !pow->visible) { stash->tablist.unlock(); vendor->tablist.unlock(); chr->tablist.unlock(); log->tablist.unlock(); } else if (!vendor->visible && ! stash->visible && !chr->visible && !log->visible) { inv->tablist.unlock(); pow->tablist.unlock(); } // lock left and right where buy/sell slots meet if (vendor->visible && drag_src != 0) { if (vendor->tablist.getCurrent() == 0 || vendor->tablist.getCurrent() == (int)vendor->tablist.size()/2) inpt->lock[LEFT] = true; if (vendor->tablist.getCurrent() == (int)vendor->tablist.size()-1 || vendor->tablist.getCurrent() == (int)vendor->tablist.size()/2 - 1) inpt->lock[RIGHT] = true; } // UP/DOWN scrolling in vendor menu if (vendor->visible && !vendor->tablist.isLocked()) { int VENDOR_ROWS = vendor->getRowsCount() * 2; int VENDOR_COLS = vendor->tablist.size()/VENDOR_ROWS; bool buy_down = vendor->tablist.getCurrent() >= 0 && vendor->tablist.getCurrent() < (int)vendor->tablist.size()/2-VENDOR_COLS; bool sell_down = vendor->tablist.getCurrent() >= (int)vendor->tablist.size()/2 && vendor->tablist.getCurrent() < (int)vendor->tablist.size()-VENDOR_COLS; bool buy_up = vendor->tablist.getCurrent() >= VENDOR_COLS && vendor->tablist.getCurrent() < (int)vendor->tablist.size()/2; bool sell_up = vendor->tablist.getCurrent() >= (int)vendor->tablist.size()/2+VENDOR_COLS && vendor->tablist.getCurrent() < (int)vendor->tablist.size(); if (inpt->pressing[DOWN] && !inpt->lock[DOWN]) { inpt->lock[DOWN] = true; if (drag_src == 0 || buy_down || sell_down) { for (unsigned i = 0; i < vendor->tablist.size()/VENDOR_ROWS; i++) vendor->tablist.getNext(); } } if (inpt->pressing[UP] && !inpt->lock[UP]) { inpt->lock[UP] = true; if (drag_src == 0 || buy_up || sell_up) { for (unsigned i = 0; i < vendor->tablist.size()/VENDOR_ROWS; i++) vendor->tablist.getPrev(); } } } // UP/DOWN scrolling in inventory if (inv->visible && !inv->tablist.isLocked()) { int INVENTORY_ROWS = inv->getCarriedRows(); int EQUIPPED_SLOTS = inv->getEquippedCount(); if (inv->tablist.getCurrent() + 1 > EQUIPPED_SLOTS && inpt->pressing[DOWN] && !inpt->lock[DOWN]) { inpt->lock[DOWN] = true; for (unsigned i = 0; i < (inv->tablist.size() - EQUIPPED_SLOTS)/INVENTORY_ROWS; i++) inv->tablist.getNext(); } if (inv->tablist.getCurrent() + 1 > EQUIPPED_SLOTS && inpt->pressing[UP] && !inpt->lock[UP]) { inpt->lock[UP] = true; for (unsigned i = 0; i < (inv->tablist.size() - EQUIPPED_SLOTS)/INVENTORY_ROWS; i++) inv->tablist.getPrev(); } } // UP/DOWN scrolling in stash if (stash->visible && !stash->tablist.isLocked()) { if (inpt->pressing[DOWN] && !inpt->lock[DOWN]) { inpt->lock[DOWN] = true; for (unsigned i = 0; i < stash->tablist.size()/stash->getRowsCount(); i++) stash->tablist.getNext(); } if (inpt->pressing[UP] && !inpt->lock[UP]) { inpt->lock[UP] = true; for (unsigned i = 0; i < stash->tablist.size()/stash->getRowsCount(); i++) stash->tablist.getPrev(); } } // stash and vendor always start locked if (!stash->visible) stash->tablist.lock(); if (!vendor->visible) vendor->tablist.lock(); // inventory always starts unlocked if (!inv->visible) inv->tablist.unlock(); // position the drag hover icon depending on the last key press if (!act_drag_hover && (inpt->pressing[ACTIONBAR_BACK] || inpt->pressing[ACTIONBAR_FORWARD])) act_drag_hover = true; else if (act_drag_hover && (inpt->pressing[LEFT] || inpt->pressing[RIGHT] || inpt->pressing[UP] || inpt->pressing[DOWN])) act_drag_hover = false; // don't allow dropping actionbar items in other menus if (keyboard_dragging && drag_src == DRAG_SRC_ACTIONBAR) { inpt->lock[ACCEPT] = true; } } void MenuManager::logic() { bool clicking_character = false; bool clicking_inventory = false; bool clicking_powers = false; bool clicking_log = false; ItemStack stack; hp->update(stats->hp,stats->get(STAT_HP_MAX),inpt->mouse,""); mp->update(stats->mp,stats->get(STAT_MP_MAX),inpt->mouse,""); xp->update((stats->xp - stats->xp_table[stats->level-1]),(stats->xp_table[stats->level] - stats->xp_table[stats->level-1]),inpt->mouse,msg->get("XP: %d/%d", stats->xp, stats->xp_table[stats->level])); effects->update(stats); if (NO_MOUSE) handleKeyboardNavigation(); act->logic(); hudlog->logic(); enemy->logic(); chr->logic(); inv->logic(); vendor->logic(); pow->logic(); log->logic(); talker->logic(); stash->logic(); if (chr->checkUpgrade() || stats->level_up) { // apply equipment and max hp/mp inv->applyEquipment(inv->inventory[EQUIPMENT].storage); stats->hp = stats->get(STAT_HP_MAX); stats->mp = stats->get(STAT_MP_MAX); stats->level_up = false; } // only allow the vendor window to be open if the inventory is open if (vendor->visible && !(inv->visible)) { snd->play(vendor->sfx_close); closeLeft(); if (vendor->talker_visible && !(inv->visible)) closeRight(); } if (!inpt->pressing[INVENTORY] && !inpt->pressing[POWERS] && !inpt->pressing[CHARACTER] && !inpt->pressing[LOG]) key_lock = false; // handle npc action menu if (npc->visible) { npc->logic(); } // check if mouse-clicking a menu button act->checkMenu(clicking_character, clicking_inventory, clicking_powers, clicking_log); if (exit->visible) { exit->logic(); if (exit->isExitRequested()) { done = true; } } // cancel dragging and defocus menu tablists if (!key_lock && inpt->pressing[CANCEL] && !inpt->lock[CANCEL] && !stats->corpse) { if (keyboard_dragging || mouse_dragging) { inpt->lock[CANCEL] = true; resetDrag(); keyboard_dragging = false; mouse_dragging = false; } if (inv->tablist.getCurrent() != -1 || vendor->tablist.getCurrent() != -1 || stash->tablist.getCurrent() != -1 || act->tablist.getCurrent() != -1 || pow->tablist.getCurrent() != -1 || chr->tablist.getCurrent() != -1 || log->tablist.getCurrent() != -1) { inpt->lock[CANCEL] = true; inv->tablist.defocus(); vendor->tablist.defocus(); stash->tablist.defocus(); act->tablist.defocus(); pow->tablist.defocus(); chr->tablist.defocus(); log->tablist.defocus(); } } // exit menu toggle if ((!key_lock && !mouse_dragging && !keyboard_dragging) && !(stats->corpse && stats->permadeath)) { if (inpt->pressing[CANCEL] && !inpt->lock[CANCEL]) { inpt->lock[CANCEL] = true; key_lock = true; if (menus_open) { closeAll(); } else { exit->visible = !exit->visible; } } } // inventory menu toggle if ((inpt->pressing[INVENTORY] && !key_lock && !mouse_dragging && !keyboard_dragging) || clicking_inventory) { key_lock = true; if (inv->visible) { snd->play(inv->sfx_close); closeRight(); } else { closeRight(); act->requires_attention[MENU_INVENTORY] = false; inv->visible = true; snd->play(inv->sfx_open); } } // powers menu toggle if (((inpt->pressing[POWERS] && !key_lock && !mouse_dragging && !keyboard_dragging) || clicking_powers) && !stats->transformed) { key_lock = true; if (pow->visible) { snd->play(pow->sfx_close); closeRight(); } else { closeRight(); act->requires_attention[MENU_POWERS] = false; pow->visible = true; snd->play(pow->sfx_open); } } act->requires_attention[MENU_POWERS] = pow->getUnspent() > 0; // character menu toggleggle if ((inpt->pressing[CHARACTER] && !key_lock && !mouse_dragging && !keyboard_dragging) || clicking_character) { key_lock = true; if (chr->visible) { snd->play(chr->sfx_close); closeLeft(); } else { closeLeft(); act->requires_attention[MENU_CHARACTER] = false; chr->visible = true; snd->play(chr->sfx_open); // Make sure the stat list isn't scrolled when we open the character menu inpt->resetScroll(); } } act->requires_attention[MENU_CHARACTER] = chr->getUnspent() > 0; // log menu toggle if ((inpt->pressing[LOG] && !key_lock && !mouse_dragging && !keyboard_dragging) || clicking_log) { key_lock = true; if (log->visible) { snd->play(log->sfx_close); closeLeft(); } else { closeLeft(); act->requires_attention[MENU_LOG] = false; log->visible = true; snd->play(log->sfx_open); // Make sure the log isn't scrolled when we open the log menu inpt->resetScroll(); } } menus_open = (inv->visible || pow->visible || chr->visible || log->visible || vendor->visible || talker->visible || npc->visible); pause = (MENUS_PAUSE && menus_open) || exit->visible; if (stats->alive) { // handle right-click if (!mouse_dragging && inpt->pressing[MAIN2] && !inpt->lock[MAIN2]) { // exit menu if (exit->visible && isWithin(exit->window_area, inpt->mouse)) { inpt->lock[MAIN2] = true; } // activate inventory item else if (inv->visible && isWithin(inv->window_area, inpt->mouse)) { inpt->lock[MAIN2] = true; if (isWithin(inv->carried_area, inpt->mouse)) { inv->activate(inpt->mouse); } } } // handle left-click if (!mouse_dragging && inpt->pressing[MAIN1] && !inpt->lock[MAIN1]) { // clear keyboard dragging if (keyboard_dragging) { resetDrag(); keyboard_dragging = false; } // exit menu if (exit->visible && isWithin(exit->window_area, inpt->mouse)) { inpt->lock[MAIN1] = true; } if (chr->visible && isWithin(chr->window_area, inpt->mouse)) { inpt->lock[MAIN1] = true; } if (vendor->visible && isWithin(vendor->window_area,inpt->mouse)) { inpt->lock[MAIN1] = true; vendor->tabsLogic(); if (inpt->pressing[CTRL]) { // buy item from a vendor stack = vendor->click(inpt->mouse); if (stack.item > 0) { if (!inv->buy(stack,vendor->getTab())) { log->add(msg->get("Not enough %s.", CURRENCY), LOG_TYPE_MESSAGES); hudlog->add(msg->get("Not enough %s.", CURRENCY)); vendor->itemReturn( stack); } else { if (inv->full(stack)) { log->add(msg->get("Inventory is full."), LOG_TYPE_MESSAGES); hudlog->add(msg->get("Inventory is full.")); drop_stack = stack; } else { inv->add(stack); } } } } else { // start dragging a vendor item drag_stack = vendor->click(inpt->mouse); if (drag_stack.item > 0) { mouse_dragging = true; drag_src = DRAG_SRC_VENDOR; } } } if (stash->visible && isWithin(stash->window_area,inpt->mouse)) { inpt->lock[MAIN1] = true; if (inpt->pressing[CTRL]) { // take an item from the stash stack = stash->click(inpt->mouse); if (stack.item > 0) { if (inv->full(stack)) { log->add(msg->get("Inventory is full."), LOG_TYPE_MESSAGES); hudlog->add(msg->get("Inventory is full.")); splitStack(stack); } else { inv->add(stack); } stash->updated = true; } } else { // start dragging a stash item drag_stack = stash->click(inpt->mouse); if (drag_stack.item > 0) { mouse_dragging = true; drag_src = DRAG_SRC_STASH; } } } if (log->visible && isWithin(log->window_area,inpt->mouse)) { inpt->lock[MAIN1] = true; } // pick up an inventory item if (inv->visible && isWithin(inv->window_area,inpt->mouse)) { if (inpt->pressing[CTRL]) { inpt->lock[MAIN1] = true; stack = inv->click(inpt->mouse); if (stack.item > 0) { if (stash->visible) { if (inv->stashAdd(stack) && !stash->full(stack.item)) { stash->add(stack); stash->updated = true; } else { inv->itemReturn(stack); } } else { // The vendor could have a limited amount of currency in the future. It will be tested here. if ((SELL_WITHOUT_VENDOR || vendor->visible) && inv->sell(stack)) { vendor->setTab(VENDOR_SELL); vendor->add(stack); } else { inv->itemReturn(stack); } } } } else { inpt->lock[MAIN1] = true; drag_stack = inv->click(inpt->mouse); if (drag_stack.item > 0) { mouse_dragging = true; drag_src = DRAG_SRC_INVENTORY; } } } // pick up a power if (pow->visible && isWithin(pow->window_area,inpt->mouse)) { inpt->lock[MAIN1] = true; // check for unlock first if (!pow->unlockClick(inpt->mouse)) { // otherwise, check for dragging drag_power = pow->click(inpt->mouse); if (drag_power > 0) { mouse_dragging = true; keyboard_dragging = false; drag_src = DRAG_SRC_POWERS; } } } // action bar if (isWithin(act->numberArea,inpt->mouse) || isWithin(act->mouseArea,inpt->mouse) || isWithin(act->menuArea, inpt->mouse)) { inpt->lock[MAIN1] = true; // ctrl-click action bar to clear that slot if (inpt->pressing[CTRL]) { act->remove(inpt->mouse); } // allow drag-to-rearrange action bar else if (!isWithin(act->menuArea, inpt->mouse)) { drag_power = act->checkDrag(inpt->mouse); if (drag_power > 0) { mouse_dragging = true; drag_src = DRAG_SRC_ACTIONBAR; } } // else, clicking action bar to use a power? // this check is done by GameEngine when calling Avatar::logic() } } // handle dropping if (mouse_dragging && !inpt->pressing[MAIN1]) { // putting a power on the Action Bar if (drag_src == DRAG_SRC_POWERS) { if (isWithin(act->numberArea,inpt->mouse) || isWithin(act->mouseArea,inpt->mouse)) { act->drop(inpt->mouse, drag_power, 0); } } // rearranging the action bar else if (drag_src == DRAG_SRC_ACTIONBAR) { if (isWithin(act->numberArea,inpt->mouse) || isWithin(act->mouseArea,inpt->mouse)) { act->drop(inpt->mouse, drag_power, 1); // for locked slots forbid power dropping } else if (act->locked[act->drag_prev_slot]) { act->hotkeys[act->drag_prev_slot] = drag_power; } drag_power = 0; } // rearranging inventory or dropping items else if (drag_src == DRAG_SRC_INVENTORY) { if (inv->visible && isWithin(inv->window_area, inpt->mouse)) { inv->drop(inpt->mouse, drag_stack); } else if (isWithin(act->numberArea,inpt->mouse) || isWithin(act->mouseArea,inpt->mouse)) { // The action bar is not storage! inv->itemReturn(drag_stack); // put an item with a power on the action bar if (items->items[drag_stack.item].power != 0) { act->drop(inpt->mouse, items->items[drag_stack.item].power, false); } } else if (vendor->visible && isWithin(vendor->slots_area, inpt->mouse)) { if (inv->sell( drag_stack)) { vendor->setTab(VENDOR_SELL); vendor->add( drag_stack); } else { inv->itemReturn(drag_stack); } } else if (stash->visible && isWithin(stash->slots_area, inpt->mouse)) { if (inv->stashAdd( drag_stack) && !stash->full(drag_stack.item)) { stash->drop(inpt->mouse, drag_stack); stash->updated = true; } else { inv->itemReturn(drag_stack); } } else { // if dragging and the source was inventory, drop item to the floor // quest items cannot be dropped if (items->items[drag_stack.item].type != "quest") { drop_stack = drag_stack; inv->clearHighlight(); } else { inv->itemReturn(drag_stack); } } } else if (drag_src == DRAG_SRC_VENDOR) { // dropping an item from vendor (we only allow to drop into the carried area) if (inv->visible && isWithin( inv->carried_area, inpt->mouse)) { if (!inv->buy(drag_stack,vendor->getTab())) { log->add(msg->get("Not enough %s.", CURRENCY), LOG_TYPE_MESSAGES); hudlog->add(msg->get("Not enough %s.", CURRENCY)); vendor->itemReturn( drag_stack); } else { if (inv->full(drag_stack)) { log->add(msg->get("Inventory is full."), LOG_TYPE_MESSAGES); hudlog->add(msg->get("Inventory is full.")); drop_stack = drag_stack; } else { inv->drop(inpt->mouse,drag_stack); } } } else { vendor->itemReturn(drag_stack); } } else if (drag_src == DRAG_SRC_STASH) { // dropping an item from stash (we only allow to drop into the carried area) if (inv->visible && isWithin( inv->carried_area, inpt->mouse)) { if (inv->full(drag_stack)) { log->add(msg->get("Inventory is full."), LOG_TYPE_MESSAGES); hudlog->add(msg->get("Inventory is full.")); splitStack(drag_stack); } else { inv->drop(inpt->mouse,drag_stack); } stash->updated = true; } else if (stash->visible && isWithin(stash->slots_area, inpt->mouse)) { stash->drop(inpt->mouse,drag_stack); } else { drop_stack = drag_stack; } } drag_stack.item = 0; drag_stack.quantity = 0; drag_power = 0; drag_src = 0; mouse_dragging = false; } if (NO_MOUSE) dragAndDropWithKeyboard(); } else { if (mouse_dragging || keyboard_dragging) { resetDrag(); mouse_dragging = false; keyboard_dragging = false; } } // handle equipment changes affecting hero stats if (inv->changed_equipment || inv->changed_artifact) { inv->applyEquipment(inv->inventory[EQUIPMENT].storage); inv->changed_artifact = false; // the equipment flag is reset after the new sprites are loaded } // for action-bar powers that represent items, lookup the current item count for (int i=0; i<12; i++) { act->slot_enabled[i] = true; act->slot_item_count[i] = -1; if (act->hotkeys[i] != -1) { int item_id = powers->powers[act->hotkeys[i]].requires_item; if (item_id != -1 && items->items[item_id].type == "consumable") { act->slot_item_count[i] = inv->getItemCountCarried(item_id); if (act->slot_item_count[i] == 0) { act->slot_enabled[i] = false; } } else if (item_id != -1) { // if a non-consumable item power is unequipped, disable that slot if (!inv->isItemEquipped(item_id)) { act->slot_item_count[i] = 0; act->slot_enabled[i] = false; } } } } } void MenuManager::dragAndDropWithKeyboard() { // inventory menu if (inv->visible && inv->tablist.getCurrent() != -1 && drag_src != DRAG_SRC_ACTIONBAR) { CLICK_TYPE slotClick; Point src_slot; WidgetSlot * inv_slot; if (inv->tablist.getCurrent() < inv->getEquippedCount()) inv_slot = inv->inventory[EQUIPMENT].slots[inv->tablist.getCurrent()]; else inv_slot = inv->inventory[CARRIED].slots[inv->tablist.getCurrent() - inv->getEquippedCount()]; src_slot.x = inv_slot->pos.x; src_slot.y = inv_slot->pos.y; slotClick = inv_slot->checkClick(); // pick up item if (slotClick == CHECKED && drag_stack.item == 0) { drag_stack = inv->click(src_slot); if (drag_stack.item > 0) { keyboard_dragging = true; drag_src = DRAG_SRC_INVENTORY; } } // rearrange item else if (slotClick == CHECKED && drag_stack.item > 0) { inv->drop(src_slot, drag_stack); inv_slot->checked = false; drag_src = 0; drag_stack.item = 0; keyboard_dragging = false; } // sell, stash, or use item else if (slotClick == ACTIVATED && drag_stack.item > 0) { bool not_quest_item = items->items[drag_stack.item].type != "quest"; if (vendor->visible && inv->sell(drag_stack) && not_quest_item) { vendor->setTab(VENDOR_SELL); vendor->add(drag_stack); } else if (stash->visible && !stash->full(drag_stack.item) && not_quest_item) { stash->add(drag_stack); } else { inv->itemReturn(drag_stack); if (!vendor->visible && !stash->visible) inv->activate(src_slot); } inv->clearHighlight(); drag_src = 0; drag_stack.item = 0; keyboard_dragging = false; } } // vendor menu if (vendor->visible && vendor->tablist.getCurrent() != -1 && drag_src != DRAG_SRC_ACTIONBAR) { CLICK_TYPE slotClick; Point src_slot; WidgetSlot * vendor_slot; if (vendor->tablist.getCurrent() < (int)vendor->tablist.size()/2) vendor_slot = vendor->stock[VENDOR_BUY].slots[vendor->tablist.getCurrent()]; else vendor_slot = vendor->stock[VENDOR_SELL].slots[vendor->tablist.getCurrent() - vendor->tablist.size()/2]; src_slot.x = vendor_slot->pos.x; src_slot.y = vendor_slot->pos.y; slotClick = vendor_slot->checkClick(); // buy item if (slotClick == CHECKED && drag_stack.item == 0) { drag_stack = vendor->click(src_slot); if (drag_stack.item > 0) { keyboard_dragging = true; drag_src = DRAG_SRC_VENDOR; } } else if (slotClick == CHECKED && drag_stack.item > 0) { vendor->itemReturn(drag_stack); vendor_slot->checked = false; drag_src = 0; drag_stack.item = 0; keyboard_dragging = false; } else if (slotClick == ACTIVATED && drag_stack.item > 0) { if (!inv->buy(drag_stack,vendor->getTab())) { log->add(msg->get("Not enough %s.", CURRENCY), LOG_TYPE_MESSAGES); hudlog->add(msg->get("Not enough %s.", CURRENCY)); vendor->itemReturn(drag_stack); } else { if (inv->full(drag_stack)) { log->add(msg->get("Inventory is full."), LOG_TYPE_MESSAGES); hudlog->add(msg->get("Inventory is full.")); drop_stack = drag_stack; } else { inv->add(drag_stack); } } drag_src = 0; drag_stack.item = 0; keyboard_dragging = false; } } // stash menu if (stash->visible && stash->tablist.getCurrent() != -1 && drag_src != DRAG_SRC_ACTIONBAR) { CLICK_TYPE slotClick = stash->stock.slots[stash->tablist.getCurrent()]->checkClick(); Point src_slot(stash->stock.slots[stash->tablist.getCurrent()]->pos.x, stash->stock.slots[stash->tablist.getCurrent()]->pos.y); // pick up item if (slotClick == CHECKED && drag_stack.item == 0) { drag_stack = stash->click(src_slot); if (drag_stack.item > 0) { keyboard_dragging = true; drag_src = DRAG_SRC_STASH; } } // rearrange item else if (slotClick == CHECKED && drag_stack.item > 0) { stash->stock.slots[stash->tablist.getCurrent()]->checked = false; stash->drop(src_slot, drag_stack); drag_src = 0; drag_stack.item = 0; keyboard_dragging = false; } // send to inventory else if (slotClick == ACTIVATED && drag_stack.item > 0) { if (!inv->full(drag_stack)) { inv->add(drag_stack); } else { log->add(msg->get("Inventory is full."), LOG_TYPE_MESSAGES); hudlog->add(msg->get("Inventory is full.")); splitStack(drag_stack); } drag_src = 0; drag_stack.item = 0; keyboard_dragging = false; } } // powers menu if (pow->visible && pow->tablist.getCurrent() != -1 && drag_src != DRAG_SRC_ACTIONBAR) { CLICK_TYPE slotClick = pow->slots[pow->tablist.getCurrent()]->checkClick(); if (slotClick == CHECKED) { // check for unlock first Point src_slot(pow->slots[pow->tablist.getCurrent()]->pos.x, pow->slots[pow->tablist.getCurrent()]->pos.y); if (!pow->unlockClick(src_slot)) { // otherwise, check for dragging drag_power = pow->click(src_slot); if (drag_power > 0) { keyboard_dragging = true; drag_src = DRAG_SRC_POWERS; } } else { pow->slots[pow->tablist.getCurrent()]->checked = false; } } // clear power dragging if power slot was pressed twice else if (slotClick == ACTIVATED) { drag_src = 0; drag_power = 0; keyboard_dragging = false; } } // actionbar if (act->tablist.getCurrent() >= 0 && act->tablist.getCurrent() < 12) { CLICK_TYPE slotClick = act->slots[act->tablist.getCurrent()]->checkClick(); Point dest_slot(act->slots[act->tablist.getCurrent()]->pos.x, act->slots[act->tablist.getCurrent()]->pos.y); // pick up power if (slotClick == CHECKED && drag_stack.item == 0 && drag_power == 0) { drag_power = act->checkDrag(dest_slot); if (drag_power > 0) { keyboard_dragging = true; drag_src = DRAG_SRC_ACTIONBAR; } } // drop power/item from other menu else if (slotClick == CHECKED && drag_src != DRAG_SRC_ACTIONBAR && (drag_stack.item > 0 || drag_power > 0)) { if (drag_src == DRAG_SRC_POWERS) { act->drop(dest_slot, drag_power, 0); pow->slots[pow->tablist.getCurrent()]->checked = false; } else if (drag_src == DRAG_SRC_INVENTORY) { if (inv->tablist.getCurrent() < inv->getEquippedCount()) inv->inventory[EQUIPMENT].slots[inv->tablist.getCurrent()]->checked = false; else inv->inventory[CARRIED].slots[inv->tablist.getCurrent() - inv->getEquippedCount()]->checked = false; if (items->items[drag_stack.item].power != 0) { act->drop(dest_slot, items->items[drag_stack.item].power, false); } } act->slots[act->tablist.getCurrent()]->checked = false; resetDrag(); keyboard_dragging = false; } // rearrange actionbar else if ((slotClick == CHECKED || slotClick == ACTIVATED) && drag_src == DRAG_SRC_ACTIONBAR && drag_power > 0) { if (slotClick == CHECKED) act->slots[act->tablist.getCurrent()]->checked = false; act->drop(dest_slot, drag_power, 1); drag_src = 0; drag_power = 0; keyboard_dragging = false; inpt->lock[ACCEPT] = false; } } } void MenuManager::resetDrag() { if (drag_src == DRAG_SRC_VENDOR) vendor->itemReturn(drag_stack); else if (drag_src == DRAG_SRC_STASH) stash->itemReturn(drag_stack); else if (drag_src == DRAG_SRC_INVENTORY) inv->itemReturn(drag_stack); else if (drag_src == DRAG_SRC_ACTIONBAR) act->actionReturn(drag_power); drag_src = 0; drag_stack.item = 0; drag_stack.quantity = 0; drag_power = 0; if (keyboard_dragging && DRAG_SRC_ACTIONBAR) { inpt->lock[ACCEPT] = false; } } void MenuManager::render() { for (unsigned int i=0; i<menus.size(); i++) { menus[i]->render(); } TooltipData tip_new; // Find tooltips depending on mouse position if (chr->visible && isWithin(chr->window_area,inpt->mouse)) { tip_new = chr->checkTooltip(); } if (vendor->visible && isWithin(vendor->window_area,inpt->mouse)) { tip_new = vendor->checkTooltip(inpt->mouse); } if (stash->visible && isWithin(stash->window_area,inpt->mouse)) { tip_new = stash->checkTooltip(inpt->mouse); } if (pow->visible && isWithin(pow->window_area,inpt->mouse)) { tip_new = pow->checkTooltip(inpt->mouse); } if (inv->visible && !mouse_dragging && isWithin(inv->window_area,inpt->mouse)) { tip_new = inv->checkTooltip(inpt->mouse); } if (isWithin(act->window_area,inpt->mouse)) { tip_new = act->checkTooltip(inpt->mouse); } if (!tip_new.isEmpty()) { // when we render a tooltip it buffers the rasterized text for performance. // If this new tooltip is the same as the existing one, reuse. if (!tip_new.compare(&tip_buf)) { tip_buf.clear(); tip_buf = tip_new; } tip->render(tip_buf, inpt->mouse, STYLE_FLOAT); TOOLTIP_CONTEXT = TOOLTIP_MENU; } else if (TOOLTIP_CONTEXT != TOOLTIP_MAP) { TOOLTIP_CONTEXT = TOOLTIP_NONE; } if (NO_MOUSE) handleKeyboardTooltips(); // draw icon under cursor if dragging if (mouse_dragging) { if (drag_src == DRAG_SRC_INVENTORY || drag_src == DRAG_SRC_VENDOR || drag_src == DRAG_SRC_STASH) items->renderIcon(drag_stack, inpt->mouse.x - ICON_SIZE/2, inpt->mouse.y - ICON_SIZE/2, ICON_SIZE); else if (drag_src == DRAG_SRC_POWERS || drag_src == DRAG_SRC_ACTIONBAR) renderIcon(powers->powers[drag_power].icon, inpt->mouse.x-ICON_SIZE/2, inpt->mouse.y-ICON_SIZE/2); } else if (keyboard_dragging) { if (drag_src == DRAG_SRC_INVENTORY || drag_src == DRAG_SRC_VENDOR || drag_src == DRAG_SRC_STASH) items->renderIcon(drag_stack, keydrag_pos.x - ICON_SIZE/2, keydrag_pos.y - ICON_SIZE/2, ICON_SIZE); else if (drag_src == DRAG_SRC_POWERS || drag_src == DRAG_SRC_ACTIONBAR) renderIcon(powers->powers[drag_power].icon, keydrag_pos.x-ICON_SIZE/2, keydrag_pos.y-ICON_SIZE/2); } } void MenuManager::handleKeyboardTooltips() { TooltipData keyb_tip_new_vendor; TooltipData keyb_tip_new_stash; TooltipData keyb_tip_new_pow; TooltipData keyb_tip_new_inv; TooltipData keyb_tip_new_act; if (vendor->visible && vendor->tablist.getCurrent() != -1) { if (vendor->tablist.getCurrent() < (int)vendor->tablist.size()/2) { keydrag_pos.x = vendor->stock[VENDOR_BUY].slots[vendor->tablist.getCurrent()]->pos.x; keydrag_pos.y = vendor->stock[VENDOR_BUY].slots[vendor->tablist.getCurrent()]->pos.y; } else { keydrag_pos.x = vendor->stock[VENDOR_SELL].slots[vendor->tablist.getCurrent() - (int)vendor->tablist.size()/2]->pos.x; keydrag_pos.y = vendor->stock[VENDOR_SELL].slots[vendor->tablist.getCurrent() - (int)vendor->tablist.size()/2]->pos.y; } keyb_tip_new_vendor = vendor->checkTooltip(keydrag_pos); if (!keyb_tip_new_vendor.isEmpty()) { if (!keyb_tip_new_vendor.compare(&keyb_tip_buf_vendor)) { keyb_tip_buf_vendor.clear(); keyb_tip_buf_vendor = keyb_tip_new_vendor; } tip->render(keyb_tip_buf_vendor, keydrag_pos, STYLE_FLOAT); } } if (stash->visible && stash->tablist.getCurrent() != -1) { keydrag_pos.x = stash->stock.slots[stash->tablist.getCurrent()]->pos.x; keydrag_pos.y = stash->stock.slots[stash->tablist.getCurrent()]->pos.y; keyb_tip_new_stash = stash->checkTooltip(keydrag_pos); if (!keyb_tip_new_stash.isEmpty()) { if (!keyb_tip_new_stash.compare(&keyb_tip_buf_stash)) { keyb_tip_buf_stash.clear(); keyb_tip_buf_stash = keyb_tip_new_stash; } tip->render(keyb_tip_buf_stash, keydrag_pos, STYLE_FLOAT); } } if (pow->visible && pow->tablist.getCurrent() != -1) { keydrag_pos.x = pow->slots[pow->tablist.getCurrent()]->pos.x; keydrag_pos.y = pow->slots[pow->tablist.getCurrent()]->pos.y; keyb_tip_new_pow = pow->checkTooltip(keydrag_pos); if (!keyb_tip_new_pow.isEmpty()) { if (!keyb_tip_new_pow.compare(&keyb_tip_buf_pow)) { keyb_tip_buf_pow.clear(); keyb_tip_buf_pow = keyb_tip_new_pow; } tip->render(keyb_tip_buf_pow, keydrag_pos, STYLE_FLOAT); } } if (inv->visible && inv->tablist.getCurrent() != -1) { if (inv->tablist.getCurrent() < inv->getEquippedCount()) { keydrag_pos.x = inv->inventory[EQUIPMENT].slots[inv->tablist.getCurrent()]->pos.x; keydrag_pos.y = inv->inventory[EQUIPMENT].slots[inv->tablist.getCurrent()]->pos.y; } else { keydrag_pos.x = inv->inventory[CARRIED].slots[inv->tablist.getCurrent() - inv->getEquippedCount()]->pos.x; keydrag_pos.y = inv->inventory[CARRIED].slots[inv->tablist.getCurrent() - inv->getEquippedCount()]->pos.y; } keyb_tip_new_inv = inv->checkTooltip(keydrag_pos); if (!keyb_tip_new_inv.isEmpty()) { if (!keyb_tip_new_inv.compare(&keyb_tip_buf_inv)) { keyb_tip_buf_inv.clear(); keyb_tip_buf_inv = keyb_tip_new_inv; } tip->render(keyb_tip_buf_inv, keydrag_pos, STYLE_FLOAT); } } if (act_drag_hover && act->tablist.getCurrent() != -1) { keydrag_pos.x = act->slots[act->tablist.getCurrent()]->pos.x; keydrag_pos.y = act->slots[act->tablist.getCurrent()]->pos.y; keyb_tip_new_act = act->checkTooltip(keydrag_pos); if (!keyb_tip_new_act.isEmpty()) { if (!keyb_tip_new_act.compare(&keyb_tip_buf_act)) { keyb_tip_buf_act.clear(); keyb_tip_buf_act = keyb_tip_new_act; } tip->render(keyb_tip_buf_act, keydrag_pos, STYLE_FLOAT); } } } void MenuManager::closeAll() { if (!mouse_dragging && !keyboard_dragging) { closeLeft(); closeRight(); vendor->talker_visible = false; } } void MenuManager::closeLeft() { if (!mouse_dragging && !keyboard_dragging) { chr->visible = false; log->visible = false; vendor->visible = false; talker->visible = false; exit->visible = false; stash->visible = false; npc->visible = false; } } void MenuManager::closeRight() { if (!mouse_dragging && !keyboard_dragging) { inv->visible = false; pow->visible = false; talker->visible = false; exit->visible = false; npc->visible = false; } } bool MenuManager::isDragging() { return drag_src != 0; } /** * Splits an item stack between the stash and the inventory when the latter is full */ void MenuManager::splitStack(ItemStack stack) { if (stack.item == 0) return; if (items->items[stack.item].max_quantity > 1) { inv->add(stack); stash->add(inv->drop_stack); inv->drop_stack.item = 0; inv->drop_stack.quantity = 0; } else { stash->itemReturn(stack); } } MenuManager::~MenuManager() { tip_buf.clear(); delete hp; delete mp; delete xp; delete mini; delete inv; delete pow; delete chr; delete hudlog; delete log; delete act; delete tip; delete vendor; delete talker; delete exit; delete enemy; delete effects; delete stash; delete npc; SDL_FreeSurface(icons); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuManager.h�����������������������������������������������������������������0000664�0000000�0000000�00000005224�12247171015�0017141�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuManager */ #pragma once #ifndef MENU_MANAGER_H #define MENU_MANAGER_H #include "CommonIncludes.h" #include "ItemManager.h" class Menu; class MenuInventory; class MenuPowers; class MenuCharacter; class MenuLog; class MenuHUDLog; class MenuActionBar; class MenuStatBar; class MenuMiniMap; class MenuNPCActions; class MenuEnemy; class MenuVendor; class MenuTalker; class MenuExit; class MenuActiveEffects; class MenuStash; class StatBlock; class WidgetTooltip; const int DRAG_SRC_POWERS = 1; const int DRAG_SRC_INVENTORY = 2; const int DRAG_SRC_ACTIONBAR = 3; const int DRAG_SRC_VENDOR = 4; const int DRAG_SRC_STASH = 5; class MenuManager { private: SDL_Surface *icons; StatBlock *stats; TooltipData tip_buf; TooltipData keyb_tip_buf_vendor; TooltipData keyb_tip_buf_stash; TooltipData keyb_tip_buf_pow; TooltipData keyb_tip_buf_inv; TooltipData keyb_tip_buf_act; void handleKeyboardTooltips(); bool key_lock; void loadIcons(); bool mouse_dragging; bool keyboard_dragging; ItemStack drag_stack; int drag_power; int drag_src; bool done; bool act_drag_hover; Point keydrag_pos; void handleKeyboardNavigation(); void dragAndDropWithKeyboard(); void resetDrag(); void splitStack(ItemStack stack); public: MenuManager(StatBlock *stats); MenuManager(const MenuManager ©); // not implemented ~MenuManager(); void logic(); void render(); void renderIcon(int icon_id, int x, int y); void closeAll(); void closeLeft(); void closeRight(); std::vector<Menu*> menus; MenuInventory *inv; MenuPowers *pow; MenuCharacter *chr; MenuLog *log; MenuHUDLog *hudlog; MenuActionBar *act; MenuStatBar *hp; MenuStatBar *mp; MenuStatBar *xp; WidgetTooltip *tip; MenuMiniMap *mini; MenuNPCActions *npc; MenuEnemy *enemy; MenuVendor *vendor; MenuTalker *talker; MenuExit *exit; MenuActiveEffects *effects; MenuStash *stash; bool pause; bool menus_open; ItemStack drop_stack; bool isDragging(); bool requestingExit() { return done; } }; #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuMiniMap.cpp���������������������������������������������������������������0000664�0000000�0000000�00000015545�12247171015�0017463�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuMiniMap */ #include "CommonIncludes.h" #include "FileParser.h" #include "MapCollision.h" #include "Menu.h" #include "MenuMiniMap.h" #include "Settings.h" #include "SharedResources.h" #include "UtilsParsing.h" #include <cmath> using namespace std; MenuMiniMap::MenuMiniMap() { map_surface = 0; createMapSurface(); color_wall = SDL_MapRGB(map_surface->format, 128,128,128); color_obst = SDL_MapRGB(map_surface->format, 64,64,64); color_hero = SDL_MapRGB(map_surface->format, 255,255,255); // Load config settings FileParser infile; if (infile.open("menus/minimap.txt")) { while(infile.next()) { infile.val = infile.val + ','; if(infile.key == "pos") { pos.x = eatFirstInt(infile.val,','); pos.y = eatFirstInt(infile.val,','); pos.w = eatFirstInt(infile.val,','); pos.h = eatFirstInt(infile.val,','); } else if(infile.key == "text_pos") { text_pos = eatLabelInfo(infile.val); } } infile.close(); } // label for map name label = new WidgetLabel(); } void MenuMiniMap::getMapTitle(std::string map_title) { label->set(window_area.x+text_pos.x, window_area.y+text_pos.y, text_pos.justify, text_pos.valign, map_title, font->getColor("menu_normal"), text_pos.font_style); } void MenuMiniMap::createMapSurface() { SDL_FreeSurface(map_surface); map_surface = createSurface(512, 512); } void MenuMiniMap::render() { } void MenuMiniMap::render(FPoint hero_pos) { if (!text_pos.hidden) label->render(); if (TILESET_ORIENTATION == TILESET_ISOMETRIC) renderIso(hero_pos); else // TILESET_ORTHOGONAL renderOrtho(hero_pos); } void MenuMiniMap::prerender(MapCollision *collider, int map_w, int map_h) { map_size.x = map_w; map_size.y = map_h; SDL_FillRect(map_surface, 0, SDL_MapRGB(map_surface->format,255,0,255)); if (TILESET_ORIENTATION == TILESET_ISOMETRIC) prerenderIso(collider); else // TILESET_ORTHOGONAL prerenderOrtho(collider); } /** * Render a top-down version of the map (90 deg angle) */ void MenuMiniMap::renderOrtho(FPoint hero_pos) { const int herox = (int)floor(hero_pos.x); const int heroy = (int)floor(hero_pos.y); SDL_Rect clip; clip.x = herox - pos.w/2; clip.y = heroy - pos.h/2; clip.w = pos.w; clip.h = pos.h; SDL_Rect map_area; map_area.x = window_area.x + pos.x; map_area.y = window_area.y + pos.y; map_area.w = pos.w; map_area.h = pos.h; SDL_BlitSurface(map_surface, &clip ,screen, &map_area); SDL_LockSurface(screen); drawPixel(screen, window_area.x + pos.x + pos.w/2, window_area.y + pos.y + pos.h/2, color_hero); drawPixel(screen, window_area.x + pos.x + pos.w/2 + 1, window_area.y + pos.y + pos.h/2, color_hero); drawPixel(screen, window_area.x + pos.x + pos.w/2 - 1, window_area.y + pos.y + pos.h/2, color_hero); drawPixel(screen, window_area.x + pos.x + pos.w/2, window_area.y + pos.y + pos.h/2 + 1, color_hero); drawPixel(screen, window_area.x + pos.x + pos.w/2, window_area.y + pos.y + pos.h/2 - 1, color_hero); SDL_UnlockSurface(screen); } /** * Render an "isometric" version of the map (45 deg angle) */ void MenuMiniMap::renderIso(FPoint hero_pos) { const int herox = (int)floor(hero_pos.x); const int heroy = (int)floor(hero_pos.y); const int heroy_screen = herox + heroy; const int herox_screen = herox - heroy + std::max(map_size.x, map_size.y); SDL_Rect clip; clip.x = herox_screen - pos.w/2; clip.y = heroy_screen - pos.h/2; clip.w = pos.w; clip.h = pos.h; SDL_Rect map_area; map_area.x = window_area.x + pos.x; map_area.y = window_area.y + pos.y; map_area.w = pos.w; map_area.h = pos.h; SDL_BlitSurface(map_surface, &clip ,screen, &map_area); SDL_LockSurface(screen); drawPixel(screen, window_area.x + pos.x + pos.w/2 + 1, window_area.y + pos.y + pos.h/2, color_hero); drawPixel(screen, window_area.x + pos.x + pos.w/2 - 1, window_area.y + pos.y + pos.h/2, color_hero); drawPixel(screen, window_area.x + pos.x + pos.w/2, window_area.y + pos.y + pos.h/2 + 1, color_hero); drawPixel(screen, window_area.x + pos.x + pos.w/2, window_area.y + pos.y + pos.h/2 - 1, color_hero); drawPixel(screen, window_area.x + pos.x + pos.w/2, window_area.y + pos.y + pos.h/2, color_hero); SDL_UnlockSurface(screen); } void MenuMiniMap::prerenderOrtho(MapCollision *collider) { for (int i=0; i<std::min(map_surface->w, map_size.x); i++) { for (int j=0; j<std::min(map_surface->h, map_size.y); j++) { if (collider->colmap[i][j] == 1 || collider->colmap[i][j] == 5) { drawPixel(map_surface, i, j, color_wall); } else if (collider->colmap[i][j] == 2 || collider->colmap[i][j] == 6) { drawPixel(map_surface, i, j, color_obst); } } } } void MenuMiniMap::prerenderIso(MapCollision *collider) { // a 2x1 pixel area correlates to a tile, so we can traverse tiles using pixel counting Uint32 draw_color; int tile_type; Point tile_cursor; tile_cursor.x = -std::max(map_size.x, map_size.y)/2; tile_cursor.y = std::max(map_size.x, map_size.y)/2; bool odd_row = false; // for each pixel row for (int j=0; j<map_surface->h; j++) { // for each 2-px wide column for (int i=0; i<map_surface->w; i+=2) { // if this tile is the max map size if (tile_cursor.x >= 0 && tile_cursor.y >= 0 && tile_cursor.x < map_size.x && tile_cursor.y < map_size.y) { tile_type = collider->colmap[tile_cursor.x][tile_cursor.y]; bool draw_tile = true; // walls and low obstacles show as different colors if (tile_type == 1 || tile_type == 5) draw_color = color_wall; else if (tile_type == 2 || tile_type == 6) draw_color = color_obst; else draw_tile = false; if (draw_tile) { if (odd_row) { drawPixel(map_surface, i, j, draw_color); drawPixel(map_surface, i+1, j, draw_color); } else { drawPixel(map_surface, i-1, j, draw_color); drawPixel(map_surface, i, j, draw_color); } } } // moving screen-right in isometric is +x -y in map coordinates tile_cursor.x++; tile_cursor.y--; } // return tile cursor to next row of tiles if (odd_row) { odd_row = false; tile_cursor.x -= map_surface->w/2; tile_cursor.y += (map_surface->w/2 +1); } else { odd_row = true; tile_cursor.x -= (map_surface->w/2 -1); tile_cursor.y += map_surface->w/2; } } } MenuMiniMap::~MenuMiniMap() { SDL_FreeSurface(map_surface); delete label; } �����������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuMiniMap.h�����������������������������������������������������������������0000664�0000000�0000000�00000002675�12247171015�0017130�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuMiniMap */ #pragma once #ifndef MENU_MINI_MAP_H #define MENU_MINI_MAP_H #include "CommonIncludes.h" #include "Utils.h" #include "WidgetLabel.h" class MapCollision; class WidgetLabel; class MenuMiniMap : public Menu { private: Uint32 color_wall; Uint32 color_obst; Uint32 color_hero; SDL_Surface *map_surface; Point map_size; SDL_Rect pos; LabelInfo text_pos; WidgetLabel *label; void createMapSurface(); void renderIso(FPoint hero_pos); void renderOrtho(FPoint hero_pos); void prerenderOrtho(MapCollision *collider); void prerenderIso(MapCollision *collider); public: MenuMiniMap(); ~MenuMiniMap(); void render(); void render(FPoint hero_pos); void prerender(MapCollision *collider, int map_w, int map_h); void getMapTitle(std::string map_title); }; #endif �������������������������������������������������������������������flare-engine-0.19/src/MenuNPCActions.cpp������������������������������������������������������������0000664�0000000�0000000�00000023165�12247171015�0020067�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuNPCActions */ #include "CommonIncludes.h" #include "FileParser.h" #include "Menu.h" #include "MenuNPCActions.h" #include "NPC.h" #include "SDL_gfxBlitFunc.h" #include "Settings.h" #include "SharedResources.h" #include "UtilsParsing.h" #define SEPARATOR_HEIGHT 2 #define ITEM_SPACING 2 #define MENU_BORDER 8 using namespace std; class Action { public: Action(std::string _id = "", std::string _label = "") : id(_id) , label(id != "" ? new WidgetLabel() : NULL) { if (label) label->set(_label); } Action(const Action &r) : id(r.id) , label(id != "" ? new WidgetLabel() : NULL) { if (label) label->set(r.label->get()); } virtual ~Action() { delete label; } std::string id; WidgetLabel *label; SDL_Rect rect; }; MenuNPCActions::MenuNPCActions() : Menu() , npc(NULL) , is_selected(false) , is_empty(true) , first_dialog_node(-1) , current_action(-1) , action_menu(NULL) , vendor_label(msg->get("Trade")) , cancel_label(msg->get("Cancel")) , dialog_selected(false) , vendor_selected(false) , cancel_selected(false) , selected_dialog_node(-1) { // Load config settings FileParser infile; if (infile.open("menus/npc.txt")) { while(infile.next()) { infile.val = infile.val + ','; if(infile.key == "background_color") { background_color.r = eatFirstInt(infile.val,','); background_color.g = eatFirstInt(infile.val,','); background_color.b = eatFirstInt(infile.val,','); background_alpha = eatFirstInt(infile.val,','); } else if(infile.key == "topic_normal_color") { topic_normal_color.r = eatFirstInt(infile.val,','); topic_normal_color.g = eatFirstInt(infile.val,','); topic_normal_color.b = eatFirstInt(infile.val,','); } else if(infile.key == "topic_hilight_color") { topic_hilight_color.r = eatFirstInt(infile.val,','); topic_hilight_color.g = eatFirstInt(infile.val,','); topic_hilight_color.b = eatFirstInt(infile.val,','); } else if(infile.key == "vendor_normal_color") { vendor_normal_color.r = eatFirstInt(infile.val,','); vendor_normal_color.g = eatFirstInt(infile.val,','); vendor_normal_color.b = eatFirstInt(infile.val,','); } else if(infile.key == "vendor_hilight_color") { vendor_hilight_color.r = eatFirstInt(infile.val,','); vendor_hilight_color.g = eatFirstInt(infile.val,','); vendor_hilight_color.b = eatFirstInt(infile.val,','); } else if(infile.key == "cancel_normal_color") { cancel_normal_color.r = eatFirstInt(infile.val,','); cancel_normal_color.g = eatFirstInt(infile.val,','); cancel_normal_color.b = eatFirstInt(infile.val,','); } else if(infile.key == "cancel_hilight_color") { cancel_hilight_color.r = eatFirstInt(infile.val,','); cancel_hilight_color.g = eatFirstInt(infile.val,','); cancel_hilight_color.b = eatFirstInt(infile.val,','); } } infile.close(); } } void MenuNPCActions::update() { if (action_menu) SDL_FreeSurface(action_menu); /* get max width and height of action menu */ int w = 0, h = 0; for(size_t i=0; i<npc_actions.size(); i++) { h += ITEM_SPACING; if (npc_actions[i].label) { w = max((int)npc_actions[i].label->bounds.w, w); h += npc_actions[i].label->bounds.h; } else h += SEPARATOR_HEIGHT; h += ITEM_SPACING; } /* set action menu position */ window_area.x = VIEW_W_HALF - (w / 2); window_area.y = max(40, VIEW_H_HALF - h - 2); window_area.w = w; window_area.h = h; /* update all action menu items */ int yoffs = MENU_BORDER; SDL_Color text_color; for(size_t i=0; i<npc_actions.size(); i++) { npc_actions[i].rect.x = window_area.x + MENU_BORDER; npc_actions[i].rect.y = window_area.y + yoffs; npc_actions[i].rect.w = w; if (npc_actions[i].label) { npc_actions[i].rect.h = npc_actions[i].label->bounds.h + (ITEM_SPACING*2); if (i == current_action) { if (npc_actions[i].id == "id_cancel") text_color = cancel_hilight_color; else if (npc_actions[i].id == "id_vendor") text_color = vendor_hilight_color; else text_color = topic_hilight_color; npc_actions[i].label->set(MENU_BORDER + (w/2), yoffs + (npc_actions[i].rect.h/2) , JUSTIFY_CENTER, VALIGN_CENTER, npc_actions[i].label->get(), text_color); } else { if (npc_actions[i].id == "id_cancel") text_color = cancel_normal_color; else if (npc_actions[i].id == "id_vendor") text_color = vendor_normal_color; else text_color = topic_normal_color; npc_actions[i].label->set(MENU_BORDER + (w/2), yoffs + (npc_actions[i].rect.h/2), JUSTIFY_CENTER, VALIGN_CENTER, npc_actions[i].label->get(), text_color); } } else npc_actions[i].rect.h = SEPARATOR_HEIGHT + (ITEM_SPACING*2); yoffs += npc_actions[i].rect.h; } w += (MENU_BORDER*2); h += (MENU_BORDER*2); /* render action menu surface */ action_menu = createAlphaSurface(w,h); Uint32 bg = SDL_MapRGBA(action_menu->format, background_color.r, background_color.g, background_color.b, background_alpha); SDL_FillRect(action_menu, NULL, bg); for(size_t i=0; i<npc_actions.size(); i++) { if (npc_actions[i].label) { npc_actions[i].label->render(action_menu); } } } void MenuNPCActions::setNPC(NPC *pnpc) { // clear actions menu npc_actions.clear(); // reset states is_empty = true; is_selected = false; int topics = 0; first_dialog_node = -1; current_action = -1; npc = pnpc; if (npc == NULL) return; // reset selection dialog_selected = vendor_selected = cancel_selected = false; /* enumerate available dialog topics */ std::vector<int> nodes; npc->getDialogNodes(nodes); for (int i = (int)nodes.size() - 1; i >= 0; i--) { if (first_dialog_node == -1 && topics == 0) first_dialog_node = nodes[i]; std::string topic = npc->getDialogTopic(nodes[i]); if (topic.length() == 0) continue; stringstream ss; ss.str(""); ss << "id_dialog_" << nodes[i]; npc_actions.push_back(Action(ss.str(), topic)); topics++; is_empty = false; } if (first_dialog_node != -1 && topics == 0) topics = 1; /* if npc is a vendor add entry */ if (npc->vendor) { if (topics) npc_actions.push_back(Action()); npc_actions.push_back(Action("id_vendor", vendor_label)); is_empty = false; } npc_actions.push_back(Action()); npc_actions.push_back(Action("id_cancel", cancel_label)); /* if npc is not a vendor and only one topic is available select the topic automatically */ if (!npc->vendor && topics == 1) { dialog_selected = true; selected_dialog_node = first_dialog_node; is_selected = true; return; } /* if there is no dialogs and npc is a vendor set vendor_selected automatically */ if (npc->vendor && topics == 0) { vendor_selected = true; is_selected = true; return; } update(); } bool MenuNPCActions::empty() { return is_empty; } bool MenuNPCActions::selection() { return is_selected; } void MenuNPCActions::logic() { if (!visible) return; if (NO_MOUSE) { if (inpt->lock[ACCEPT]) return; keyboardLogic(); } else { if (inpt->lock[MAIN1]) return; /* get action under mouse */ bool got_action = false; for (size_t i=0; i<npc_actions.size(); i++) { if (!isWithin(npc_actions[i].rect, inpt->mouse)) continue; got_action = true; if (current_action != i) { current_action = i; update(); } break; } /* if we dont have an action under mouse skip main1 check */ if (!got_action) { current_action = -1; update(); return; } } /* is main1 pressed */ if ((int)current_action > -1 && ((inpt->pressing[MAIN1] && !NO_MOUSE) || (inpt->pressing[ACCEPT] && NO_MOUSE))) { if (inpt->pressing[MAIN1]) inpt->lock[MAIN1] = true; if (inpt->pressing[ACCEPT]) inpt->lock[ACCEPT] = true; if (npc_actions[current_action].label == NULL) return; else if (npc_actions[current_action].id == "id_cancel") cancel_selected = true; else if (npc_actions[current_action].id == "id_vendor") vendor_selected = true; else if (npc_actions[current_action].id.compare("id_dialog_")) { dialog_selected = true; std::stringstream ss; std::string tmp(10,' '); ss.str(npc_actions[current_action].id); ss.read(&tmp[0], 10); ss >> selected_dialog_node; } is_selected = true; visible = false; } } void MenuNPCActions::keyboardLogic() { if (inpt->pressing[LEFT]) inpt->lock[LEFT] = true; if (inpt->pressing[RIGHT]) inpt->lock[RIGHT] = true; if (inpt->pressing[UP] && !inpt->lock[UP]) { inpt->lock[UP] = true; do { current_action--; if ((int)current_action < 0) current_action = npc_actions.size()-1; } while (npc_actions[current_action].label == NULL); } if (inpt->pressing[DOWN] && !inpt->lock[DOWN]) { inpt->lock[DOWN] = true; do { current_action++; if (current_action >= npc_actions.size()) current_action = 0; } while (npc_actions[current_action].label == NULL); } update(); } void MenuNPCActions::render() { if (!visible) return; if (!action_menu) return; SDL_BlitSurface(action_menu, NULL, screen, &window_area); } MenuNPCActions::~MenuNPCActions() { SDL_FreeSurface(action_menu); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuNPCActions.h��������������������������������������������������������������0000664�0000000�0000000�00000003254�12247171015�0017531�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuNPCActions */ #pragma once #ifndef MENU_NPC_ACTIONS_H #define MENU_NPC_ACTIONS_H #include "CommonIncludes.h" class Action; class NPC; class MenuNPCActions : public Menu { private: typedef std::vector<Action> ActionsContainer; typedef ActionsContainer::iterator ActionsIterator; ActionsContainer npc_actions; NPC *npc; bool is_selected; bool is_empty; int first_dialog_node; size_t current_action; SDL_Surface *action_menu; SDL_Color topic_normal_color; SDL_Color topic_hilight_color; SDL_Color vendor_normal_color; SDL_Color vendor_hilight_color; SDL_Color cancel_normal_color; SDL_Color cancel_hilight_color; std::string vendor_label; std::string cancel_label; SDL_Color background_color; int background_alpha; void keyboardLogic(); public: MenuNPCActions(); ~MenuNPCActions(); void setNPC(NPC *npc); bool empty(); void logic(); void render(); void update(); bool selection(); bool dialog_selected; bool vendor_selected; bool cancel_selected; int selected_dialog_node; }; #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuPowers.cpp����������������������������������������������������������������0000664�0000000�0000000�00000077556�12247171015�0017422�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuPowers */ #include "CommonIncludes.h" #include "Menu.h" #include "MenuPowers.h" #include "Settings.h" #include "SharedGameResources.h" #include "SharedResources.h" #include "StatBlock.h" #include "UtilsParsing.h" #include "WidgetLabel.h" #include "WidgetSlot.h" #include "TooltipData.h" #include "MenuActionBar.h" #include <climits> using namespace std; MenuPowers::MenuPowers(StatBlock *_stats, SDL_Surface *_icons, MenuActionBar *_action_bar) { stats = _stats; icons = _icons; action_bar = _action_bar; overlay_disabled = NULL; visible = false; points_left = 0; tabs_count = 1; pressed = false; skip_section = false; tabControl = NULL; closeButton = new WidgetButton("images/menus/buttons/button_x.png"); // Read powers data from config file FileParser infile; if (infile.open("menus/powers.txt")) { while (infile.next()) { if (infile.new_section) { // for sections that are stored in collections, add a new object here if (infile.section == "power") { slots.push_back(NULL); upgradeButtons.push_back(NULL); power_cell.push_back(Power_Menu_Cell()); } else if (infile.section == "upgrade") upgrade.push_back(Power_Menu_Cell()); } if (infile.section == "header") loadHeader(infile); else if (infile.section == "power") loadPower(infile); else if (infile.section == "upgrade") loadUpgrade(infile); } infile.close(); } loadGraphics(); // check for errors in config file if((tabs_count == 1) && (!tree_image_files.empty() || !tab_titles.empty())) { fprintf(stderr, "menu/powers.txt error: you don't have tabs, but tab_tree_image and tab_title counts are not 0\n"); SDL_Quit(); exit(1); } else if((tabs_count > 1) && (tree_image_files.size() != (unsigned)tabs_count || tab_titles.size() != (unsigned)tabs_count)) { fprintf(stderr, "menu/powers.txt error: tabs count, tab_tree_image and tab_name counts do not match\n"); SDL_Quit(); exit(1); } menu_powers = this; color_bonus = font->getColor("menu_bonus"); color_penalty = font->getColor("menu_penalty"); } void MenuPowers::update() { for (unsigned i=0; i<power_cell.size(); i++) { slots[i]->pos.x = window_area.x + power_cell[i].pos.x; slots[i]->pos.y = window_area.y + power_cell[i].pos.y; if (upgradeButtons[i] != NULL) { upgradeButtons[i]->pos.x = slots[i]->pos.x + ICON_SIZE; upgradeButtons[i]->pos.y = slots[i]->pos.y; } } label_powers.set(window_area.x+title.x, window_area.y+title.y, title.justify, title.valign, msg->get("Powers"), font->getColor("menu_normal"), title.font_style); closeButton->pos.x = window_area.x+close_pos.x; closeButton->pos.y = window_area.y+close_pos.y; stat_up.set(window_area.x+unspent_points.x, window_area.y+unspent_points.y, unspent_points.justify, unspent_points.valign, "", font->getColor("menu_bonus"), unspent_points.font_style); // If we have more than one tab, create TabControl if (tabs_count > 1) { tabControl = new WidgetTabControl(tabs_count); // Initialize the tab control. tabControl->setMainArea(window_area.x+tab_area.x, window_area.y+tab_area.y, tab_area.w, tab_area.h); // Define the header. for (int i=0; i<tabs_count; i++) tabControl->setTabTitle(i, msg->get(tab_titles[i])); tabControl->updateHeader(); } } void MenuPowers::loadGraphics() { background = loadGraphicSurface("images/menus/powers.png"); powers_unlock = loadGraphicSurface("images/menus/powers_unlock.png"); overlay_disabled = loadGraphicSurface("images/menus/disabled.png"); if (tree_image_files.empty()) { tree_surf.push_back(loadGraphicSurface("images/menus/powers_tree.png")); } else { for (unsigned int i = 0; i < tree_image_files.size(); ++i) tree_surf.push_back(loadGraphicSurface(tree_image_files[i])); } for (unsigned int i=0; i<slots.size(); i++) { slots[i] = new WidgetSlot(icons, powers->powers[power_cell[i].id].icon); slots[i]->pos.x = power_cell[i].pos.x; slots[i]->pos.y = power_cell[i].pos.y; tablist.add(slots[i]); } } short MenuPowers::id_by_powerIndex(short power_index, const std::vector<Power_Menu_Cell>& cell) { // Find cell with our power for (unsigned i=0; i<cell.size(); i++) if (cell[i].id == power_index) return i; return -1; } /** * Apply power upgrades on savegame loading */ void MenuPowers::applyPowerUpgrades() { for (unsigned i = 0; i < power_cell.size(); i++) { if (!power_cell[i].upgrades.empty()) { vector<short>::iterator it; for (it = power_cell[i].upgrades.end(); it != power_cell[i].upgrades.begin(); ) { --it; vector<int>::iterator upgrade_it; upgrade_it = find(stats->powers_list.begin(), stats->powers_list.end(), *it); if (upgrade_it != stats->powers_list.end()) { short upgrade_index = id_by_powerIndex(*upgrade_it, upgrade); replacePowerCellDataByUpgrade(i, upgrade_index); break; } } } } } /** * Find cell in upgrades with next upgrade for current power_cell */ short MenuPowers::nextLevel(short power_cell_index) { vector<short>::iterator level_it; level_it = find(power_cell[power_cell_index].upgrades.begin(), power_cell[power_cell_index].upgrades.end(), power_cell[power_cell_index].id); if (level_it == power_cell[power_cell_index].upgrades.end()) { // current power is base power, take first upgrade short index = power_cell[power_cell_index].upgrades[0]; return id_by_powerIndex(index, upgrade); } // current power is an upgrade, take next upgrade if avaliable short index = distance(power_cell[power_cell_index].upgrades.begin(), level_it); if ((short)power_cell[power_cell_index].upgrades.size() > index + 1) { return id_by_powerIndex(*(level_it++), upgrade); } else { return -1; } } /** * Replace data in power_cell[cell_index] by data in upgrades */ void MenuPowers::upgradePower(short power_cell_index) { short i = nextLevel(power_cell_index); if (i == -1) return; // if power was present in ActionBar, update it there for(int j = 0; j < 12; j++){ if(action_bar->hotkeys[j] == power_cell[power_cell_index].id) { action_bar->hotkeys[j] = upgrade[i].id; } } // if we have tabControl if (tabs_count > 1) { int active_tab = tabControl->getActiveTab(); if (power_cell[power_cell_index].tab == active_tab) { replacePowerCellDataByUpgrade(power_cell_index, i); stats->powers_list.push_back(upgrade[i].id); stats->check_title = true; } } // if have don't have tabs else { replacePowerCellDataByUpgrade(power_cell_index, i); stats->powers_list.push_back(upgrade[i].id); stats->check_title = true; } } void MenuPowers::replacePowerCellDataByUpgrade(short power_cell_index, short upgrade_cell_index) { power_cell[power_cell_index].id = upgrade[upgrade_cell_index].id; power_cell[power_cell_index].requires_physoff = upgrade[upgrade_cell_index].requires_physoff; power_cell[power_cell_index].requires_physdef = upgrade[upgrade_cell_index].requires_physdef; power_cell[power_cell_index].requires_mentoff = upgrade[upgrade_cell_index].requires_mentoff; power_cell[power_cell_index].requires_mentdef = upgrade[upgrade_cell_index].requires_mentdef; power_cell[power_cell_index].requires_defense = upgrade[upgrade_cell_index].requires_defense; power_cell[power_cell_index].requires_offense = upgrade[upgrade_cell_index].requires_offense; power_cell[power_cell_index].requires_physical = upgrade[upgrade_cell_index].requires_physical; power_cell[power_cell_index].requires_mental = upgrade[upgrade_cell_index].requires_mental; power_cell[power_cell_index].requires_level = upgrade[upgrade_cell_index].requires_level; power_cell[power_cell_index].requires_power = upgrade[upgrade_cell_index].requires_power; power_cell[power_cell_index].requires_point = upgrade[upgrade_cell_index].requires_point; power_cell[power_cell_index].passive_on = upgrade[upgrade_cell_index].passive_on; slots[power_cell_index]->setIcon(powers->powers[upgrade[upgrade_cell_index].id].icon); } bool MenuPowers::baseRequirementsMet(int power_index, const vector<Power_Menu_Cell>& power_cells) { int id = id_by_powerIndex(power_index, power_cells); for (unsigned i = 0; i < power_cells[id].requires_power.size(); ++i) if (!requirementsMet(power_cells[id].requires_power[i], power_cells)) return false; if ((stats->physoff() >= power_cells[id].requires_physoff) && (stats->physdef() >= power_cells[id].requires_physdef) && (stats->mentoff() >= power_cells[id].requires_mentoff) && (stats->mentdef() >= power_cells[id].requires_mentdef) && (stats->get_defense() >= power_cells[id].requires_defense) && (stats->get_offense() >= power_cells[id].requires_offense) && (stats->get_physical() >= power_cells[id].requires_physical) && (stats->get_mental() >= power_cells[id].requires_mental) && (stats->level >= power_cells[id].requires_level)) return true; return false; } /** * With great power comes great stat requirements. */ bool MenuPowers::requirementsMet(int power_index, const vector<Power_Menu_Cell>& power_cells) { // power_index can be 0 during recursive call if requires_power is not defined. // Power with index 0 doesn't exist and is always enabled if (power_index == 0) return true; int id = id_by_powerIndex(power_index, power_cells); // If we didn't find power in power_menu, than it has no requirements if (id == -1) return true; if (!powerIsVisible(power_index, power_cells)) return false; // If power_id is saved into vector, it's unlocked anyway if (find(stats->powers_list.begin(), stats->powers_list.end(), power_index) != stats->powers_list.end()) return true; // Check the rest requirements if (baseRequirementsMet(power_index, power_cells) && !power_cells[id].requires_point) return true; return false; } /** * Check if we can unlock power. */ bool MenuPowers::powerUnlockable(int power_index, const vector<Power_Menu_Cell>& power_cells) { // power_index can be 0 during recursive call if requires_power is not defined. // Power with index 0 doesn't exist and is always enabled if (power_index == 0) return true; // Find cell with our power int id = id_by_powerIndex(power_index, power_cells); // If we didn't find power in power_menu, than it has no requirements if (id == -1) return true; if (!powerIsVisible(power_index, power_cells)) return false; // If we already have a power, don't try to unlock it if (requirementsMet(power_index, power_cells)) return false; // Check requirements if (baseRequirementsMet(power_index, power_cells)) return true; return false; } /** * Click-to-drag a power (to the action bar) */ int MenuPowers::click(Point mouse) { // if we have tabControl if (tabs_count > 1) { int active_tab = tabControl->getActiveTab(); for (unsigned i=0; i<power_cell.size(); i++) { if (isWithin(slots[i]->pos, mouse) && (power_cell[i].tab == active_tab)) { if (requirementsMet(power_cell[i].id, power_cell) && !powers->powers[power_cell[i].id].passive) return power_cell[i].id; else return 0; } } // if have don't have tabs } else { for (unsigned i=0; i<power_cell.size(); i++) { if (isWithin(slots[i]->pos, mouse)) { if (requirementsMet(power_cell[i].id, power_cell) && !powers->powers[power_cell[i].id].passive) return power_cell[i].id; else return 0; } } } return 0; } /** * Unlock a power */ bool MenuPowers::unlockClick(Point mouse) { // if we have tabControl if (tabs_count > 1) { int active_tab = tabControl->getActiveTab(); for (unsigned i=0; i<power_cell.size(); i++) { if (isWithin(slots[i]->pos, mouse) && (powerUnlockable(power_cell[i].id, power_cell)) && points_left > 0 && power_cell[i].requires_point && power_cell[i].tab == active_tab) { stats->powers_list.push_back(power_cell[i].id); stats->check_title = true; return true; } } // if have don't have tabs } else { for (unsigned i=0; i<power_cell.size(); i++) { if (isWithin(slots[i]->pos, mouse) && (powerUnlockable(power_cell[i].id, power_cell)) && points_left > 0 && power_cell[i].requires_point) { stats->powers_list.push_back(power_cell[i].id); stats->check_title = true; return true; } } } return false; } void MenuPowers::logic() { short points_used = 0; for (unsigned i=0; i<power_cell.size(); i++) { if (powers->powers[power_cell[i].id].passive) { bool unlocked_power = find(stats->powers_list.begin(), stats->powers_list.end(), power_cell[i].id) != stats->powers_list.end(); vector<int>::iterator it = find(stats->powers_passive.begin(), stats->powers_passive.end(), power_cell[i].id); if (it != stats->powers_passive.end()) { if (!baseRequirementsMet(power_cell[i].id, power_cell) && power_cell[i].passive_on) { stats->powers_passive.erase(it); stats->effects.removeEffectPassive(power_cell[i].id); power_cell[i].passive_on = false; stats->refresh_stats = true; } } else if (((baseRequirementsMet(power_cell[i].id, power_cell) && !power_cell[i].requires_point) || unlocked_power) && !power_cell[i].passive_on) { stats->powers_passive.push_back(power_cell[i].id); power_cell[i].passive_on = true; // for passives without special triggers, we need to trigger them here if (stats->effects.triggered_others) powers->activateSinglePassive(stats, power_cell[i].id); } } if (power_cell[i].requires_point && (find(stats->powers_list.begin(), stats->powers_list.end(), power_cell[i].id) != stats->powers_list.end())) points_used++; //upgrade buttons logic if (upgradeButtons[i] != NULL && power_cell[i].tab == tabControl->getActiveTab()) { if (upgradeButtons[i]->checkClick()) { upgradePower(i); } } } points_left = (stats->level * stats->power_points_per_level) - points_used; if (!visible) return; if (NO_MOUSE) { tablist.logic(); } // make shure keyboard navigation leads us to correct tab for (unsigned int i = 0; i < slots.size(); i++) { if (slots[i]->in_focus) tabControl->setActiveTab(power_cell[i].tab); } if (closeButton->checkClick()) { visible = false; snd->play(sfx_close); } if (tabs_count > 1) tabControl->logic(); } void MenuPowers::render() { if (!visible) return; SDL_Rect src; SDL_Rect dest; // background dest = window_area; src.x = 0; src.y = 0; src.w = window_area.w; src.h = window_area.h; SDL_BlitSurface(background, &src, screen, &dest); if (tabs_count > 1) { tabControl->render(); int active_tab = tabControl->getActiveTab(); for (int i=0; i<tabs_count; i++) { if (active_tab == i) { // power tree SDL_BlitSurface(tree_surf[i], &src, screen, &dest); // power icons renderPowers(active_tab); } } } else { SDL_BlitSurface(tree_surf[0], &src, screen, &dest); renderPowers(0); } // close button closeButton->render(); // text overlay if (!title.hidden) label_powers.render(); // stats if (!unspent_points.hidden) { stringstream ss; ss.str(""); if (points_left !=0) { ss << msg->get("Unspent skill points:") << " " << points_left; } stat_up.set(ss.str()); stat_up.render(); } } /** * Highlight unlocked powers */ void MenuPowers::displayBuild(int power_id) { SDL_Rect src_unlock; src_unlock.x = 0; src_unlock.y = 0; src_unlock.w = ICON_SIZE; src_unlock.h = ICON_SIZE; for (unsigned i=0; i<power_cell.size(); i++) { if (power_cell[i].id == power_id) { SDL_BlitSurface(powers_unlock, &src_unlock, screen, &slots[i]->pos); } } } /** * Show mouseover descriptions of disciplines and powers */ TooltipData MenuPowers::checkTooltip(Point mouse) { TooltipData tip; for (unsigned i=0; i<power_cell.size(); i++) { if ((tabs_count > 1) && (tabControl->getActiveTab() != power_cell[i].tab)) continue; if (!powerIsVisible(power_cell[i].id, power_cell)) continue; if (isWithin(slots[i]->pos, mouse)) { generatePowerDescription(&tip, i, power_cell); if (!power_cell[i].upgrades.empty()) { short next_level = nextLevel(i); if (next_level != -1) { tip.addText(msg->get("\nNext Level:")); generatePowerDescription(&tip, next_level, upgrade); } } return tip; } } return tip; } void MenuPowers::generatePowerDescription(TooltipData* tip, int slot_num, const vector<Power_Menu_Cell>& power_cells) { tip->addText(powers->powers[power_cells[slot_num].id].name); if (powers->powers[power_cells[slot_num].id].passive) tip->addText("Passive"); tip->addText(powers->powers[power_cells[slot_num].id].description); std::set<std::string>::iterator it; for (it = powers->powers[power_cells[slot_num].id].requires_flags.begin(); it != powers->powers[power_cells[slot_num].id].requires_flags.end(); ++it) { tip->addText(msg->get("Requires a %s", msg->get(EQUIP_FLAGS[(*it)]))); } // add requirement if ((power_cells[slot_num].requires_physoff > 0) && (stats->physoff() < power_cells[slot_num].requires_physoff)) { tip->addText(msg->get("Requires Physical Offense %d", power_cells[slot_num].requires_physoff), color_penalty); } else if((power_cells[slot_num].requires_physoff > 0) && (stats->physoff() >= power_cells[slot_num].requires_physoff)) { tip->addText(msg->get("Requires Physical Offense %d", power_cells[slot_num].requires_physoff)); } if ((power_cells[slot_num].requires_physdef > 0) && (stats->physdef() < power_cells[slot_num].requires_physdef)) { tip->addText(msg->get("Requires Physical Defense %d", power_cells[slot_num].requires_physdef), color_penalty); } else if ((power_cells[slot_num].requires_physdef > 0) && (stats->physdef() >= power_cells[slot_num].requires_physdef)) { tip->addText(msg->get("Requires Physical Defense %d", power_cells[slot_num].requires_physdef)); } if ((power_cells[slot_num].requires_mentoff > 0) && (stats->mentoff() < power_cells[slot_num].requires_mentoff)) { tip->addText(msg->get("Requires Mental Offense %d", power_cells[slot_num].requires_mentoff), color_penalty); } else if ((power_cells[slot_num].requires_mentoff > 0) && (stats->mentoff() >= power_cells[slot_num].requires_mentoff)) { tip->addText(msg->get("Requires Mental Offense %d", power_cells[slot_num].requires_mentoff)); } if ((power_cells[slot_num].requires_mentdef > 0) && (stats->mentdef() < power_cells[slot_num].requires_mentdef)) { tip->addText(msg->get("Requires Mental Defense %d", power_cells[slot_num].requires_mentdef), color_penalty); } else if ((power_cells[slot_num].requires_mentdef > 0) && (stats->mentdef() >= power_cells[slot_num].requires_mentdef)) { tip->addText(msg->get("Requires Mental Defense %d", power_cells[slot_num].requires_mentdef)); } if ((power_cells[slot_num].requires_offense > 0) && (stats->get_offense() < power_cells[slot_num].requires_offense)) { tip->addText(msg->get("Requires Offense %d", power_cells[slot_num].requires_offense), color_penalty); } else if ((power_cells[slot_num].requires_offense > 0) && (stats->get_offense() >= power_cells[slot_num].requires_offense)) { tip->addText(msg->get("Requires Offense %d", power_cells[slot_num].requires_offense)); } if ((power_cells[slot_num].requires_defense > 0) && (stats->get_defense() < power_cells[slot_num].requires_defense)) { tip->addText(msg->get("Requires Defense %d", power_cells[slot_num].requires_defense), color_penalty); } else if ((power_cells[slot_num].requires_defense > 0) && (stats->get_defense() >= power_cells[slot_num].requires_defense)) { tip->addText(msg->get("Requires Defense %d", power_cells[slot_num].requires_defense)); } if ((power_cells[slot_num].requires_physical > 0) && (stats->get_physical() < power_cells[slot_num].requires_physical)) { tip->addText(msg->get("Requires Physical %d", power_cells[slot_num].requires_physical), color_penalty); } else if ((power_cells[slot_num].requires_physical > 0) && (stats->get_physical() >= power_cells[slot_num].requires_physical)) { tip->addText(msg->get("Requires Physical %d", power_cells[slot_num].requires_physical)); } if ((power_cells[slot_num].requires_mental > 0) && (stats->get_mental() < power_cells[slot_num].requires_mental)) { tip->addText(msg->get("Requires Mental %d", power_cells[slot_num].requires_mental), color_penalty); } else if ((power_cells[slot_num].requires_mental > 0) && (stats->get_mental() >= power_cells[slot_num].requires_mental)) { tip->addText(msg->get("Requires Mental %d", power_cells[slot_num].requires_mental)); } // Draw required Level Tooltip if ((power_cells[slot_num].requires_level > 0) && stats->level < power_cells[slot_num].requires_level) { tip->addText(msg->get("Requires Level %d", power_cells[slot_num].requires_level), color_penalty); } else if ((power_cells[slot_num].requires_level > 0) && stats->level >= power_cells[slot_num].requires_level) { tip->addText(msg->get("Requires Level %d", power_cells[slot_num].requires_level)); } // Draw required Skill Point Tooltip if ((power_cells[slot_num].requires_point) && !(find(stats->powers_list.begin(), stats->powers_list.end(), power_cells[slot_num].id) != stats->powers_list.end()) && (points_left < 1)) { tip->addText(msg->get("Requires %d Skill Point", power_cells[slot_num].requires_point), color_penalty); } else if ((power_cells[slot_num].requires_point) && !(find(stats->powers_list.begin(), stats->powers_list.end(), power_cells[slot_num].id) != stats->powers_list.end()) && (points_left > 0)) { tip->addText(msg->get("Requires %d Skill Point", power_cells[slot_num].requires_point)); } // Draw unlock power Tooltip if (power_cells[slot_num].requires_point && !(find(stats->powers_list.begin(), stats->powers_list.end(), power_cells[slot_num].id) != stats->powers_list.end()) && (points_left > 0) && powerUnlockable(power_cells[slot_num].id, power_cells)) { tip->addText(msg->get("Click to Unlock"), color_bonus); } for (unsigned j = 0; j < power_cells[slot_num].requires_power.size(); ++j) { // Required Power Tooltip if ((power_cells[slot_num].requires_power[j] != 0) && !(requirementsMet(power_cells[slot_num].requires_power[j], power_cells))) { tip->addText(msg->get("Requires Power: %s", powers->powers[power_cells[slot_num].requires_power[j]].name), color_penalty); } else if ((power_cells[slot_num].requires_power[j] != 0) && (requirementsMet(power_cells[slot_num].requires_power[j], power_cells))) { tip->addText(msg->get("Requires Power: %s", powers->powers[power_cells[slot_num].requires_power[j]].name)); } } // add mana cost if (powers->powers[power_cells[slot_num].id].requires_mp > 0) { tip->addText(msg->get("Costs %d MP", powers->powers[power_cells[slot_num].id].requires_mp)); } // add health cost if (powers->powers[power_cells[slot_num].id].requires_hp > 0) { tip->addText(msg->get("Costs %d HP", powers->powers[power_cells[slot_num].id].requires_hp)); } // add cooldown time if (powers->powers[power_cells[slot_num].id].cooldown > 0) { tip->addText(msg->get("Cooldown: %d seconds", powers->powers[power_cells[slot_num].id].cooldown / MAX_FRAMES_PER_SEC)); } } MenuPowers::~MenuPowers() { SDL_FreeSurface(background); for (unsigned int i=0; i<tree_surf.size(); i++) SDL_FreeSurface(tree_surf[i]); for (unsigned int i=0; i<slots.size(); i++) { delete slots.at(i); delete upgradeButtons.at(i); } slots.clear(); upgradeButtons.clear(); SDL_FreeSurface(powers_unlock); SDL_FreeSurface(overlay_disabled); delete closeButton; if (tabs_count > 1) delete tabControl; menu_powers = NULL; } /** * Return true if required stats for power usage are met. Else return false. */ bool MenuPowers::meetsUsageStats(unsigned powerid) { // Find cell with our power int id = id_by_powerIndex(powerid, power_cell); // If we didn't find power in power_menu, than it has no stats requirements if (id == -1) return true; return stats->physoff() >= power_cell[id].requires_physoff && stats->physdef() >= power_cell[id].requires_physdef && stats->mentoff() >= power_cell[id].requires_mentoff && stats->mentdef() >= power_cell[id].requires_mentdef && stats->get_defense() >= power_cell[id].requires_defense && stats->get_offense() >= power_cell[id].requires_offense && stats->get_mental() >= power_cell[id].requires_mental && stats->get_physical() >= power_cell[id].requires_physical; } void MenuPowers::renderPowers(int tab_num) { SDL_Rect disabled_src; disabled_src.x = disabled_src.y = 0; disabled_src.w = disabled_src.h = ICON_SIZE; for (unsigned i=0; i<power_cell.size(); i++) { bool power_in_vector = false; // Continue if slot is not filled with data if (power_cell[i].tab != tab_num) continue; if (!powerIsVisible(power_cell[i].id, power_cell)) continue; if (find(stats->powers_list.begin(), stats->powers_list.end(), power_cell[i].id) != stats->powers_list.end()) power_in_vector = true; slots[i]->render(); // highlighting if (power_in_vector || requirementsMet(power_cell[i].id, power_cell)) { displayBuild(power_cell[i].id); } else { if (overlay_disabled != NULL) { SDL_BlitSurface(overlay_disabled, &disabled_src, screen, &slots[i]->pos); } } slots[i]->renderSelection(); // upgrade buttons if (upgradeButtons[i] != NULL && nextLevel(i) != -1) { // draw button only if current level is unlocked and next level can be unlocked if (requirementsMet(power_cell[i].id, power_cell) && powerUnlockable(upgrade[nextLevel(i)].id, upgrade) && points_left > 0 && upgrade[nextLevel(i)].requires_point) { upgradeButtons[i]->enabled = true; upgradeButtons[i]->render(); } else { upgradeButtons[i]->enabled = false; } } } } bool MenuPowers::powerIsVisible(short power_index, const std::vector<Power_Menu_Cell>& power_cells) { // power_index can be 0 during recursive call if requires_power is not defined. // Power with index 0 doesn't exist and is always enabled if (power_index == 0) return true; // Find cell with our power int id = id_by_powerIndex(power_index, power_cells); // If we didn't find power in power_menu, than it has no requirements if (id == -1) return true; for (unsigned i = 0; i < power_cells[id].visible_requires_status.size(); ++i) if (!camp->checkStatus(power_cells[id].visible_requires_status[i])) return false; for (unsigned i = 0; i < power_cells[id].visible_requires_not.size(); ++i) if (camp->checkStatus(power_cells[id].visible_requires_not[i])) return false; return true; } void MenuPowers::loadHeader(FileParser &infile) { infile.val = infile.val + ','; if (infile.key == "tab_title") { tab_titles.push_back(eatFirstString(infile.val, ',')); } else if (infile.key == "tab_tree") { tree_image_files.push_back(eatFirstString(infile.val, ',')); } else if (infile.key == "caption") { title = eatLabelInfo(infile.val); } else if (infile.key == "unspent_points") { unspent_points = eatLabelInfo(infile.val); } else if (infile.key == "close") { close_pos.x = eatFirstInt(infile.val, ','); close_pos.y = eatFirstInt(infile.val, ','); } else if (infile.key == "tab_area") { tab_area.x = eatFirstInt(infile.val, ','); tab_area.y = eatFirstInt(infile.val, ','); tab_area.w = eatFirstInt(infile.val, ','); tab_area.h = eatFirstInt(infile.val, ','); } else if (infile.key == "tabs") { tabs_count = eatFirstInt(infile.val, ','); if (tabs_count < 1) tabs_count = 1; } } void MenuPowers::loadPower(FileParser &infile) { infile.val = infile.val + ','; if (infile.key == "id") { int id = eatFirstInt(infile.val, ','); if (id > 0) { skip_section = false; power_cell.back().id = id; } else { skip_section = true; power_cell.pop_back(); slots.pop_back(); upgradeButtons.pop_back(); fprintf(stderr, "Power index inside power menu definition out of bounds 1-%d, skipping\n", INT_MAX); } } if (skip_section) return; if (infile.key == "tab") { power_cell.back().tab = eatFirstInt(infile.val, ','); } else if (infile.key == "position") { power_cell.back().pos.x = eatFirstInt(infile.val, ','); power_cell.back().pos.y = eatFirstInt(infile.val, ','); } else if (infile.key == "requires_physoff") { power_cell.back().requires_physoff = eatFirstInt(infile.val, ','); } else if (infile.key == "requires_physdef") { power_cell.back().requires_physdef = eatFirstInt(infile.val, ','); } else if (infile.key == "requires_mentoff") { power_cell.back().requires_mentoff = eatFirstInt(infile.val, ','); } else if (infile.key == "requires_mentdef") { power_cell.back().requires_mentdef = eatFirstInt(infile.val, ','); } else if (infile.key == "requires_defense") { power_cell.back().requires_defense = eatFirstInt(infile.val, ','); } else if (infile.key == "requires_offense") { power_cell.back().requires_offense = eatFirstInt(infile.val, ','); } else if (infile.key == "requires_physical") { power_cell.back().requires_physical = eatFirstInt(infile.val, ','); } else if (infile.key == "requires_mental") { power_cell.back().requires_mental = eatFirstInt(infile.val, ','); } else if (infile.key == "requires_point") { if (infile.val == "true,") power_cell.back().requires_point = true; } else if (infile.key == "requires_level") { power_cell.back().requires_level = eatFirstInt(infile.val, ','); } else if (infile.key == "upgrades") { upgradeButtons.back() = new WidgetButton("images/menus/buttons/button_plus.png"); string repeat_val = infile.nextValue(); while (repeat_val != "") { power_cell.back().upgrades.push_back(toInt(repeat_val)); repeat_val = infile.nextValue(); } } else if (infile.key == "requires_power") { power_cell.back().requires_power.push_back(eatFirstInt(infile.val, ',')); } else if (infile.key == "visible_requires_status") { power_cell.back().visible_requires_status.push_back(eatFirstString(infile.val, ',')); } else if (infile.key == "visible_requires_not_status") { power_cell.back().visible_requires_not.push_back(eatFirstString(infile.val, ',')); } } void MenuPowers::loadUpgrade(FileParser &infile) { infile.val = infile.val + ','; if (infile.key == "id") { int id = eatFirstInt(infile.val, ','); if (id > 0) { skip_section = false; upgrade.back().id = id; } else { skip_section = true; upgrade.pop_back(); fprintf(stderr, "Power index inside power menu definition out of bounds 1-%d, skipping\n", INT_MAX); } } if (skip_section) return; if (infile.key == "requires_physoff") { upgrade.back().requires_physoff = eatFirstInt(infile.val, ','); } else if (infile.key == "requires_physdef") { upgrade.back().requires_physdef = eatFirstInt(infile.val, ','); } else if (infile.key == "requires_mentoff") { upgrade.back().requires_mentoff = eatFirstInt(infile.val, ','); } else if (infile.key == "requires_mentdef") { upgrade.back().requires_mentdef = eatFirstInt(infile.val, ','); } else if (infile.key == "requires_defense") { upgrade.back().requires_defense = eatFirstInt(infile.val, ','); } else if (infile.key == "requires_offense") { upgrade.back().requires_offense = eatFirstInt(infile.val, ','); } else if (infile.key == "requires_physical") { upgrade.back().requires_physical = eatFirstInt(infile.val, ','); } else if (infile.key == "requires_mental") { upgrade.back().requires_mental = eatFirstInt(infile.val, ','); } else if (infile.key == "requires_point") { if (infile.val == "true,") upgrade.back().requires_point = true; } else if (infile.key == "requires_level") { upgrade.back().requires_level = eatFirstInt(infile.val, ','); } else if (infile.key == "requires_power") { upgrade.back().requires_power.push_back(eatFirstInt(infile.val, ',')); } else if (infile.key == "visible_requires_status") { upgrade.back().visible_requires_status.push_back(eatFirstString(infile.val, ',')); } else if (infile.key == "visible_requires_not_status") { upgrade.back().visible_requires_not.push_back(eatFirstString(infile.val, ',')); } } ��������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuPowers.h������������������������������������������������������������������0000664�0000000�0000000�00000007722�12247171015�0017053�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuPowers */ #pragma once #ifndef MENU_POWERS_H #define MENU_POWERS_H #include "CommonIncludes.h" #include "Menu.h" #include "Utils.h" #include "WidgetButton.h" #include "WidgetLabel.h" #include "WidgetTabControl.h" #include "FileParser.h" class StatBlock; class TooltipData; class WidgetSlot; class MenuActionBar; class Power_Menu_Cell { public: short id; short tab; Point pos; short requires_physoff; short requires_physdef; short requires_mentoff; short requires_mentdef; short requires_defense; short requires_offense; short requires_physical; short requires_mental; short requires_level; std::vector<short> upgrades; std::vector<short> requires_power; bool requires_point; bool passive_on; std::vector<std::string> visible_requires_status; std::vector<std::string> visible_requires_not; Power_Menu_Cell() : id(-1) , tab(0) , pos(Point()) , requires_physoff(0) , requires_physdef(0) , requires_mentoff(0) , requires_mentdef(0) , requires_defense(0) , requires_offense(0) , requires_physical(0) , requires_mental(0) , requires_level(0) , upgrades() , requires_power() , requires_point(false) , passive_on(false) { } }; class MenuPowers : public Menu { private: StatBlock *stats; MenuActionBar *action_bar; std::vector<Power_Menu_Cell> power_cell; std::vector<Power_Menu_Cell> upgrade; std::vector<WidgetButton*> upgradeButtons; bool skip_section; SDL_Surface *icons; std::vector<SDL_Surface*> tree_surf; SDL_Surface *powers_unlock; SDL_Surface *overlay_disabled; WidgetButton *closeButton; bool pressed; LabelInfo title; LabelInfo unspent_points; Point close_pos; SDL_Rect tab_area; short points_left; short tabs_count; std::vector<std::string> tab_titles; std::vector<std::string> tree_image_files; WidgetLabel label_powers; WidgetLabel stat_up; WidgetTabControl *tabControl; void loadGraphics(); void displayBuild(int power_id); bool powerUnlockable(int power_index, const std::vector<Power_Menu_Cell>& power_cells); void renderPowers(int tab_num); SDL_Color color_bonus; SDL_Color color_penalty; short id_by_powerIndex(short power_index, const std::vector<Power_Menu_Cell>& cell); short nextLevel(short power_cell_index); void upgradePower(short power_cell_index); void replacePowerCellDataByUpgrade(short power_cell_index, short upgrade_cell_index); bool powerIsVisible(short power_index, const std::vector<Power_Menu_Cell>& power_cells); void loadHeader(FileParser &infile); void loadPower(FileParser &infile); void loadUpgrade(FileParser &infile); public: MenuPowers(StatBlock *_stats, SDL_Surface *_icons, MenuActionBar *_action_bar); ~MenuPowers(); void update(); void logic(); void render(); TooltipData checkTooltip(Point mouse); void generatePowerDescription(TooltipData* tip, int slot_num, const std::vector<Power_Menu_Cell>& power_cells); bool baseRequirementsMet(int power_index, const std::vector<Power_Menu_Cell>& power_cells); bool requirementsMet(int power_index, const std::vector<Power_Menu_Cell>& power_cells); int click(Point mouse); bool unlockClick(Point mouse); void applyPowerUpgrades(); bool meetsUsageStats(unsigned powerid); short getUnspent() { return points_left; } std::vector<WidgetSlot*> slots; // power slot Widgets TabList tablist; }; #endif ����������������������������������������������flare-engine-0.19/src/MenuStash.cpp�����������������������������������������������������������������0000664�0000000�0000000�00000013573�12247171015�0017212�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuStash */ #include "FileParser.h" #include "Menu.h" #include "MenuStash.h" #include "Settings.h" #include "SharedResources.h" #include "UtilsParsing.h" #include "WidgetButton.h" #include "SharedGameResources.h" using namespace std; MenuStash::MenuStash(StatBlock *_stats) : Menu() , stats(_stats) , closeButton(new WidgetButton("images/menus/buttons/button_x.png")) , color_normal(font->getColor("menu_normal")) , stock() , updated(false) { background = loadGraphicSurface("images/menus/stash.png"); // Load config settings FileParser infile; if (infile.open("menus/stash.txt")) { while(infile.next()) { infile.val = infile.val + ','; if (infile.key == "close") { close_pos.x = eatFirstInt(infile.val,','); close_pos.y = eatFirstInt(infile.val,','); } else if (infile.key == "slots_area") { slots_area.x = eatFirstInt(infile.val,','); slots_area.y = eatFirstInt(infile.val,','); } else if (infile.key == "stash_cols") { slots_cols = eatFirstInt(infile.val,','); } else if (infile.key == "stash_rows") { slots_rows = eatFirstInt(infile.val,','); } else if (infile.key == "caption") { title = eatLabelInfo(infile.val); } else if (infile.key == "currency") { currency = eatLabelInfo(infile.val); } } infile.close(); } STASH_SLOTS = slots_cols * slots_rows; } void MenuStash::update() { slots_area.x += window_area.x; slots_area.y += window_area.y; slots_area.w = slots_cols*ICON_SIZE; slots_area.h = slots_rows*ICON_SIZE; stock.init( STASH_SLOTS, slots_area, ICON_SIZE, slots_cols); closeButton->pos.x = window_area.x+close_pos.x; closeButton->pos.y = window_area.y+close_pos.y; for (int i = 0; i < STASH_SLOTS; i++) { tablist.add(stock.slots[i]); } } void MenuStash::logic() { if (!visible) return; if (NO_MOUSE) { tablist.logic(); } if (closeButton->checkClick()) { visible = false; snd->play(sfx_close); } } void MenuStash::render() { if (!visible) return; SDL_Rect src; SDL_Rect dest; // background src.x = 0; src.y = 0; dest.x = window_area.x; dest.y = window_area.y; src.w = dest.w = window_area.w; src.h = dest.h = window_area.h; SDL_BlitSurface(background, &src, screen, &dest); // close button closeButton->render(); // text overlay WidgetLabel label; if (!title.hidden) { label.set(window_area.x+title.x, window_area.y+title.y, title.justify, title.valign, msg->get("Shared Stash"), color_normal, title.font_style); label.render(); } if (!currency.hidden) { label.set(window_area.x+currency.x, window_area.y+currency.y, currency.justify, currency.valign, msg->get("%d %s", stock.count(CURRENCY_ID), CURRENCY), color_normal, currency.font_style); label.render(); } // show stock stock.render(); } /** * Dragging and dropping an item can be used to rearrange the stash */ void MenuStash::drop(Point position, ItemStack stack) { int slot; int drag_prev_slot; items->playSound(stack.item); slot = stock.slotOver(position); drag_prev_slot = stock.drag_prev_slot; if (slot != drag_prev_slot) { if (stock[slot].item == stack.item) { // Merge the stacks add(stack, slot); } else if (stock[slot].item == 0) { // Drop the stack stock[slot] = stack; } else if (stock[drag_prev_slot].item == 0) { // Check if the previous slot is free (could still be used if SHIFT was used). // Swap the two stacks itemReturn(stock[slot]); stock[slot] = stack; } else { itemReturn( stack); } } else { itemReturn(stack); // cancel } } void MenuStash::add(ItemStack stack, int slot) { if (stack.item != 0) { int max_quantity = items->items[stack.item].max_quantity; if (slot > -1 && stock[slot].item != 0 && stock[slot].item != stack.item) { // the proposed slot isn't available, search for another one slot = -1; } // first search of stack to complete if the item is stackable int i = 0; while (max_quantity > 1 && slot == -1 && i < STASH_SLOTS) { if (stock[i].item == stack.item && stock[i].quantity < max_quantity) { slot = i; } i++; } // then an empty slot i = 0; while (slot == -1 && i < STASH_SLOTS) { if (stock[i].item == 0) { slot = i; } i++; } if (slot != -1) { // Add int quantity_added = min( stack.quantity, max_quantity - stock[slot].quantity); stock[slot].item = stack.item; stock[slot].quantity += quantity_added; stack.quantity -= quantity_added; // Add back the remaining if (stack.quantity > 0) { add( stack); } } else { // No available slot, drop } } } /** * Start dragging a vendor item * Players can drag an item to their inventory. */ ItemStack MenuStash::click(Point position) { ItemStack stack = stock.click(position); return stack; } /** * Cancel the dragging initiated by the click() */ void MenuStash::itemReturn(ItemStack stack) { stock.itemReturn(stack); } void MenuStash::add(ItemStack stack) { items->playSound(stack.item); stock.add(stack); } TooltipData MenuStash::checkTooltip(Point position) { return stock.checkTooltip(position, stats, PLAYER_INV); } bool MenuStash::full(int item) { return stock.full(item); } int MenuStash::getRowsCount() { return slots_rows; } MenuStash::~MenuStash() { SDL_FreeSurface(background); delete closeButton; } �������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuStash.h�������������������������������������������������������������������0000664�0000000�0000000�00000003075�12247171015�0016653�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuStash */ #pragma once #ifndef MENU_STASH_H #define MENU_STASH_H #include "CommonIncludes.h" #include "MenuItemStorage.h" #include "WidgetLabel.h" class NPC; class StatBlock; class WidgetButton; class MenuStash : public Menu { private: StatBlock *stats; WidgetButton *closeButton; int STASH_SLOTS; // label and widget positions Point close_pos; LabelInfo title; LabelInfo currency; int slots_cols; int slots_rows; SDL_Color color_normal; public: MenuStash(StatBlock *stats); ~MenuStash(); void update(); void logic(); void render(); ItemStack click(Point position); void itemReturn(ItemStack stack); void add(ItemStack stack); TooltipData checkTooltip(Point position); bool full(int item); void drop(Point position, ItemStack stack); void add(ItemStack stack, int slot); int getRowsCount(); SDL_Rect slots_area; MenuItemStorage stock; bool updated; TabList tablist; }; #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuStatBar.cpp���������������������������������������������������������������0000664�0000000�0000000�00000007767�12247171015�0017500�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Justin Jacobs This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * MenuStatBar * * Handles the display of a status bar */ #include "CommonIncludes.h" #include "Menu.h" #include "MenuStatBar.h" #include "ModManager.h" #include "SharedResources.h" #include "StatBlock.h" #include "WidgetLabel.h" #include "FileParser.h" #include "UtilsParsing.h" #include "UtilsFileSystem.h" using namespace std; MenuStatBar::MenuStatBar(std::string type) { label = new WidgetLabel(); orientation = 0; // horizontal custom_text_pos = false; // label will be placed in the middle of the bar custom_string = ""; stat_cur = 0; stat_max = 0; // Load config settings FileParser infile; if(infile.open("menus/"+type+".txt")) { while(infile.next()) { infile.val = infile.val + ','; if(infile.key == "pos") { bar_pos.x = eatFirstInt(infile.val,','); bar_pos.y = eatFirstInt(infile.val,','); bar_pos.w = eatFirstInt(infile.val,','); bar_pos.h = eatFirstInt(infile.val,','); } else if(infile.key == "text_pos") { custom_text_pos = true; text_pos = eatLabelInfo(infile.val); } else if(infile.key == "orientation") { int orient = eatFirstInt(infile.val,','); if (orient == 1) orientation = true; else orientation = false; } } infile.close(); } loadGraphics(type); color_normal = font->getColor("menu_normal"); } void MenuStatBar::loadGraphics(std::string type) { background = loadGraphicSurface("images/menus/bar_" + type + "_background.png"); bar = loadGraphicSurface("images/menus/bar_" + type + ".png"); } void MenuStatBar::update(int _stat_cur, int _stat_max, Point _mouse, std::string _custom_string) { if (_custom_string != "") custom_string = _custom_string; mouse = _mouse; stat_cur = _stat_cur; stat_max = _stat_max; } void MenuStatBar::render() { SDL_Rect src; SDL_Rect dest; // position elements based on the window position SDL_Rect bar_dest = bar_pos; bar_dest.x = bar_pos.x+window_area.x; bar_dest.y = bar_pos.y+window_area.y; // draw bar background dest.x = bar_dest.x; dest.y = bar_dest.y; src.x = 0; src.y = 0; src.w = bar_pos.w; src.h = bar_pos.h; SDL_BlitSurface(background, &src, screen, &dest); // draw bar progress based on orientation if (orientation == 0) { unsigned bar_length = (stat_max == 0) ? 0 : ((long)stat_cur * (long)bar_pos.w) / (long)stat_max; src.x = 0; src.y = 0; src.w = bar_length; src.h = bar_pos.h; dest.x = bar_dest.x; dest.y = bar_dest.y; } else if (orientation == 1) { unsigned bar_length = (stat_max == 0) ? 0 : ((long)stat_cur * (long)bar_pos.h) / (long)stat_max; src.x = 0; src.y = bar_pos.h-bar_length; src.w = bar_pos.w; src.h = bar_length; dest.x = bar_dest.x; dest.y = bar_dest.y+src.y; } SDL_BlitSurface(bar, &src, screen, &dest); // if mouseover, draw text if (!text_pos.hidden) { if (custom_text_pos) label->set(bar_dest.x+text_pos.x, bar_dest.y+text_pos.y, text_pos.justify, text_pos.valign, "", color_normal, text_pos.font_style); else label->set(bar_dest.x+bar_pos.w/2, bar_dest.y+bar_pos.h/2, JUSTIFY_CENTER, VALIGN_CENTER, "", color_normal); if (isWithin(bar_dest,mouse)) { stringstream ss; if (custom_string != "") ss << custom_string; else ss << stat_cur << "/" << stat_max; label->set(ss.str()); label->render(); } } } MenuStatBar::~MenuStatBar() { SDL_FreeSurface(background); SDL_FreeSurface(bar); delete label; } ���������flare-engine-0.19/src/MenuStatBar.h�����������������������������������������������������������������0000664�0000000�0000000�00000002552�12247171015�0017130�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Justin Jacobs This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * MenuStatBar * * Handles the display of a status bar */ #pragma once #ifndef MENU_STATBAR_H #define MENU_STATBAR_H #include "CommonIncludes.h" #include "Utils.h" #include "WidgetLabel.h" class WidgetLabel; class MenuStatBar : public Menu { private: SDL_Surface *bar; WidgetLabel *label; int stat_cur; int stat_max; Point mouse; SDL_Rect bar_pos; LabelInfo text_pos; bool orientation; bool custom_text_pos; std::string custom_string; SDL_Color color_normal; public: MenuStatBar(std::string type); ~MenuStatBar(); void loadGraphics(std::string type); void update(int _stat_cur, int _stat_max, Point _mouse, std::string _custom_string); void render(); }; #endif ������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuTalker.cpp����������������������������������������������������������������0000664�0000000�0000000�00000021016�12247171015�0017341�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger and morris989 Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuTalker */ #include "FileParser.h" #include "Menu.h" #include "MenuTalker.h" #include "NPC.h" #include "WidgetButton.h" #include "WidgetLabel.h" #include "WidgetScrollBox.h" #include "SharedResources.h" #include "Settings.h" #include "UtilsParsing.h" #include "MenuManager.h" #include "MenuNPCActions.h" using namespace std; MenuTalker::MenuTalker(MenuManager *_menu) : Menu() , menu(_menu) , portrait(NULL) , dialog_node(0) , event_cursor(0) , font_who("font_regular") , font_dialog("font_regular") , color_normal(font->getColor("menu_normal")) , npc(NULL) , vendor_visible(false) , advanceButton(new WidgetButton("images/menus/buttons/right.png")) , closeButton(new WidgetButton("images/menus/buttons/button_x.png")) { background = loadGraphicSurface("images/menus/dialog_box.png"); // Load config settings FileParser infile; if(infile.open("menus/talker.txt")) { while(infile.next()) { infile.val = infile.val + ','; if(infile.key == "close") { close_pos.x = eatFirstInt(infile.val,','); close_pos.y = eatFirstInt(infile.val,','); } else if(infile.key == "advance") { advance_pos.x = eatFirstInt(infile.val,','); advance_pos.y = eatFirstInt(infile.val,','); } else if (infile.key == "dialogbox") { dialog_pos.x = eatFirstInt(infile.val,','); dialog_pos.y = eatFirstInt(infile.val,','); dialog_pos.w = eatFirstInt(infile.val,','); dialog_pos.h = eatFirstInt(infile.val,','); } else if (infile.key == "dialogtext") { text_pos.x = eatFirstInt(infile.val,','); text_pos.y = eatFirstInt(infile.val,','); text_pos.w = eatFirstInt(infile.val,','); text_pos.h = eatFirstInt(infile.val,','); } else if (infile.key == "text_offset") { text_offset.x = eatFirstInt(infile.val,','); text_offset.y = eatFirstInt(infile.val,','); } else if (infile.key == "portrait_he") { portrait_he.x = eatFirstInt(infile.val,','); portrait_he.y = eatFirstInt(infile.val,','); portrait_he.w = eatFirstInt(infile.val,','); portrait_he.h = eatFirstInt(infile.val,','); } else if (infile.key == "portrait_you") { portrait_you.x = eatFirstInt(infile.val,','); portrait_you.y = eatFirstInt(infile.val,','); portrait_you.w = eatFirstInt(infile.val,','); portrait_you.h = eatFirstInt(infile.val,','); } else if (infile.key == "font_who") { font_who = eatFirstString(infile.val,','); } else if (infile.key == "font_dialog") { font_dialog = eatFirstString(infile.val,','); } } infile.close(); } label_name = new WidgetLabel(); textbox = new WidgetScrollBox(text_pos.w, text_pos.h-(text_offset.y*2)); tablist.add(advanceButton); tablist.add(closeButton); tablist.add(textbox); } void MenuTalker::chooseDialogNode(int request_dialog_node) { event_cursor = 0; if(request_dialog_node == -1) return; dialog_node = request_dialog_node; npc->processEvent(dialog_node, event_cursor); npc->processDialog(dialog_node, event_cursor); createBuffer(); } void MenuTalker::update() { advanceButton->pos.x = window_area.x + advance_pos.x; advanceButton->pos.y = window_area.y + advance_pos.y; closeButton->pos.x = window_area.x + close_pos.x; closeButton->pos.y = window_area.y + close_pos.y; label_name->set(window_area.x+text_pos.x+text_offset.x, window_area.y+text_pos.y+text_offset.y, JUSTIFY_LEFT, VALIGN_TOP, "", color_normal, font_who); textbox->pos.x = window_area.x + text_pos.x; textbox->pos.y = window_area.y + text_pos.y+text_offset.y+label_name->bounds.h; textbox->pos.h -= label_name->bounds.h; } /** * Menu interaction (enter/space/click to continue) */ void MenuTalker::logic() { if (!visible || npc==NULL) return; if (NO_MOUSE) { tablist.logic(); } advanceButton->enabled = false; closeButton->enabled = false; // determine active button if (event_cursor < npc->dialog[dialog_node].size()-1) { if (npc->dialog[dialog_node][event_cursor+1].type != "") { advanceButton->enabled = true; tablist.remove(closeButton); tablist.add(advanceButton); } else { closeButton->enabled = true; tablist.remove(advanceButton); tablist.add(closeButton); } } else { closeButton->enabled = true; tablist.remove(advanceButton); tablist.add(closeButton); } bool more; if (advanceButton->checkClick() || closeButton->checkClick()) { // button was clicked npc->processEvent(dialog_node, event_cursor); event_cursor++; more = npc->processDialog(dialog_node, event_cursor); } else if (inpt->pressing[ACCEPT] && !inpt->lock[ACCEPT]) { inpt->lock[ACCEPT] = true; // pressed next/more npc->processEvent(dialog_node, event_cursor); event_cursor++; more = npc->processDialog(dialog_node, event_cursor); } else { textbox->logic(); return; } if (more) { createBuffer(); } else { // show the NPC Action Menu menu->npc->setNPC(npc); if (!menu->npc->selection()) menu->npc->visible = true; else menu->npc->setNPC(NULL); // end dialog npc = NULL; visible = false; } } void MenuTalker::createBuffer() { if (event_cursor >= npc->dialog[dialog_node].size()) return; string line; // speaker name string etype = npc->dialog[dialog_node][event_cursor].type; string who; if (etype == "him" || etype == "her") { who = npc->name; } else if (etype == "you") { who = hero_name; } label_name->set(who); line = parseLine(npc->dialog[dialog_node][event_cursor].s); // render dialog text to the scrollbox buffer Point line_size = font->calc_size(line,textbox->pos.w-(text_offset.x*2)); textbox->resize(line_size.y); textbox->line_height = font->getLineHeight(); font->setFont(font_dialog); font->render(line, text_offset.x, 0, JUSTIFY_LEFT, textbox->contents, text_pos.w - text_offset.x*2, color_normal); } void MenuTalker::render() { if (!visible) return; SDL_Rect src; SDL_Rect dest; int offset_x = window_area.x; int offset_y = window_area.y; // dialog box src.x = 0; src.y = 0; dest.x = offset_x + dialog_pos.x; dest.y = offset_y + dialog_pos.y; src.w = dest.w = dialog_pos.w; src.h = dest.h = dialog_pos.h; SDL_BlitSurface(background, &src, screen, &dest); // show active portrait string etype = npc->dialog[dialog_node][event_cursor].type; if (etype == "him" || etype == "her") { if (npc->portrait != NULL) { src.w = dest.w = portrait_he.w; src.h = dest.h = portrait_he.h; dest.x = offset_x + portrait_he.x; dest.y = offset_y + portrait_he.y; SDL_BlitSurface(npc->portrait, &src, screen, &dest); } } else if (etype == "you") { if (portrait != NULL) { src.w = dest.w = portrait_you.w; src.h = dest.h = portrait_you.h; dest.x = offset_x + portrait_you.x; dest.y = offset_y + portrait_you.y; SDL_BlitSurface(portrait, &src, screen, &dest); } } // name & dialog text label_name->render(); textbox->render(); // show advance button if there are more event components, or close button if not if (event_cursor < npc->dialog[dialog_node].size()-1) { if (npc->dialog[dialog_node][event_cursor+1].type != "") { advanceButton->render(); } else { closeButton->render(); } } else { closeButton->render(); } } void MenuTalker::setHero(const string& name, const string& class_name, const string& portrait_filename) { hero_name = name; hero_class = msg->get(class_name); SDL_FreeSurface(portrait); portrait = loadGraphicSurface("images/portraits/" + portrait_filename + ".png", "Couldn't load portrait"); } string MenuTalker::parseLine(const string &line) { string new_line = line; // name size_t index = new_line.find("%N"); if (index != string::npos) new_line = new_line.replace(index, 2, hero_name); // class index = new_line.find("%C"); if (index != string::npos) new_line.replace(index, 2, hero_class); return new_line; } MenuTalker::~MenuTalker() { SDL_FreeSurface(background); SDL_FreeSurface(portrait); delete label_name; delete textbox; delete advanceButton; delete closeButton; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuTalker.h������������������������������������������������������������������0000664�0000000�0000000�00000003560�12247171015�0017012�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger and morris989 Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuTalker */ #pragma once #ifndef MENU_TALKER_H #define MENU_TALKER_H #include "CommonIncludes.h" #include "Utils.h" #include "Widget.h" class CampaignManager; class MenuManager; class NPC; class WidgetButton; class WidgetLabel; class WidgetScrollBox; class MenuTalker : public Menu { private: std::string parseLine(const std::string &line); MenuManager *menu; SDL_Surface *portrait; std::string hero_name; std::string hero_class; int dialog_node; unsigned int event_cursor; Point close_pos; Point advance_pos; SDL_Rect dialog_pos; SDL_Rect text_pos; Point text_offset; SDL_Rect portrait_he; SDL_Rect portrait_you; std::string font_who; std::string font_dialog; SDL_Color color_normal; TabList tablist; WidgetLabel *label_name; WidgetScrollBox *textbox; public: MenuTalker(MenuManager *menu); ~MenuTalker(); NPC *npc; void chooseDialogNode(int requested_node = -1); void update(); void logic(); void render(); void setHero(const std::string& name, const std::string& class_name, const std::string& portrait_filename); void createBuffer(); bool vendor_visible; WidgetButton *advanceButton; WidgetButton *closeButton; }; #endif ������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MenuVendor.cpp����������������������������������������������������������������0000664�0000000�0000000�00000014674�12247171015�0017370�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuVendor */ #include "FileParser.h" #include "ItemStorage.h" #include "Menu.h" #include "MenuVendor.h" #include "NPC.h" #include "Settings.h" #include "SharedResources.h" #include "UtilsParsing.h" #include "WidgetButton.h" #include "WidgetTabControl.h" #include "SharedGameResources.h" using namespace std; MenuVendor::MenuVendor(StatBlock *_stats) : Menu() , stats(_stats) , closeButton(new WidgetButton("images/menus/buttons/button_x.png")) , tabControl(new WidgetTabControl(2)) , activetab(VENDOR_BUY) , color_normal(font->getColor("menu_normal")) , npc(NULL) , buyback_stock() , talker_visible(false) { background = loadGraphicSurface("images/menus/vendor.png"); tabControl->setTabTitle(VENDOR_BUY,msg->get("Inventory")); tabControl->setTabTitle(VENDOR_SELL,msg->get("Buyback")); loadMerchant(""); // Load config settings FileParser infile; if(infile.open("menus/vendor.txt")) { while(infile.next()) { infile.val = infile.val + ','; if(infile.key == "close") { close_pos.x = eatFirstInt(infile.val,','); close_pos.y = eatFirstInt(infile.val,','); } else if(infile.key == "slots_area") { slots_area.x = eatFirstInt(infile.val,','); slots_area.y = eatFirstInt(infile.val,','); } else if (infile.key == "vendor_cols") { slots_cols = eatFirstInt(infile.val,','); } else if (infile.key == "vendor_rows") { slots_rows = eatFirstInt(infile.val,','); } else if (infile.key == "caption") { title = eatLabelInfo(infile.val); } } infile.close(); } VENDOR_SLOTS = slots_cols * slots_rows; } void MenuVendor::update() { slots_area.x += window_area.x; slots_area.y += window_area.y; slots_area.w = slots_cols*ICON_SIZE; slots_area.h = slots_rows*ICON_SIZE; SDL_Rect tabs_area = slots_area; int tabheight = tabControl->getTabHeight(); tabControl->setMainArea(tabs_area.x, tabs_area.y-tabheight, tabs_area.w, tabs_area.h+tabheight); tabControl->updateHeader(); stock[VENDOR_BUY].init( VENDOR_SLOTS, slots_area, ICON_SIZE, slots_cols); stock[VENDOR_SELL].init( VENDOR_SLOTS, slots_area, ICON_SIZE, slots_cols); closeButton->pos.x = window_area.x+close_pos.x; closeButton->pos.y = window_area.y+close_pos.y; for (unsigned i = 0; i < VENDOR_SLOTS; i++) { tablist.add(stock[VENDOR_BUY].slots[i]); } for (unsigned i = 0; i < VENDOR_SLOTS; i++) { tablist.add(stock[VENDOR_SELL].slots[i]); } } void MenuVendor::loadMerchant(const std::string&) { } void MenuVendor::logic() { if (!visible) return; if (NO_MOUSE) { tablist.logic(); } // make shure keyboard navigation leads us to correct tab for (unsigned i = 0; i < VENDOR_SLOTS; i++) { if (stock[VENDOR_BUY].slots[i]->in_focus) { tabControl->setActiveTab(0); activetab = 0; break; } else if (stock[VENDOR_SELL].slots[i]->in_focus) { tabControl->setActiveTab(1); activetab = 1; break; } } if (closeButton->checkClick()) { visible = false; snd->play(sfx_close); } } void MenuVendor::tabsLogic() { tabControl->logic(); activetab = tabControl->getActiveTab(); } void MenuVendor::setTab(int tab) { tabControl->setActiveTab(tab); activetab = tab; } void MenuVendor::render() { if (!visible) return; SDL_Rect src; SDL_Rect dest; // background src.x = 0; src.y = 0; dest.x = window_area.x; dest.y = window_area.y; src.w = dest.w = window_area.w; src.h = dest.h = window_area.h; SDL_BlitSurface(background, &src, screen, &dest); // close button closeButton->render(); // text overlay if (!title.hidden) { WidgetLabel label; label.set(window_area.x+title.x, window_area.y+title.y, title.justify, title.valign, msg->get("Vendor") + " - " + npc->name, color_normal, title.font_style); label.render(); } // render tabs tabControl->render(); // show stock stock[activetab].render(); } /** * Start dragging a vendor item * Players can drag an item to their inventory to purchase. */ ItemStack MenuVendor::click(Point position) { ItemStack stack = stock[activetab].click(position); saveInventory(); return stack; } /** * Cancel the dragging initiated by the clic() */ void MenuVendor::itemReturn(ItemStack stack) { items->playSound(stack.item); stock[activetab].itemReturn(stack); saveInventory(); } void MenuVendor::add(ItemStack stack) { // Remove the first item stack to make room if (stock[VENDOR_SELL].full(stack)) { stock[VENDOR_SELL][0].item = 0; stock[VENDOR_SELL][0].quantity = 0; sort(VENDOR_SELL); } items->playSound(stack.item); stock[VENDOR_SELL].add(stack); saveInventory(); } TooltipData MenuVendor::checkTooltip(Point position) { int vendor_view = (activetab == VENDOR_BUY) ? VENDOR_BUY : VENDOR_SELL; return stock[activetab].checkTooltip(position, stats, vendor_view); } /** * Several NPCs vendors can share this menu. * When the player talks to a new NPC, apply that NPC's inventory */ void MenuVendor::setInventory() { for (unsigned i=0; i<VENDOR_SLOTS; i++) { stock[VENDOR_BUY][i] = npc->stock[i]; stock[VENDOR_SELL][i] = buyback_stock[i]; } sort(VENDOR_BUY); sort(VENDOR_SELL); } /** * Save changes to the inventory back to the NPC * For persistent stock amounts and buyback (at least until * the player leaves this map) */ void MenuVendor::saveInventory() { for (unsigned i=0; i<VENDOR_SLOTS; i++) { if (npc) npc->stock[i] = stock[VENDOR_BUY][i]; buyback_stock[i] = stock[VENDOR_SELL][i]; } } void MenuVendor::sort(int type) { for (unsigned i=0; i<VENDOR_SLOTS; i++) { if (stock[type][i].item == 0) { for (unsigned j=i; j<VENDOR_SLOTS; j++) { if (stock[type][j].item != 0) { stock[type][i] = stock[type][j]; stock[type][j].item = 0; stock[type][j].quantity = 0; break; } } } } } int MenuVendor::getRowsCount() { return slots_rows; } MenuVendor::~MenuVendor() { SDL_FreeSurface(background); delete closeButton; delete tabControl; } ��������������������������������������������������������������������flare-engine-0.19/src/MenuVendor.h������������������������������������������������������������������0000664�0000000�0000000�00000003471�12247171015�0017026�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MenuVendor */ #pragma once #ifndef MENU_VENDOR_H #define MENU_VENDOR_H #include "CommonIncludes.h" #include "MenuItemStorage.h" #include "WidgetLabel.h" class ItemStorage; class NPC; class StatBlock; class WidgetButton; class WidgetTabControl; class MenuVendor : public Menu { private: StatBlock *stats; WidgetButton *closeButton; WidgetTabControl *tabControl; unsigned VENDOR_SLOTS; // label and widget positions Point close_pos; LabelInfo title; int slots_cols; int slots_rows; int activetab; SDL_Color color_normal; public: MenuVendor(StatBlock *stats); ~MenuVendor(); NPC *npc; ItemStorage buyback_stock; MenuItemStorage stock[2]; // items the vendor currently has in stock void update(); void loadMerchant(const std::string&); void logic(); void tabsLogic(); void setTab(int tab); int getTab() {return activetab;} void render(); ItemStack click(Point position); void itemReturn(ItemStack stack); void add(ItemStack stack); TooltipData checkTooltip(Point position); void setInventory(); void saveInventory(); void sort(int type); int getRowsCount(); bool talker_visible; SDL_Rect slots_area; TabList tablist; }; #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MessageEngine.cpp�������������������������������������������������������������0000664�0000000�0000000�00000007631�12247171015�0020013�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Thane Brimhall Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MessageEngine * * The MessageEngine class loads all of FLARE's internal messages from a configuration file * and returns them as human-readable strings. * * This class is primarily used for making sure FLARE is flexible and translatable. */ #include "CommonIncludes.h" #include "GetText.h" #include "SharedResources.h" #include "Settings.h" using namespace std; MessageEngine::MessageEngine() { GetText infile; vector<string> engineFiles = mods->list("languages/engine." + LANGUAGE + ".po"); if (engineFiles.size() == 0 && LANGUAGE != "en") fprintf(stderr, "Unable to open basic translation files located in languages/engine.%s.po\n", LANGUAGE.c_str()); for (unsigned i = 0; i < engineFiles.size(); ++i) { if (infile.open(engineFiles[i])) { while (infile.next() && !infile.fuzzy) messages.insert(pair<string,string>(infile.key, infile.val)); infile.close(); } } vector<string> dataFiles = mods->list("languages/data." + LANGUAGE + ".po"); if (dataFiles.size() == 0 && LANGUAGE != "en") fprintf(stderr, "Unable to open basic translation files located in languages/data.%s.po\n", LANGUAGE.c_str()); for (unsigned i = 0; i < dataFiles.size(); ++i) { if (infile.open(dataFiles[i])) { while (infile.next() && !infile.fuzzy) messages.insert(pair<string,string>(infile.key, infile.val)); infile.close(); } } } /* * Each of the get() functions returns the mapped value * They differ only on which variables they replace in the string - strings replace %s, integers replace %d */ string MessageEngine::get(const string& key) { string message = messages[key]; if (message == "") message = key; return unescape(message); } string MessageEngine::get(const string& key, int i) { string message = messages[key]; if (message == "") message = key; size_t index = message.find("%d"); if (index != string::npos) message = message.replace(index, 2, str(i)); return unescape(message); } string MessageEngine::get(const string& key, const string& s) { string message = messages[key]; if (message == "") message = key; size_t index = message.find("%s"); if (index != string::npos) message = message.replace(index, 2, s); return unescape(message); } string MessageEngine::get(const string& key, int i, const string& s) { string message = messages[key]; if (message == "") message = key; size_t index = message.find("%d"); if (index != string::npos) message = message.replace(index, 2, str(i)); index = message.find("%s"); if (index != string::npos) message = message.replace(index, 2, s); return unescape(message); } string MessageEngine::get(const string& key, int i, int j) { string message = messages[key]; if (message == "") message = key; size_t index = message.find("%d"); if (index != string::npos) message = message.replace(index, 2, str(i)); index = message.find("%d"); if (index != string::npos) message = message.replace(index, 2, str(j)); return unescape(message); } // Changes an int into a string string MessageEngine::str(int i) { stringstream ss; ss << i; return ss.str(); } // unescape c formatted string string MessageEngine::unescape(string val) { // unescape percentage %% to % size_t pos; while ((pos = val.find("%%")) != string::npos) val = val.replace(pos, 2, "%"); return val; } �������������������������������������������������������������������������������������������������������flare-engine-0.19/src/MessageEngine.h���������������������������������������������������������������0000664�0000000�0000000�00000002744�12247171015�0017460�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Thane Brimhall Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class MessageEngine * * The MessageEngine class allows translation of messages in FLARE by comparing them to * .po files in a format similar to gettext. * * This class is primarily used for making sure FLARE is flexible and translatable. */ #pragma once #ifndef MESSAGE_ENGINE_H #define MESSAGE_ENGINE_H #include "CommonIncludes.h" class MessageEngine { private: std::map<std::string,std::string> messages; std::string str(int i); std::string unescape(std::string msg); public: MessageEngine(); std::string get(const std::string& key); std::string get(const std::string& key, int i); std::string get(const std::string& key, const std::string& s); std::string get(const std::string& key, int i, const std::string& s); std::string get(const std::string& key, int i, int j); }; #endif ����������������������������flare-engine-0.19/src/ModManager.cpp����������������������������������������������������������������0000664�0000000�0000000�00000014204�12247171015�0017305�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "CommonIncludes.h" #include "ModManager.h" #include "Settings.h" #include "UtilsFileSystem.h" #include "UtilsParsing.h" using namespace std; ModManager::ModManager() { loc_cache.clear(); mod_dirs.clear(); mod_list.clear(); vector<string> mod_dirs_other; getDirList(PATH_DEFAULT_DATA + "mods", mod_dirs); getDirList(PATH_DEFAULT_USER + "mods", mod_dirs_other); getDirList(PATH_DATA + "mods", mod_dirs_other); getDirList(PATH_USER + "mods", mod_dirs_other); for (unsigned i=0; i<mod_dirs_other.size(); ++i) { if (find(mod_dirs.begin(), mod_dirs.end(), mod_dirs_other[i]) == mod_dirs.end()) mod_dirs.push_back(mod_dirs_other[i]); } loadModList(); } /** * The mod list is in either: * 1. [PATH_CONF]/mods.txt * 2. [PATH_DATA]/mods/mods.txt * The mods.txt file shows priority/load order for mods * * File format: * One mod folder name per line * Later mods override previous mods */ void ModManager::loadModList() { ifstream infile; string line; string starts_with; bool found_any_mod = false; // Add the fallback mod by default // Note: if a default mod is not found in mod_dirs, the game will exit if (find(mod_dirs.begin(), mod_dirs.end(), FALLBACK_MOD) != mod_dirs.end()) { mod_list.push_back(FALLBACK_MOD); found_any_mod = true; } // Add all other mods. string place1 = PATH_CONF + "mods.txt"; string place2 = PATH_DATA + "mods/mods.txt"; infile.open(place1.c_str(), ios::in); if (!infile.is_open()) { infile.open(place2.c_str(), ios::in); } if (!infile.is_open()) { fprintf(stderr, "Error during ModManager::loadModList() -- couldn't open mods.txt, to be located at \n"); fprintf(stderr, "%s\n%s\n\n", place1.c_str(), place2.c_str()); } while (infile.good()) { line = getLine(infile); // skip ahead if this line is empty if (line.length() == 0) continue; // skip comments starts_with = line.at(0); if (starts_with == "#") continue; // add the mod if it exists in the mods folder if (find(mod_dirs.begin(), mod_dirs.end(), line) != mod_dirs.end()) { mod_list.push_back(line); found_any_mod = true; } else { fprintf(stderr, "Mod \"%s\" not found, skipping\n", line.c_str()); } } infile.close(); if (!found_any_mod && mod_list.size() == 1) { fprintf(stderr, "Couldn't locate any Flare mod. "); fprintf(stderr, "Check if the game data are installed correctly. "); fprintf(stderr, "Expected to find the data in the $XDG_DATA_DIRS path, "); fprintf(stderr, "in /usr/local/share/flare/mods, "); fprintf(stderr, "or in the same folder as the executable. "); fprintf(stderr, "Try placing the mods folder in one of these locations.\n"); } } /** * Find the location (mod file name) for this data file. * Use private loc_cache to prevent excessive disk I/O */ string ModManager::locate(const string& filename) { // set some flags if directories are identical bool uniq_path_data = PATH_USER != PATH_DATA; bool uniq_path_default_user = PATH_USER != PATH_DEFAULT_USER && PATH_DATA != PATH_DEFAULT_USER; bool uniq_path_default_data = PATH_USER != PATH_DEFAULT_DATA && PATH_DATA != PATH_DEFAULT_DATA && PATH_DEFAULT_USER != PATH_DEFAULT_DATA; // if we have this location already cached, return it if (loc_cache.find(filename) != loc_cache.end()) { return loc_cache[filename]; } // search through mods for the first instance of this filename string test_path; for (unsigned int i = mod_list.size(); i > 0; i--) { test_path = PATH_USER + "mods/" + mod_list[i-1] + "/" + filename; if (fileExists(test_path)) { loc_cache[filename] = test_path; return test_path; } if (uniq_path_data) { test_path = PATH_DATA + "mods/" + mod_list[i-1] + "/" + filename; if (fileExists(test_path)) { loc_cache[filename] = test_path; return test_path; } } if (uniq_path_default_user) { test_path = PATH_DEFAULT_USER + "mods/" + mod_list[i-1] + "/" + filename; if (fileExists(test_path)) { loc_cache[filename] = test_path; return test_path; } } if (uniq_path_default_data) { test_path = PATH_DEFAULT_DATA + "mods/" + mod_list[i-1] + "/" + filename; if (fileExists(test_path)) { loc_cache[filename] = test_path; return test_path; } } } // all else failing, simply return the filename return PATH_DATA + filename; } void amendPathToVector(const string &path, std::vector<std::string> &vec) { if (pathExists(path)) { if (isDirectory(path)) { getFileList(path, "txt", vec); } else { vec.push_back(path); } } } vector<string> ModManager::list(const string &path) { // set some flags if directories are identical bool uniq_path_data = PATH_USER != PATH_DATA; bool uniq_path_default_user = PATH_USER != PATH_DEFAULT_USER && PATH_DATA != PATH_DEFAULT_USER; bool uniq_path_default_data = PATH_USER != PATH_DEFAULT_DATA && PATH_DATA != PATH_DEFAULT_DATA && PATH_DEFAULT_USER != PATH_DEFAULT_DATA; vector<string> ret; string test_path = PATH_DATA + path; amendPathToVector(test_path, ret); for (unsigned int i = 0; i < mod_list.size(); ++i) { if (uniq_path_default_data) { test_path = PATH_DEFAULT_DATA + "mods/" + mod_list[i] + "/" + path; amendPathToVector(test_path, ret); } if (uniq_path_default_user) { test_path = PATH_DEFAULT_USER + "mods/" + mod_list[i] + "/" + path; amendPathToVector(test_path, ret); } if (uniq_path_data) { test_path = PATH_DATA + "mods/" + mod_list[i] + "/" + path; amendPathToVector(test_path, ret); } test_path = PATH_USER + "mods/" + mod_list[i] + "/" + path; amendPathToVector(test_path, ret); } return ret; } ModManager::~ModManager() { } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/ModManager.h������������������������������������������������������������������0000664�0000000�0000000�00000003140�12247171015�0016747�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /* class ModManager ModManager maintains a list of active mods and provides functions for checking mods in priority order when loading data files. */ #pragma once #ifndef MOD_MANAGER_H #define MOD_MANAGER_H #define FALLBACK_MOD "default" #include "CommonIncludes.h" class ModManager { private: void loadModList(); std::map<std::string,std::string> loc_cache; public: ModManager(); ~ModManager(); // Returns the filename within the latest mod, in which the provided generic // filename was found. std::string locate(const std::string& filename); // Returns a list of filenames, going through all mods, in which the provided // generic filename is found. // The list is ordered the same way as locate() is searching for files, so // files being at later positions in the list should overwrite previous files std::vector<std::string> list(const std::string& path); std::vector<std::string> mod_dirs; std::vector<std::string> mod_list; }; #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/NPC.cpp�����������������������������������������������������������������������0000664�0000000�0000000�00000024007�12247171015�0015715�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012-2013 Henrik Andersson Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class NPC */ #include "NPC.h" #include "Animation.h" #include "AnimationSet.h" #include "AnimationManager.h" #include "CampaignManager.h" #include "FileParser.h" #include "ItemManager.h" #include "SharedResources.h" #include "UtilsParsing.h" #include "SharedGameResources.h" using namespace std; ItemStorage stock; std::vector<SoundManager::SoundID> vox_intro; std::vector<SoundManager::SoundID> vox_quests; std::vector<std::vector<Event_Component> > dialog; NPC::NPC() : Entity() , name("") , gfx("") , pos() , level(1) , direction(0) , portrait(NULL) , talker(false) , vendor(false) , stock() , stock_count(0) , vox_intro() , vox_quests() , dialog() { stock.init(NPC_VENDOR_MAX_STOCK); } /** * NPCs are stored in simple config files * * @param npc_id Config file loaded at npcs/[npc_id].txt */ void NPC::load(const string& npc_id, int hero_level) { FileParser infile; ItemStack stack; string filename_portrait = ""; if (infile.open("npcs/" + npc_id + ".txt")) { while (infile.next()) { if (infile.section == "dialog") { if (infile.new_section) { dialog.push_back(vector<Event_Component>()); } Event_Component e; e.type = infile.key; if (infile.key == "him" || infile.key == "her") e.s = msg->get(infile.val); else if (infile.key == "you") e.s = msg->get(infile.val); else if (infile.key == "voice") { e.x = loadSound(infile.val, NPC_VOX_QUEST); } else if (infile.key == "topic") { e.s = msg->get(infile.val); } else if (infile.key == "group") { e.s = infile.val; } else if (infile.key == "allow_movement") { e.s = infile.val; } else { EventManager::loadEventComponent(infile, NULL, &e); } dialog.back().push_back(e); } else { filename = npc_id; if (infile.key == "name") { name = msg->get(infile.val); } else if (infile.key == "level") { if (infile.val == "hero") level = hero_level; else level = toInt(infile.val); } else if (infile.key == "gfx") { gfx = infile.val; } // handle talkers else if (infile.key == "talker") { if (infile.val == "true") talker = true; } else if (infile.key == "portrait") { filename_portrait = infile.val; } // handle vendors else if (infile.key == "vendor") { if (infile.val == "true") vendor = true; } else if (infile.key == "constant_stock") { stack.quantity = 1; while (infile.val != "") { stack.item = toInt(infile.nextValue()); stock.add(stack); } } else if (infile.key == "status_stock") { if (camp->checkStatus(infile.nextValue())) { stack.quantity = 1; while (infile.val != "") { stack.item = toInt(infile.nextValue()); stock.add(stack); } } } // handle vocals else if (infile.key == "vox_intro") { loadSound(infile.val, NPC_VOX_INTRO); } } } infile.close(); } loadGraphics(filename_portrait); } void NPC::loadGraphics(const string& filename_portrait) { if (gfx != "") { anim->increaseCount(gfx); animationSet = anim->getAnimationSet(gfx); activeAnimation = animationSet->getAnimation(); } if (filename_portrait != "") portrait = loadGraphicSurface("images/portraits/" + filename_portrait + ".png", "Couldn't load NPC portrait", false, true); } /** * filename assumes the file is in soundfx/npcs/ * type is a const int enum, see NPC.h * returns -1 if not loaded or error. * returns index in specific vector where to be found. */ int NPC::loadSound(const string& fname, int type) { SoundManager::SoundID a = snd->load(fname, "NPC voice"); if (!a) return -1; if (type == NPC_VOX_INTRO) { vox_intro.push_back(a); return vox_intro.size() - 1; } if (type == NPC_VOX_QUEST) { vox_quests.push_back(a); return vox_quests.size() - 1; } return -1; } void NPC::logic() { activeAnimation->advanceFrame(); } /** * type is a const int enum, see NPC.h */ bool NPC::playSound(int type, int id) { if (type == NPC_VOX_INTRO) { int roll; if (vox_intro.empty()) return false; roll = rand() % vox_intro.size(); snd->play(vox_intro[roll], "NPC_VOX"); return true; } if (type == NPC_VOX_QUEST) { if (id < 0 || id >= (int)vox_quests.size()) return false; snd->play(vox_quests[id], "NPC_VOX"); return true; } return false; } /** * get list of available dialogs with NPC */ void NPC::getDialogNodes(std::vector<int> &result) { result.clear(); if (!talker) return; std::string group; typedef std::vector<int> Dialogs; typedef std::map<std::string, Dialogs > DialogGroups; DialogGroups groups; for (int i=dialog.size()-1; i>=0; i--) { bool is_available = true; bool is_grouped = false; for (unsigned int j=0; j<dialog[i].size(); j++) { if (dialog[i][j].type == "requires_status") { if (camp->checkStatus(dialog[i][j].s)) continue; is_available = false; break; } else if (dialog[i][j].type == "requires_not_status") { if (!camp->checkStatus(dialog[i][j].s)) continue; is_available = false; break; } else if (dialog[i][j].type == "requires_currency") { if (camp->checkCurrency(dialog[i][j].x)) continue; is_available = false; break; } else if (dialog[i][j].type == "requires_item") { if (camp->checkItem(dialog[i][j].x)) continue; is_available = false; break; } else if (dialog[i][j].type == "requires_level") { if (camp->hero->level >= dialog[i][j].x) continue; is_available = false; break; } else if (dialog[i][j].type == "requires_not_level") { if (camp->hero->level < dialog[i][j].x) continue; is_available = false; break; } else if (dialog[i][j].type == "group") { is_grouped = true; group = dialog[i][j].s; } } if (is_available) { if (!is_grouped) { result.push_back(i); } else { DialogGroups::iterator it; it = groups.find(group); if (it == groups.end()) { groups.insert(DialogGroups::value_type(group, Dialogs())); } else it->second.push_back(i); } } } /* Iterate over dialoggroups and roll a dialog to add to result */ DialogGroups::iterator it; it = groups.begin(); if (it == groups.end()) return; while (it != groups.end()) { /* roll a dialog for this group and add to result */ int di = it->second[rand() % it->second.size()]; result.push_back(di); ++it; } } std::string NPC::getDialogTopic(unsigned int dialog_node) { if (!talker) return ""; for (unsigned int j=0; j<dialog[dialog_node].size(); j++) { if (dialog[dialog_node][j].type == "topic") return dialog[dialog_node][j].s; } return ""; } /** * Check if the hero can move during this dialog branch */ bool NPC::checkMovement(unsigned int dialog_node) { for (unsigned int i=0; i<dialog[dialog_node].size(); i++) { if (dialog[dialog_node][i].type == "allow_movement") return toBool(dialog[dialog_node][i].s); } return true; } /** * Process the current dialog * * Return false if the dialog has ended */ bool NPC::processDialog(unsigned int dialog_node, unsigned int &event_cursor) { while (event_cursor < dialog[dialog_node].size()) { // we've already determined requirements are met, so skip these if (dialog[dialog_node][event_cursor].type == "requires_status") { // continue to next event component } else if (dialog[dialog_node][event_cursor].type == "requires_not_status") { // continue to next event component } else if (dialog[dialog_node][event_cursor].type == "requires_level") { // continue to next event component } else if (dialog[dialog_node][event_cursor].type == "requires_not_level") { // continue to next event component } else if (dialog[dialog_node][event_cursor].type == "requires_currency") { // continue to next event component } else if (dialog[dialog_node][event_cursor].type == "requires_item") { // continue to next event component } else if (dialog[dialog_node][event_cursor].type == "him") { return true; } else if (dialog[dialog_node][event_cursor].type == "her") { return true; } else if (dialog[dialog_node][event_cursor].type == "you") { return true; } else if (dialog[dialog_node][event_cursor].type == "voice") { playSound(NPC_VOX_QUEST, dialog[dialog_node][event_cursor].x); } else if (dialog[dialog_node][event_cursor].type == "") { // conversation ends return false; } event_cursor++; } return false; } void NPC::processEvent(unsigned int dialog_node, unsigned int cursor) { Event ev; if (cursor < dialog[dialog_node].size() && isDialogType(dialog[dialog_node][cursor].type)) { cursor++; } while (cursor < dialog[dialog_node].size() && !isDialogType(dialog[dialog_node][cursor].type)) { ev.components.push_back(dialog[dialog_node][cursor]); cursor++; } EventManager::executeEvent(ev); } Renderable NPC::getRender() { Renderable r = activeAnimation->getCurrentFrame(direction); r.map_pos.x = pos.x; r.map_pos.y = pos.y; return r; } bool NPC::isDialogType(const std::string &type) { return type == "him" || type == "her" || type == "you" || type == "voice"; } NPC::~NPC() { if (gfx != "") { anim->decreaseCount(gfx); } if (portrait != NULL) SDL_FreeSurface(portrait); while (!vox_intro.empty()) { snd->unload(vox_intro.back()); vox_intro.pop_back(); } while (!vox_quests.empty()) { snd->unload(vox_quests.back()); vox_quests.pop_back(); } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/NPC.h�������������������������������������������������������������������������0000664�0000000�0000000�00000004333�12247171015�0015362�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class NPC */ #pragma once #ifndef NPC_H #define NPC_H #include "CommonIncludes.h" #include "Entity.h" #include "ItemStorage.h" #include "Utils.h" const int NPC_VENDOR_MAX_STOCK = 80; const int NPC_VOX_INTRO = 0; const int NPC_VOX_QUEST = 1; const int NPC_NO_DIALOG_AVAIL = -1; class NPC : public Entity { private: bool isDialogType(const std::string &type); public: NPC(); ~NPC(); void load(const std::string& npc_id, int hero_level); void loadGraphics(const std::string& filename_portrait); int loadSound(const std::string& fname, int type); void logic(); bool playSound(int type, int id=-1); void getDialogNodes(std::vector<int> &result); std::string getDialogTopic(unsigned int dialog_node); bool checkMovement(unsigned int dialog_node); bool processDialog(unsigned int dialog_node, unsigned int& event_cursor); void processEvent(unsigned int dialog_node, unsigned int cursor); virtual Renderable getRender(); // general info std::string name; std::string filename; std::string gfx; // filename of sprite. FPoint pos; // map position int level; // used in determining item quality int direction; // talker info SDL_Surface *portrait; bool talker; // vendor info bool vendor; ItemStorage stock; int stock_count; // vocals std::vector<SoundManager::SoundID> vox_intro; std::vector<SoundManager::SoundID> vox_quests; // story and dialog options // outer vector is addressing the dialog and the inner vector is // addressing the events during one dialog std::vector<std::vector<Event_Component> > dialog; }; #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/NPCManager.cpp����������������������������������������������������������������0000664�0000000�0000000�00000011101�12247171015�0017177�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class NPCManager * * NPCs which are not combatative enemies are handled by this Manager. * Most commonly this involves vendor and conversation townspeople. */ #include "Animation.h" #include "FileParser.h" #include "ItemManager.h" #include "NPCManager.h" #include "NPC.h" #include "SharedResources.h" #include "StatBlock.h" #include "WidgetTooltip.h" #include "SharedGameResources.h" #include "UtilsParsing.h" #include <limits> using namespace std; NPCManager::NPCManager(StatBlock *_stats) : tip(new WidgetTooltip()) , stats(_stats) , tip_buf() { FileParser infile; // load tooltip_margin from engine config file if (infile.open("engine/tooltips.txt")) { while (infile.next()) { if (infile.key == "npc_tooltip_margin") { tooltip_margin = toInt(infile.val); } } infile.close(); } } void NPCManager::addRenders(std::vector<Renderable> &r) { for (unsigned i=0; i<npcs.size(); i++) { r.push_back(npcs[i]->getRender()); } } void NPCManager::handleNewMap() { Map_NPC mn; ItemStack item_roll; // remove existing NPCs for (unsigned i=0; i<npcs.size(); i++) delete(npcs[i]); npcs.clear(); // read the queued NPCs in the map file while (!mapr->npcs.empty()) { mn = mapr->npcs.front(); mapr->npcs.pop(); for (unsigned i = 0; i < mn.requires_status.size(); ++i) if (!camp->checkStatus(mn.requires_status[i])) continue; for (unsigned i = 0; i < mn.requires_not_status.size(); ++i) if (camp->checkStatus(mn.requires_not_status[i])) continue; NPC *npc = new NPC(); npc->load(mn.id, stats->level); npc->pos.x = mn.pos.x; npc->pos.y = mn.pos.y; npc->stock.sort(); npcs.push_back(npc); } } void NPCManager::logic() { for (unsigned i=0; i<npcs.size(); i++) { npcs[i]->logic(); } } int NPCManager::getID(std::string npcName) { for (unsigned i=0; i<npcs.size(); i++) { if (npcs[i]->filename == npcName) return i; } return -1; } int NPCManager::checkNPCClick(Point mouse, FPoint cam) { Point p; SDL_Rect r; for (unsigned i=0; i<npcs.size(); i++) { p = map_to_screen(npcs[i]->pos.x, npcs[i]->pos.y, cam.x, cam.y); Renderable ren = npcs[i]->activeAnimation->getCurrentFrame(npcs[i]->direction); r.w = ren.src.w; r.h = ren.src.h; r.x = p.x - ren.offset.x; r.y = p.y - ren.offset.y; if (isWithin(r, mouse)) { return i; } } return -1; } int NPCManager::getNearestNPC(FPoint pos) { int nearest = -1; float best_distance = std::numeric_limits<float>::max(); for (unsigned i=0; i<npcs.size(); i++) { float distance = calcDist(pos, npcs[i]->pos); if (distance < best_distance) { best_distance = distance; nearest = i; } } if (best_distance > INTERACT_RANGE) nearest = -1; return nearest; } /** * On mouseover, display NPC's name */ void NPCManager::renderTooltips(FPoint cam, Point mouse, int nearest) { Point p; SDL_Rect r; int id = -1; for (unsigned i=0; i<npcs.size(); i++) { if (NO_MOUSE && nearest != -1 && (unsigned)nearest != i) continue; p = map_to_screen(npcs[i]->pos.x, npcs[i]->pos.y, cam.x, cam.y); Renderable ren = npcs[i]->activeAnimation->getCurrentFrame(npcs[i]->direction); r.w = ren.src.w; r.h = ren.src.h; r.x = p.x - ren.offset.x; r.y = p.y - ren.offset.y; if (NO_MOUSE && nearest != -1 && (unsigned)nearest == i) { id = nearest; break; } else if (!NO_MOUSE && isWithin(r, mouse)) { id = i; break; } } if (id != -1 && TOOLTIP_CONTEXT != TOOLTIP_MENU) { // adjust dest.y so that the tooltip floats above the item p.y -= tooltip_margin; // use current tip or make a new one? if (!tip_buf.compareFirstLine(npcs[id]->name)) { tip_buf.clear(); tip_buf.addText(npcs[id]->name); } tip->render(tip_buf, p, STYLE_TOPLABEL); TOOLTIP_CONTEXT = TOOLTIP_MAP; } else if (TOOLTIP_CONTEXT != TOOLTIP_MENU) { TOOLTIP_CONTEXT = TOOLTIP_NONE; } } NPCManager::~NPCManager() { for (unsigned i=0; i<npcs.size(); i++) { delete npcs[i]; } tip_buf.clear(); delete tip; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/NPCManager.h������������������������������������������������������������������0000664�0000000�0000000�00000002746�12247171015�0016663�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class NPCManager * * NPCs which are not combatative enemies are handled by this Manager. * Most commonly this involves vendor and conversation townspeople. */ #pragma once #ifndef NPC_MANAGER_H #define NPC_MANAGER_H #include "CommonIncludes.h" #include "TooltipData.h" class StatBlock; class NPC; class WidgetTooltip; class NPCManager { private: WidgetTooltip *tip; StatBlock *stats; TooltipData tip_buf; int tooltip_margin; public: NPCManager(StatBlock *stats); NPCManager(const NPCManager ©); // not implemented ~NPCManager(); std::vector<NPC*> npcs; void handleNewMap(); void logic(); void addRenders(std::vector<Renderable> &r); int getID(std::string npcName); int checkNPCClick(Point mouse, FPoint cam); int getNearestNPC(FPoint pos); void renderTooltips(FPoint cam, Point mouse, int nearest); }; #endif ��������������������������flare-engine-0.19/src/PowerManager.cpp��������������������������������������������������������������0000664�0000000�0000000�00000133300�12247171015�0017661�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class PowerManager */ #include "PowerManager.h" #include "Animation.h" #include "AnimationSet.h" #include "AnimationManager.h" #include "FileParser.h" #include "Hazard.h" #include "SharedResources.h" #include "Settings.h" #include "SharedResources.h" #include "StatBlock.h" #include "MapCollision.h" #include "Utils.h" #include "UtilsFileSystem.h" #include "UtilsMath.h" #include "UtilsParsing.h" #include <cmath> #include <climits> using namespace std; /** * PowerManager constructor */ PowerManager::PowerManager() : collider(NULL) , log_msg("") , used_items() , used_equipped_items() { loadEffects(); loadPowers(); } void PowerManager::loadEffects() { FileParser infile; if (!infile.open("powers/effects.txt", true, false)) return; std::string input_name = ""; bool skippingEntry = false; while (infile.next()) { // name needs to be the first component of each power. That is how we write // data to the correct power. if (infile.key == "name") { // @ATTR name|string|Uniq identifier for the effect definition. input_name = infile.val; skippingEntry = input_name == ""; if (skippingEntry) fprintf(stderr, "Effect without a name, skipping\n"); continue; } if (skippingEntry) continue; if (infile.key == "type") { // @ATTR type|string|Defines the type of effect effects[input_name].type = infile.val; } else if (infile.key == "icon") { // @ATTR icon|integer|The icon to visually represent the effect in the status area effects[input_name].icon = toInt(infile.val); } else if (infile.key == "animation") { // @ATTR animation|string|The name of effect animation. effects[input_name].animation = infile.val; } else if (infile.key == "additive") { // @ATTR additive|bool|Effect is additive effects[input_name].additive = toBool(infile.val); } else if (infile.key == "render_above") { // @ATTR render_above|bool|Effect is rendered above effects[input_name].render_above = toBool(infile.val); } } infile.close(); } void PowerManager::loadPowers() { FileParser infile; // @CLASS Power|Description about powers... if (!infile.open("powers/powers.txt", true, false)) return; int input_id = 0; bool skippingEntry = false; while (infile.next()) { // id needs to be the first component of each power. That is how we write // data to the correct power. if (infile.key == "id") { // @ATTR id|integer|Uniq identifier for the power definition. input_id = toInt(infile.val); skippingEntry = input_id < 1; if (skippingEntry) fprintf(stderr, "Power index out of bounds 1-%d, skipping\n", INT_MAX); if (static_cast<int>(powers.size()) < input_id + 1) powers.resize(input_id + 1); continue; } if (skippingEntry) continue; if (infile.key == "type") { // @ATTR type|[fixed:missile:repeater:spawn:transform]|Defines the type of power definiton if (infile.val == "fixed") powers[input_id].type = POWTYPE_FIXED; else if (infile.val == "missile") powers[input_id].type = POWTYPE_MISSILE; else if (infile.val == "repeater") powers[input_id].type = POWTYPE_REPEATER; else if (infile.val == "spawn") powers[input_id].type = POWTYPE_SPAWN; else if (infile.val == "transform") powers[input_id].type = POWTYPE_TRANSFORM; else fprintf(stderr, "unknown type %s\n", infile.val.c_str()); } else if (infile.key == "name") // @ATTR name|string|The name of the power powers[input_id].name = msg->get(infile.val); else if (infile.key == "description") // @ATTR description|string|Description of the power powers[input_id].description = msg->get(infile.val); else if (infile.key == "icon") // @ATTR icon|string|The icon to visually represent the power eg. in skill tree or action bar. powers[input_id].icon = toInt(infile.val); else if (infile.key == "new_state") { // @ATTR new_state|string|When power is used, hero or enemy will change to this state. Must be one of the states [block, instant, user defined] if (infile.val == "block") powers[input_id].new_state = POWSTATE_BLOCK; else if (infile.val == "instant") powers[input_id].new_state = POWSTATE_INSTANT; else { powers[input_id].new_state = POWSTATE_ATTACK; powers[input_id].attack_anim = infile.val; } } else if (infile.key == "face") // @ATTR face|bool|Power will make hero or enemy to face the target location. powers[input_id].face = toBool(infile.val); else if (infile.key == "source_type") { // @ATTR source_type|[hero:neutral:enemy]| if (infile.val == "hero") powers[input_id].source_type = SOURCE_TYPE_HERO; else if (infile.val == "neutral") powers[input_id].source_type = SOURCE_TYPE_NEUTRAL; else if (infile.val == "enemy") powers[input_id].source_type = SOURCE_TYPE_ENEMY; else fprintf(stderr, "unknown source_type %s\n", infile.val.c_str()); } else if (infile.key == "beacon") // @ATTR beacon|bool|True if enemy is calling its allies. powers[input_id].beacon = toBool(infile.val); else if (infile.key == "count") // @ATTR count|integer|The count of hazards/effect or spawns to be created by this power. powers[input_id].count = toInt(infile.val); else if (infile.key == "passive") // @ATTR passive|bool|If power is unlocked when the hero or enemy spawns it will be automatically activated. powers[input_id].passive = toBool(infile.val); else if (infile.key == "passive_trigger") { // @ATTR passive_trigger|[on_block:on_hit:on_halfdeath:on_joincombat:on_death]|This will only activate a passive power under a certain condition. if (infile.val == "on_block") powers[input_id].passive_trigger = TRIGGER_BLOCK; else if (infile.val == "on_hit") powers[input_id].passive_trigger = TRIGGER_HIT; else if (infile.val == "on_halfdeath") powers[input_id].passive_trigger = TRIGGER_HALFDEATH; else if (infile.val == "on_joincombat") powers[input_id].passive_trigger = TRIGGER_JOINCOMBAT; else if (infile.val == "on_death") powers[input_id].passive_trigger = TRIGGER_DEATH; else fprintf(stderr, "unknown passive trigger %s\n", infile.val.c_str()); } // power requirements else if (infile.key == "requires_flags") { infile.val = infile.val + ','; std::string flag = eatFirstString(infile.val,','); while (flag != "") { powers[input_id].requires_flags.insert(flag); flag = eatFirstString(infile.val,','); } } else if (infile.key == "requires_mp") // @ATTR requires_mp|integer|Restrict power usage to a specified MP level. powers[input_id].requires_mp = toInt(infile.val); else if (infile.key == "requires_hp") // @ATTR requires_hp|integer|Restrict power usage to a specified HP level. powers[input_id].requires_hp = toInt(infile.val); else if (infile.key == "sacrifice") // @ATTR sacrifice|bool| powers[input_id].sacrifice = toBool(infile.val); else if (infile.key == "requires_los") // @ATTR requires_los|bool|Requires a line-of-sight to target. powers[input_id].requires_los = toBool(infile.val); else if (infile.key == "requires_empty_target") // @ATTR requires_empty_target|bool|The power can only be cast when target tile is empty. powers[input_id].requires_empty_target = toBool(infile.val); else if (infile.key == "requires_item") // @ATTR requires_item|item_id|Requires a specific item in inventory. powers[input_id].requires_item = toInt(infile.val); else if (infile.key == "requires_equipped_item") // @ATTR requires_equipped_item|item_id|Requires a specific item to be equipped on hero. powers[input_id].requires_equipped_item = toInt(infile.val); else if (infile.key == "requires_targeting") // @ATTR requires_targeting|bool|Power is only used when targeting using click-to-target. powers[input_id].requires_targeting = toBool(infile.val); else if (infile.key == "cooldown") // @ATTR cooldown|duration|Specify the duration for cooldown of the power. powers[input_id].cooldown = parse_duration(infile.val); // animation info else if (infile.key == "animation") // @ATTR animation|string|The name of power animation. powers[input_id].animation_name = infile.val; else if (infile.key == "soundfx") // @ATTR soundfx|string|Sound effect to play when use of power. powers[input_id].sfx_index = loadSFX(infile.val); else if (infile.key == "directional") // @ATTR directional|bool|The animation sprite sheet contains 8 directions, one per row. powers[input_id].directional = toBool(infile.val); else if (infile.key == "visual_random") // @ATTR visual_random|integer|The animation sprite sheet contains rows of random options powers[input_id].visual_random = toInt(infile.val); else if (infile.key == "visual_option") // @ATTR visual_option|integer|The animation sprite sheet containers rows of similar effects, use a specific option. powers[input_id].visual_option = toInt(infile.val); else if (infile.key == "aim_assist") // @ATTR aim_assist|bool|Power is aim assisted. powers[input_id].aim_assist = toBool(infile.val); else if (infile.key == "speed") // @ATTR speed|integer|The speed of missile hazard, the unit is defined as map units per frame. powers[input_id].speed = toFloat(infile.val) / MAX_FRAMES_PER_SEC; else if (infile.key == "lifespan") // @ATTR lifespan|duration|How long the hazard/animation lasts. powers[input_id].lifespan = parse_duration(infile.val); else if (infile.key == "floor") // @ATTR floor|bool|The hazard is drawn between the background and the object layer. powers[input_id].floor = toBool(infile.val); else if (infile.key == "complete_animation") // @ATTR complete_animation|bool| powers[input_id].complete_animation = toBool(infile.val); // hazard traits else if (infile.key == "use_hazard") // @ATTR use_hazard|bool|Power uses hazard. powers[input_id].use_hazard = toBool(infile.val); else if (infile.key == "no_attack") // @ATTR no_attack|bool| powers[input_id].no_attack = toBool(infile.val); else if (infile.key == "radius") // @ATTR radius|integer|Radius in pixels powers[input_id].radius = toFloat(infile.val); else if (infile.key == "base_damage") { // @ATTR base_damage|[melee:ranged:ment]| if (infile.val == "none") powers[input_id].base_damage = BASE_DAMAGE_NONE; else if (infile.val == "melee") powers[input_id].base_damage = BASE_DAMAGE_MELEE; else if (infile.val == "ranged") powers[input_id].base_damage = BASE_DAMAGE_RANGED; else if (infile.val == "ment") powers[input_id].base_damage = BASE_DAMAGE_MENT; else fprintf(stderr, "unknown base_damage %s\n", infile.val.c_str()); } else if (infile.key == "starting_pos") { // @ATTR starting_pos|[source, target, melee]|Start position for hazard if (infile.val == "source") powers[input_id].starting_pos = STARTING_POS_SOURCE; else if (infile.val == "target") powers[input_id].starting_pos = STARTING_POS_TARGET; else if (infile.val == "melee") powers[input_id].starting_pos = STARTING_POS_MELEE; else fprintf(stderr, "unknown starting_pos %s\n", infile.val.c_str()); } else if (infile.key == "multitarget") // @ATTR multitarget|bool| powers[input_id].multitarget = toBool(infile.val); else if (infile.key == "trait_armor_penetration") // @ATTR trait_armor_penetration|bool| powers[input_id].trait_armor_penetration = toBool(infile.val); else if (infile.key == "trait_avoidance_ignore") // @ATTR trait_avoidance_ignore|bool| powers[input_id].trait_avoidance_ignore = toBool(infile.val); else if (infile.key == "trait_crits_impaired") // @ATTR trait_crits_impaired|bool| powers[input_id].trait_crits_impaired = toInt(infile.val); else if (infile.key == "trait_elemental") { // @ATTR, trait_elemental|string| for (unsigned int i=0; i<ELEMENTS.size(); i++) { if (infile.val == ELEMENTS[i].name) powers[input_id].trait_elemental = i; } } else if (infile.key == "target_range") // @ATTR, target_range|float||The distance from the caster that the power can be activated powers[input_id].target_range = toFloat(infile.nextValue()); //steal effects else if (infile.key == "hp_steal") // @ATTR, hp_steal|integer|Percentage of damage to steal into HP powers[input_id].hp_steal = toInt(infile.val); else if (infile.key == "mp_steal") // @ATTR, mp_steal|integer|Percentage of damage to steal into MP powers[input_id].mp_steal = toInt(infile.val); //missile modifiers else if (infile.key == "missile_angle") // @ATTR missile_angle|integer|Angle of missile powers[input_id].missile_angle = toInt(infile.val); else if (infile.key == "angle_variance") // @ATTR angle_variance|integer|Percentage of variance added to missile angle powers[input_id].angle_variance = toInt(infile.val); else if (infile.key == "speed_variance") // @ATTR speed_variance|integer|Percentage of variance added to missile speed powers[input_id].speed_variance = toFloat(infile.val); //repeater modifiers else if (infile.key == "delay") // @ATTR delay|duration|Delay between repeats powers[input_id].delay = parse_duration(infile.val); // buff/debuff durations else if (infile.key == "transform_duration") // @ATTR transform_duration|duration|Duration for transform powers[input_id].transform_duration = toInt(infile.val); else if (infile.key == "manual_untransform") // @ATTR transform_duration|bool|Force manual untranform powers[input_id].manual_untransform = toBool(infile.val); else if (infile.key == "keep_equipment") // @ATTR keep_equipment|bool|Keep equipment while transformed powers[input_id].keep_equipment = toBool(infile.val); // buffs else if (infile.key == "buff") // @ATTR buff|bool| powers[input_id].buff= toBool(infile.val); else if (infile.key == "buff_teleport") // @ATTR buff_teleport|bool| powers[input_id].buff_teleport = toBool(infile.val); else if (infile.key == "buff_party") // @ATTR buff_part|bool| powers[input_id].buff_party = toBool(infile.val); else if (infile.key == "buff_party_power_id") // @ATTR buff_part_power_id|bool| powers[input_id].buff_party_power_id = toInt(infile.val); else if (infile.key == "post_effect") { // @ATTR post_effect|[effect_id, magnitude (integer), duration (integer)]|Post effect. infile.val = infile.val + ','; PostEffect pe; pe.id = eatFirstString(infile.val, ','); pe.magnitude = eatFirstInt(infile.val, ','); pe.duration = eatFirstInt(infile.val, ','); powers[input_id].post_effects.push_back(pe); } // pre and post power effects else if (infile.key == "post_power") // @ATTR post_power|power_id|Post power powers[input_id].post_power = toInt(infile.val); else if (infile.key == "wall_power") // @ATTR wall_power|power_id|Wall power powers[input_id].wall_power = toInt(infile.val); else if (infile.key == "allow_power_mod") // @ATTR allow_power_mod|bool|Allow power modifiers powers[input_id].allow_power_mod = toBool(infile.val); // spawn info else if (infile.key == "spawn_type") // @ATTR spawn_type|string|Type of spawn. powers[input_id].spawn_type = infile.val; else if (infile.key == "target_neighbor") // @ATTR target_neighbor|int|Neigbor target. powers[input_id].target_neighbor = toInt(infile.val); else if (infile.key == "spawn_limit") { // @ATTR spawn_limit|[fixed:stat:unlimited],stat[physical:mental:offense:defens]| infile.val = infile.val + ','; std::string mode = eatFirstString(infile.val,','); if (mode == "fixed") powers[input_id].spawn_limit_mode = SPAWN_LIMIT_MODE_FIXED; else if (mode == "stat") powers[input_id].spawn_limit_mode = SPAWN_LIMIT_MODE_STAT; else if (mode == "unlimited") powers[input_id].spawn_limit_mode = SPAWN_LIMIT_MODE_UNLIMITED; else fprintf(stderr, "unknown spawn_limit_mode %s\n", mode.c_str()); if(powers[input_id].spawn_limit_mode != SPAWN_LIMIT_MODE_UNLIMITED) { powers[input_id].spawn_limit_qty = eatFirstInt(infile.val,','); if(powers[input_id].spawn_limit_mode == SPAWN_LIMIT_MODE_STAT) { powers[input_id].spawn_limit_every = eatFirstInt(infile.val,','); std::string stat = eatFirstString(infile.val,','); if (stat == "physical") powers[input_id].spawn_limit_stat = SPAWN_LIMIT_STAT_PHYSICAL; else if (stat == "mental") powers[input_id].spawn_limit_stat = SPAWN_LIMIT_STAT_MENTAL; else if (stat == "offense") powers[input_id].spawn_limit_stat = SPAWN_LIMIT_STAT_OFFENSE; else if (stat == "defense") powers[input_id].spawn_limit_stat = SPAWN_LIMIT_STAT_DEFENSE; else fprintf(stderr, "unknown spawn_limit_stat %s\n", stat.c_str()); } } } else if (infile.key == "spawn_level") { infile.val = infile.val + ','; std::string mode = eatFirstString(infile.val,','); if (mode == "default") powers[input_id].spawn_level_mode = SPAWN_LEVEL_MODE_DEFAULT; else if (mode == "fixed") powers[input_id].spawn_level_mode = SPAWN_LEVEL_MODE_FIXED; else if (mode == "stat") powers[input_id].spawn_level_mode = SPAWN_LEVEL_MODE_STAT; else if (mode == "level") powers[input_id].spawn_level_mode = SPAWN_LEVEL_MODE_LEVEL; else fprintf(stderr, "unknown spawn_level_mode %s\n", mode.c_str()); if(powers[input_id].spawn_level_mode != SPAWN_LEVEL_MODE_DEFAULT) { powers[input_id].spawn_level_qty = eatFirstInt(infile.val,','); if(powers[input_id].spawn_level_mode != SPAWN_LEVEL_MODE_FIXED) { powers[input_id].spawn_level_every = eatFirstInt(infile.val,','); if(powers[input_id].spawn_level_mode == SPAWN_LEVEL_MODE_STAT) { std::string stat = eatFirstString(infile.val,','); if (stat == "physical") powers[input_id].spawn_level_stat = SPAWN_LEVEL_STAT_PHYSICAL; else if (stat == "mental") powers[input_id].spawn_level_stat = SPAWN_LEVEL_STAT_MENTAL; else if (stat == "offense") powers[input_id].spawn_level_stat = SPAWN_LEVEL_STAT_OFFENSE; else if (stat == "defense") powers[input_id].spawn_level_stat = SPAWN_LEVEL_STAT_DEFENSE; else fprintf(stderr, "unknown spawn_level_stat %s\n", stat.c_str()); } } } } else if (infile.key == "target_party") // @ATTR target_party|bool| powers[input_id].target_party = toBool(infile.val); else if (infile.key == "target_categories") { // @ATTR target_categories|string,...| string cat; while ((cat = infile.nextValue()) != "") { powers[input_id].target_categories.push_back(cat); } } else if (infile.key == "modifier_accuracy") { // @ATTR modifier_accuracy|[multiply:add:absolute], integer| infile.val = infile.val + ','; std::string mode = eatFirstString(infile.val, ','); if(mode == "multiply") powers[input_id].mod_accuracy_mode = STAT_MODIFIER_MODE_MULTIPLY; else if(mode == "add") powers[input_id].mod_accuracy_mode = STAT_MODIFIER_MODE_ADD; else if(mode == "absolute") powers[input_id].mod_accuracy_mode = STAT_MODIFIER_MODE_ABSOLUTE; else fprintf(stderr, "unknown stat_modifier_mode %s\n", mode.c_str()); powers[input_id].mod_accuracy_value = eatFirstInt(infile.val, ','); } else if (infile.key == "modifier_damage") { // @ATTR modifier_damage|[multiply:add:absolute], integer| infile.val = infile.val + ','; std::string mode = eatFirstString(infile.val, ','); if(mode == "multiply") powers[input_id].mod_damage_mode = STAT_MODIFIER_MODE_MULTIPLY; else if(mode == "add") powers[input_id].mod_damage_mode = STAT_MODIFIER_MODE_ADD; else if(mode == "absolute") powers[input_id].mod_damage_mode = STAT_MODIFIER_MODE_ABSOLUTE; else fprintf(stderr, "unknown stat_modifier_mode %s\n", mode.c_str()); powers[input_id].mod_damage_value_min = eatFirstInt(infile.val, ','); powers[input_id].mod_damage_value_max = eatFirstInt(infile.val, ','); } else if (infile.key == "modifier_critical") { // @ATTR modifier_critical|[multiply:add:absolute], integer| infile.val = infile.val + ','; std::string mode = eatFirstString(infile.val, ','); if(mode == "multiply") powers[input_id].mod_crit_mode = STAT_MODIFIER_MODE_MULTIPLY; else if(mode == "add") powers[input_id].mod_crit_mode = STAT_MODIFIER_MODE_ADD; else if(mode == "absolute") powers[input_id].mod_crit_mode = STAT_MODIFIER_MODE_ABSOLUTE; else fprintf(stderr, "unknown stat_modifier_mode %s\n", mode.c_str()); powers[input_id].mod_crit_value = eatFirstInt(infile.val, ','); } else fprintf(stderr, "ignoring unknown key %s set to %s in file %s\n", infile.key.c_str(), infile.val.c_str(), infile.getFileName().c_str()); } infile.close(); } /** * Load the specified sound effect for this power * * @param filename The .ogg file containing the sound for this power, assumed to be in soundfx/powers/ * @return The sfx[] array index for this mix chunk, or -1 upon load failure */ int PowerManager::loadSFX(const string& filename) { SoundManager::SoundID sid = snd->load(filename, "PowerManager sfx"); vector<SoundManager::SoundID>::iterator it = std::find(sfx.begin(), sfx.end(), sid); if (it == sfx.end()) { sfx.push_back(sid); return sfx.size() - 1; } return it - sfx.begin(); } /** * Set new collision object */ void PowerManager::handleNewMap(MapCollision *_collider) { collider = _collider; } /** * Keep two points within a certain range */ FPoint PowerManager::limitRange(float range, FPoint src, FPoint target) { if (range > 0) { if (src.x+range < target.x) target.x = src.x+range; if (src.x-range > target.x) target.x = src.x-range; if (src.y+range < target.y) target.y = src.y+range; if (src.y-range > target.y) target.y = src.y-range; } return target; } /** * Check if the target is valid (not an empty area or a wall) */ bool PowerManager::hasValidTarget(int power_index, StatBlock *src_stats, FPoint target) { if (!collider) return false; target = limitRange(powers[power_index].target_range,src_stats->pos,target); if (!collider->is_empty(target.x, target.y) || collider->is_wall(target.x,target.y)) { if (powers[power_index].buff_teleport) { return false; } } return true; } /** * Try to retarget the power to one of the 8 adjacent tiles * Returns the retargeted position on success, returns the original position on failure */ FPoint PowerManager::targetNeighbor(Point target, int range, bool ignore_blocked) { FPoint new_target = target; std::vector<FPoint> valid_tiles; for (int i=-range; i<=range; i++) { for (int j=-range; j<=range; j++) { if (i == 0 && j == 0) continue; // skip the middle tile new_target.x = target.x + i + 0.5f; new_target.y = target.y + j + 0.5f; if (collider->is_valid_position(new_target.x,new_target.y,MOVEMENT_NORMAL,false) || ignore_blocked) valid_tiles.push_back(new_target); } } if (!valid_tiles.empty()) return valid_tiles[rand() % valid_tiles.size()]; else return target; } /** * Apply basic power info to a new hazard. * * This can be called several times to combine powers. * Typically done when a base power can be modified by equipment * (e.g. ammo type affects the traits of powers that shoot) * * @param power_index The activated power ID * @param src_stats The StatBlock of the power activator * @param target Aim position in map coordinates * @param haz A newly-initialized hazard */ void PowerManager::initHazard(int power_index, StatBlock *src_stats, FPoint target, Hazard *haz) { //the hazard holds the statblock of its source haz->src_stats = src_stats; haz->power_index = power_index; if (powers[power_index].source_type == -1) { if (src_stats->hero) haz->source_type = SOURCE_TYPE_HERO; else if (src_stats->hero_ally) haz->source_type = SOURCE_TYPE_ALLY; else haz->source_type = SOURCE_TYPE_ENEMY; } else { haz->source_type = powers[power_index].source_type; } haz->target_party = powers[power_index].target_party; // Hazard attributes based on power source haz->crit_chance = src_stats->get(STAT_CRIT); haz->accuracy = src_stats->get(STAT_ACCURACY); // If the hazard's damage isn't default (0), we are applying an item-based power mod. // We don't allow equipment power mods to alter damage (mainly to preserve the base power's multiplier). if (haz->dmg_max == 0) { // base damage is by equipped item if (powers[power_index].base_damage == BASE_DAMAGE_MELEE) { haz->dmg_min = src_stats->get(STAT_DMG_MELEE_MIN); haz->dmg_max = src_stats->get(STAT_DMG_MELEE_MAX); } else if (powers[power_index].base_damage == BASE_DAMAGE_RANGED) { haz->dmg_min = src_stats->get(STAT_DMG_RANGED_MIN); haz->dmg_max = src_stats->get(STAT_DMG_RANGED_MAX); } else if (powers[power_index].base_damage == BASE_DAMAGE_MENT) { haz->dmg_min = src_stats->get(STAT_DMG_MENT_MIN); haz->dmg_max = src_stats->get(STAT_DMG_MENT_MAX); } } // Only apply stats from powers that are not defaults // If we do this, we can init with multiple power layers // (e.g. base spell plus weapon type) if (powers[power_index].animation_name != "") haz->loadAnimation(powers[power_index].animation_name); if (powers[power_index].lifespan != 0) haz->lifespan = powers[power_index].lifespan; if (powers[power_index].directional) haz->animationKind = calcDirection(src_stats->pos.x, src_stats->pos.y, target.x, target.y); else if (powers[power_index].visual_random) haz->animationKind = rand() % powers[power_index].visual_random; else if (powers[power_index].visual_option) haz->animationKind = powers[power_index].visual_option; haz->on_floor = powers[power_index].floor; haz->base_speed = powers[power_index].speed; haz->complete_animation = powers[power_index].complete_animation; // combat traits if (powers[power_index].radius != 0) { haz->radius = powers[power_index].radius; } if (powers[power_index].trait_elemental != -1) { haz->trait_elemental = powers[power_index].trait_elemental; } if (powers[power_index].no_attack) { haz->active = false; } // note: it may look like this line would be more efficient: // haz->multitarget = powers[power_index].multitarget // but as mentioned above, only apply traits that are not the default! // If haz->multitarget is already true, don't reset it to false. // otherwise a base power with multitarget will lose multitarget from a power mod // e.g. Piercing Shot in flare-game has multitarget // but the generic Arrow missile or Sling Stone missile does not. if (powers[power_index].multitarget) { haz->multitarget = true; } if (powers[power_index].trait_armor_penetration) { haz->trait_armor_penetration = true; } haz->trait_crits_impaired += powers[power_index].trait_crits_impaired; if (powers[power_index].beacon) { haz->beacon = true; } // status effect durations // steal effects haz->hp_steal += powers[power_index].hp_steal; haz->mp_steal += powers[power_index].mp_steal; // hazard starting position if (powers[power_index].starting_pos == STARTING_POS_SOURCE) { haz->pos = src_stats->pos; } else if (powers[power_index].starting_pos == STARTING_POS_TARGET) { haz->pos = limitRange(powers[power_index].target_range,src_stats->pos,target); } else if (powers[power_index].starting_pos == STARTING_POS_MELEE) { haz->pos = calcVector(src_stats->pos, src_stats->direction, src_stats->melee_range); } if (powers[power_index].target_neighbor > 0) { haz->pos = targetNeighbor(floor(src_stats->pos), powers[power_index].target_neighbor, true); } // pre/post power effects if (powers[power_index].post_power != 0) { haz->post_power = powers[power_index].post_power; } if (powers[power_index].wall_power != 0) { haz->wall_power = powers[power_index].wall_power; } // if equipment has special powers, apply it here (if it hasn't already been applied) if (haz->mod_power == 0 && powers[power_index].allow_power_mod) { if (powers[power_index].base_damage == BASE_DAMAGE_MELEE && src_stats->melee_weapon_power != 0) { haz->mod_power = power_index; initHazard(src_stats->melee_weapon_power, src_stats, target, haz); } else if (powers[power_index].base_damage == BASE_DAMAGE_MENT && src_stats->mental_weapon_power != 0) { haz->mod_power = power_index; initHazard(src_stats->mental_weapon_power, src_stats, target, haz); } else if (powers[power_index].base_damage == BASE_DAMAGE_RANGED && src_stats->ranged_weapon_power != 0) { haz->mod_power = power_index; initHazard(src_stats->ranged_weapon_power, src_stats, target, haz); } } } /** * Any attack-based effects are handled by hazards. * Self-enhancements (buffs) are handled by this function. */ void PowerManager::buff(int power_index, StatBlock *src_stats, FPoint target) { // teleport to the target location if (powers[power_index].buff_teleport) { target = limitRange(powers[power_index].target_range,src_stats->pos,target); if (powers[power_index].target_neighbor > 0) { FPoint new_target = targetNeighbor(floor(target), powers[power_index].target_neighbor); if (floor(new_target.x) == floor(target.x) && floor(new_target.y) == floor(target.y)) { src_stats->teleportation = false; } else { src_stats->teleportation = true; src_stats->teleport_destination.x = new_target.x; src_stats->teleport_destination.y = new_target.y; } } else { src_stats->teleportation = true; src_stats->teleport_destination.x = target.x; src_stats->teleport_destination.y = target.y; } } // handle all other effects if (powers[power_index].buff || (powers[power_index].buff_party && src_stats->hero_ally)) { int source_type = src_stats->hero ? SOURCE_TYPE_HERO : (src_stats->hero_ally ? SOURCE_TYPE_ALLY : SOURCE_TYPE_ENEMY); effect(src_stats, src_stats, power_index, source_type); } if (powers[power_index].buff_party && !powers[power_index].passive) { party_buffs.push(power_index); } // activate any post powers here if the power doesn't use a hazard // otherwise the post power will chain off the hazard itself if (!powers[power_index].use_hazard) { activate(powers[power_index].post_power, src_stats, src_stats->pos); } } /** * Play the sound effect for this power * Equipped items may have unique sounds */ void PowerManager::playSound(int power_index, StatBlock *src_stats) { bool play_base_sound = false; if (powers[power_index].allow_power_mod) { if (powers[power_index].base_damage == BASE_DAMAGE_MELEE && src_stats->melee_weapon_power != 0 && powers[src_stats->melee_weapon_power].sfx_index != -1) { snd->play(sfx[powers[src_stats->melee_weapon_power].sfx_index]); } else if (powers[power_index].base_damage == BASE_DAMAGE_MENT && src_stats->mental_weapon_power != 0 && powers[src_stats->mental_weapon_power].sfx_index != -1) { snd->play(sfx[powers[src_stats->mental_weapon_power].sfx_index]); } else if (powers[power_index].base_damage == BASE_DAMAGE_RANGED && src_stats->ranged_weapon_power != 0 && powers[src_stats->ranged_weapon_power].sfx_index != -1) { snd->play(sfx[powers[src_stats->ranged_weapon_power].sfx_index]); } else play_base_sound = true; } else play_base_sound = true; if (play_base_sound && powers[power_index].sfx_index != -1) snd->play(sfx[powers[power_index].sfx_index]); } bool PowerManager::effect(StatBlock *src_stats, StatBlock *caster_stats, int power_index, int source_type) { for (unsigned i=0; i<powers[power_index].post_effects.size(); i++) { std::string effect_index = powers[power_index].post_effects[i].id; int magnitude = powers[power_index].post_effects[i].magnitude; int duration = powers[power_index].post_effects[i].duration; if (effects.find(effect_index) != effects.end()) { if (effects[effect_index].type == "shield") { // charge shield to max ment weapon damage * damage multiplier if(powers[power_index].mod_damage_mode == STAT_MODIFIER_MODE_MULTIPLY) magnitude = caster_stats->get(STAT_DMG_MENT_MAX) * powers[power_index].mod_damage_value_min / 100; else if(powers[power_index].mod_damage_mode == STAT_MODIFIER_MODE_ADD) magnitude = caster_stats->get(STAT_DMG_MENT_MAX) + powers[power_index].mod_damage_value_min; else if(powers[power_index].mod_damage_mode == STAT_MODIFIER_MODE_ABSOLUTE) magnitude = randBetween(powers[power_index].mod_damage_value_min, powers[power_index].mod_damage_value_max); comb->addMessage(msg->get("+%d Shield",magnitude), src_stats->pos, COMBAT_MESSAGE_BUFF); } else if (effects[effect_index].type == "heal") { // heal for ment weapon damage * damage multiplier magnitude = randBetween(caster_stats->get(STAT_DMG_MENT_MIN), caster_stats->get(STAT_DMG_MENT_MAX)); if(powers[power_index].mod_damage_mode == STAT_MODIFIER_MODE_MULTIPLY) magnitude = magnitude * powers[power_index].mod_damage_value_min / 100; else if(powers[power_index].mod_damage_mode == STAT_MODIFIER_MODE_ADD) magnitude += powers[power_index].mod_damage_value_min; else if(powers[power_index].mod_damage_mode == STAT_MODIFIER_MODE_ABSOLUTE) magnitude = randBetween(powers[power_index].mod_damage_value_min, powers[power_index].mod_damage_value_max); comb->addMessage(msg->get("+%d HP",magnitude), src_stats->pos, COMBAT_MESSAGE_BUFF); src_stats->hp += magnitude; if (src_stats->hp > src_stats->get(STAT_HP_MAX)) src_stats->hp = src_stats->get(STAT_HP_MAX); } int passive_id = 0; if (powers[power_index].passive) passive_id = power_index; src_stats->effects.addEffect(effect_index, effects[effect_index].icon, duration, magnitude, effects[effect_index].type, effects[effect_index].animation, effects[effect_index].additive, false, powers[power_index].passive_trigger, effects[effect_index].render_above, passive_id, source_type); } // If there's a sound effect, play it here playSound(power_index, src_stats); } return true; } /** * The activated power creates a static effect (not a moving hazard) * * @param power_index The activated power ID * @param src_stats The StatBlock of the power activator * @param target The mouse cursor position in map coordinates * return boolean true if successful */ bool PowerManager::fixed(int power_index, StatBlock *src_stats, FPoint target) { if (powers[power_index].use_hazard) { int delay_iterator = 0; for (int i=0; i < powers[power_index].count; i++) { Hazard *haz = new Hazard(collider); initHazard(power_index, src_stats, target, haz); // add optional delay haz->delay_frames = delay_iterator; delay_iterator += powers[power_index].delay; // Hazard memory is now the responsibility of HazardManager hazards.push(haz); } } buff(power_index, src_stats, target); // If there's a sound effect, play it here playSound(power_index, src_stats); payPowerCost(power_index, src_stats); return true; } /** * The activated power creates a group of missile hazards (e.g. arrow, thrown knife, firebolt). * Each individual missile is a single animated hazard that travels from the caster position to the * mouse target position. * * @param power_index The activated power ID * @param src_stats The StatBlock of the power activator * @param target The mouse cursor position in map coordinates * return boolean true if successful */ bool PowerManager::missile(int power_index, StatBlock *src_stats, FPoint target) { const float pi = 3.1415926535898f; FPoint src; if (powers[power_index].starting_pos == STARTING_POS_TARGET) { src = target; } else { src = src_stats->pos; } // calculate polar coordinates angle float theta = calcTheta(src.x, src.y, target.x, target.y); int delay_iterator = 0; //generate hazards for (int i=0; i < powers[power_index].count; i++) { Hazard *haz = new Hazard(collider); //calculate individual missile angle float offset_angle = ((1.0f - powers[power_index].count)/2 + i) * (powers[power_index].missile_angle * pi / 180.0f); float variance = 0; if (powers[power_index].angle_variance != 0) variance = pow(-1.0f, (rand() % 2) - 1) * (rand() % powers[power_index].angle_variance) * pi / 180.0f; //random between 0 and angle_variance away float alpha = theta + offset_angle + variance; while (alpha >= pi+pi) alpha -= pi+pi; while (alpha < 0.0) alpha += pi+pi; initHazard(power_index, src_stats, target, haz); //calculate the missile velocity float speed_var = 0; if (powers[power_index].speed_variance != 0) { const float var = powers[power_index].speed_variance; speed_var = ((var * 2.0f * rand()) / RAND_MAX) - var; } haz->speed.x = (haz->base_speed + speed_var) * cos(alpha); haz->speed.y = (haz->base_speed + speed_var) * sin(alpha); // calculate direction based on trajectory, not actual target if (powers[power_index].directional) haz->animationKind = calcDirection(src.x, src.y, src.x + haz->speed.x, src.y + haz->speed.y); // add optional delay haz->delay_frames = delay_iterator; delay_iterator += powers[power_index].delay; hazards.push(haz); } payPowerCost(power_index, src_stats); playSound(power_index, src_stats); return true; } /** * Repeaters are multiple hazards that spawn in a straight line */ bool PowerManager::repeater(int power_index, StatBlock *src_stats, FPoint target) { payPowerCost(power_index, src_stats); //initialize variables FPoint location_iterator; FPoint speed; int delay_iterator = 0; // calculate polar coordinates angle float theta = calcTheta(src_stats->pos.x, src_stats->pos.y, target.x, target.y); speed.x = powers[power_index].speed * cos(theta); speed.y = powers[power_index].speed * sin(theta); location_iterator = src_stats->pos; playSound(power_index, src_stats); for (int i=0; i<powers[power_index].count; i++) { location_iterator.x += speed.x; location_iterator.y += speed.y; // only travels until it hits a wall if (collider->is_wall(location_iterator.x, location_iterator.y)) { break; // no more hazards } Hazard *haz = new Hazard(collider); initHazard(power_index, src_stats, target, haz); haz->pos = location_iterator; haz->delay_frames = delay_iterator; delay_iterator += powers[power_index].delay; hazards.push(haz); } return true; } /** * Spawn a creature. Does not create a hazard */ bool PowerManager::spawn(int power_index, StatBlock *src_stats, FPoint target) { // apply any buffs buff(power_index, src_stats, target); // If there's a sound effect, play it here playSound(power_index, src_stats); Map_Enemy espawn; espawn.type = powers[power_index].spawn_type; espawn.summoner = src_stats; // enemy spawning position if (powers[power_index].starting_pos == STARTING_POS_SOURCE) { espawn.pos = src_stats->pos; } else if (powers[power_index].starting_pos == STARTING_POS_TARGET) { espawn.pos = target; } else if (powers[power_index].starting_pos == STARTING_POS_MELEE) { espawn.pos = calcVector(src_stats->pos, src_stats->direction, src_stats->melee_range); } if (powers[power_index].target_neighbor > 0) { espawn.pos = floor(targetNeighbor(floor(src_stats->pos), powers[power_index].target_neighbor)); } espawn.direction = calcDirection(src_stats->pos.x, src_stats->pos.y, target.x, target.y); espawn.summon_power_index = power_index; espawn.hero_ally = src_stats->hero || src_stats->hero_ally; for (int i=0; i < powers[power_index].count; i++) { enemies.push(espawn); } payPowerCost(power_index, src_stats); return true; } /** * A simpler spawn routine for map events */ bool PowerManager::spawn(const std::string& enemy_type, Point target) { Map_Enemy espawn; espawn.type = enemy_type; espawn.pos = target; // quick spawns start facing a random direction espawn.direction = rand() % 8; enemies.push(espawn); return true; } /** * Transform into a creature. Fully replaces entity characteristics */ bool PowerManager::transform(int power_index, StatBlock *src_stats, FPoint target) { // locking the actionbar prevents power usage until after the hero is transformed inpt->lockActionBar(); if (src_stats->transformed && powers[power_index].spawn_type != "untransform") { log_msg = msg->get("You are already transformed, untransform first."); return false; } // apply any buffs buff(power_index, src_stats, target); src_stats->manual_untransform = powers[power_index].manual_untransform; src_stats->transform_with_equipment = powers[power_index].keep_equipment; // If there's a sound effect, play it here playSound(power_index, src_stats); // execute untransform powers if (powers[power_index].spawn_type == "untransform" && src_stats->transformed) { src_stats->transform_duration = 0; src_stats->transform_type = "untransform"; // untransform() is called only if type !="" } else { if (powers[power_index].transform_duration == 0) { // permanent transformation src_stats->transform_duration = -1; } else if (powers[power_index].transform_duration > 0) { // timed transformation src_stats->transform_duration = powers[power_index].transform_duration; } src_stats->transform_type = powers[power_index].spawn_type; } payPowerCost(power_index, src_stats); return true; } /** * Activate is basically a switch/redirect to the appropriate function */ bool PowerManager::activate(int power_index, StatBlock *src_stats, FPoint target) { if (src_stats->hero) { if (powers[power_index].requires_mp > src_stats->mp) return false; } if (src_stats->hp > 0 && powers[power_index].sacrifice == false && powers[power_index].requires_hp >= src_stats->hp) return false; // logic for different types of powers are very different. We allow these // separate functions to handle the details. switch(powers[power_index].type) { case POWTYPE_FIXED: return fixed(power_index, src_stats, target); case POWTYPE_MISSILE: return missile(power_index, src_stats, target); case POWTYPE_REPEATER: return repeater(power_index, src_stats, target); case POWTYPE_SPAWN: return spawn(power_index, src_stats, target); case POWTYPE_TRANSFORM: return transform(power_index, src_stats, target); } return false; } /** * pay costs, i.e. remove mana or items. */ void PowerManager::payPowerCost(int power_index, StatBlock *src_stats) { if (src_stats) { if (src_stats->hero) { src_stats->mp -= powers[power_index].requires_mp; if (powers[power_index].requires_item != -1) used_items.push_back(powers[power_index].requires_item); // only allow one instance of duplicate items at a time in the used_equipped_items queue // this is useful for Ouroboros rings, where we have 2 equipped, but only want to remove one at a time if (powers[power_index].requires_equipped_item != -1 && find(used_equipped_items.begin(), used_equipped_items.end(), powers[power_index].requires_equipped_item) == used_equipped_items.end()) used_equipped_items.push_back(powers[power_index].requires_equipped_item); } src_stats->hp -= powers[power_index].requires_hp; src_stats->hp = (src_stats->hp < 0 ? 0 : src_stats->hp); } } /** * Activate an entity's passive powers */ void PowerManager::activatePassives(StatBlock *src_stats) { bool triggered_others = false; int trigger = -1; // unlocked powers for (unsigned i=0; i<src_stats->powers_passive.size(); i++) { if (powers[src_stats->powers_passive[i]].passive) { trigger = powers[src_stats->powers_passive[i]].passive_trigger; if (trigger == -1) { if (src_stats->effects.triggered_others) continue; else triggered_others = true; } else if (trigger == TRIGGER_BLOCK && !src_stats->effects.triggered_block) continue; else if (trigger == TRIGGER_HIT && !src_stats->effects.triggered_hit) continue; else if (trigger == TRIGGER_HALFDEATH && !src_stats->effects.triggered_halfdeath) { if (src_stats->hp > src_stats->get(STAT_HP_MAX)/2) continue; else src_stats->effects.triggered_halfdeath = true; } else if (trigger == TRIGGER_JOINCOMBAT && !src_stats->effects.triggered_joincombat) { if (!src_stats->in_combat) continue; else src_stats->effects.triggered_joincombat = true; } else if (trigger == TRIGGER_DEATH && !src_stats->effects.triggered_death) continue; activate(src_stats->powers_passive[i], src_stats, src_stats->pos); src_stats->refresh_stats = true; } } // item powers for (unsigned i=0; i<src_stats->powers_list_items.size(); i++) { if (powers[src_stats->powers_list_items[i]].passive) { trigger = powers[src_stats->powers_list_items[i]].passive_trigger; if (trigger == -1) { if (src_stats->effects.triggered_others) continue; else triggered_others = true; } else if (trigger == TRIGGER_BLOCK && !src_stats->effects.triggered_block) continue; else if (trigger == TRIGGER_HIT && !src_stats->effects.triggered_hit) continue; else if (trigger == TRIGGER_HALFDEATH && !src_stats->effects.triggered_halfdeath) { if (src_stats->hp > src_stats->get(STAT_HP_MAX)/2) continue; else src_stats->effects.triggered_halfdeath = true; } else if (trigger == TRIGGER_JOINCOMBAT && !src_stats->effects.triggered_joincombat) { if (!src_stats->in_combat) continue; else src_stats->effects.triggered_joincombat = true; } else if (trigger == TRIGGER_DEATH && !src_stats->effects.triggered_death) continue; activate(src_stats->powers_list_items[i], src_stats, src_stats->pos); src_stats->refresh_stats = true; } } // Only trigger normal passives once if (triggered_others) src_stats->effects.triggered_others = true; // the hit/death triggers can be triggered more than once, so reset them here // the block trigger is handled in the Avatar class src_stats->effects.triggered_hit = false; src_stats->effects.triggered_death = false; } /** * Activate a single passive * this is used when unlocking powers in MenuPowers */ void PowerManager::activateSinglePassive(StatBlock *src_stats, int id) { if (!powers[id].passive) return; if (powers[id].passive_trigger == -1) { activate(id, src_stats, src_stats->pos); src_stats->refresh_stats = true; src_stats->effects.triggered_others = true; } } PowerManager::~PowerManager() { for (unsigned i=0; i<sfx.size(); i++) { snd->unload(sfx[i]); } sfx.clear(); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/PowerManager.h����������������������������������������������������������������0000664�0000000�0000000�00000024070�12247171015�0017331�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class PowerManager * * Special code for handling spells, special powers, item effects, etc. */ #pragma once #ifndef POWER_MANAGER_H #define POWER_MANAGER_H #include "CommonIncludes.h" #include "MapRenderer.h" #include "Utils.h" #include <queue> #include <cassert> class Animation; class AnimationSet; class Hazard; class MapCollision; class StatBlock; const int POWTYPE_FIXED = 0; const int POWTYPE_MISSILE = 1; const int POWTYPE_REPEATER = 2; const int POWTYPE_SPAWN = 3; const int POWTYPE_TRANSFORM = 4; const int POWTYPE_EFFECT = 5; const int POWSTATE_BLOCK = 1; const int POWSTATE_INSTANT = 2; const int POWSTATE_ATTACK = 3; const int BASE_DAMAGE_NONE = 0; const int BASE_DAMAGE_MELEE = 1; const int BASE_DAMAGE_RANGED = 2; const int BASE_DAMAGE_MENT = 3; // when casting a spell/power, the hazard starting position is // either the source (the avatar or enemy), the target (mouse click position), // or melee range in the direction that the source is facing const int STARTING_POS_SOURCE = 0; const int STARTING_POS_TARGET = 1; const int STARTING_POS_MELEE = 2; const int TRIGGER_BLOCK = 0; const int TRIGGER_HIT = 1; const int TRIGGER_HALFDEATH = 2; const int TRIGGER_JOINCOMBAT = 3; const int TRIGGER_DEATH = 4; const int SPAWN_LIMIT_MODE_FIXED = 0; const int SPAWN_LIMIT_MODE_STAT = 1; const int SPAWN_LIMIT_MODE_UNLIMITED = 2; const int SPAWN_LIMIT_STAT_PHYSICAL = 0; const int SPAWN_LIMIT_STAT_MENTAL = 1; const int SPAWN_LIMIT_STAT_OFFENSE = 2; const int SPAWN_LIMIT_STAT_DEFENSE = 3; const int SPAWN_LEVEL_MODE_DEFAULT = 0; const int SPAWN_LEVEL_MODE_FIXED = 1; const int SPAWN_LEVEL_MODE_STAT = 2; const int SPAWN_LEVEL_MODE_LEVEL = 3; const int SPAWN_LEVEL_STAT_PHYSICAL = 0; const int SPAWN_LEVEL_STAT_MENTAL = 1; const int SPAWN_LEVEL_STAT_OFFENSE = 2; const int SPAWN_LEVEL_STAT_DEFENSE = 3; const int STAT_MODIFIER_MODE_MULTIPLY = 0; const int STAT_MODIFIER_MODE_ADD = 1; const int STAT_MODIFIER_MODE_ABSOLUTE = 2; class EffectDef { public: std::string name; std::string type; int icon; std::string animation; bool additive; bool render_above; EffectDef() : name("") , type("") , icon(-1) , animation("") , additive(false) , render_above(false) {} }; class PostEffect { public: std::string id; int magnitude; int duration; PostEffect() : id("") , magnitude(0) , duration(0) {} }; class Power { public: // base info int type; // what kind of activate() this is std::string name; std::string description; int icon; // just the number. The caller menu will have access to the surface. int new_state; // when using this power the user (avatar/enemy) starts a new state std::string attack_anim; // name of the animation to play when using this power, if it is not block bool face; // does the user turn to face the mouse cursor when using this power? int source_type; //hero, neutral, or enemy bool beacon; //true if it's just an ememy calling its allies int count; // number of hazards/effects or spawns created bool passive; // if unlocked when the user spawns, automatically cast it int passive_trigger; // only activate passive powers under certain conditions (block, hit, death, etc) // power requirements std::set<std::string> requires_flags; // checked against equip_flags granted from items int requires_mp; int requires_hp; bool sacrifice; bool requires_los; // line of sight bool requires_empty_target; // target square must be empty int requires_item; int requires_equipped_item; bool consumable; bool requires_targeting; // power only makes sense when using click-to-target int cooldown; // milliseconds before you can use the power again // animation info std::string animation_name; int sfx_index; bool directional; // sprite sheet contains options for 8 directions, one per row int visual_random; // sprite sheet contains rows of random options int visual_option; // sprite sheet contains rows of similar effects. use a specific option bool aim_assist; float speed; // for missile hazards, tiles per frame int lifespan; // how long the hazard/animation lasts bool floor; // the hazard is drawn between the background and object layers bool complete_animation; // hazard traits bool use_hazard; bool no_attack; float radius; int base_damage; // enum. damage is powered by melee, ranged, mental weapon int starting_pos; // enum. (source, target, or melee) bool multitarget; float target_range; bool target_party; std::vector<std::string> target_categories; int mod_accuracy_mode; int mod_accuracy_value; int mod_crit_mode; int mod_crit_value; int mod_damage_mode; int mod_damage_value_min; int mod_damage_value_max;//only used if mode is absolute //steal effects (in %, eg. hp_steal=50 turns 50% damage done into HP regain.) int hp_steal; int mp_steal; //missile traits int missile_angle; int angle_variance; float speed_variance; //repeater traits int delay; int trait_elemental; // enum. of elements bool trait_armor_penetration; int trait_crits_impaired; // crit bonus vs. movement impaired enemies (slowed, immobilized, stunned) bool trait_avoidance_ignore; int transform_duration; bool manual_untransform; // true binds to the power another recurrence power bool keep_equipment; // special effects bool buff; bool buff_teleport; bool buff_party; int buff_party_power_id; std::vector<PostEffect> post_effects; int post_power; int wall_power; bool allow_power_mod; // spawn info std::string spawn_type; int target_neighbor; int spawn_limit_mode; int spawn_limit_qty; int spawn_limit_every; int spawn_limit_stat; int spawn_level_mode; int spawn_level_qty; int spawn_level_every; int spawn_level_stat; Power() : type(-1) , name("") , description("") , icon(-1) , new_state(-1) , attack_anim("") , face(false) , source_type(-1) , beacon(false) , count(1) , passive(false) , passive_trigger(-1) , requires_mp(0) , requires_hp(0) , sacrifice(false) , requires_los(false) , requires_empty_target(false) , requires_item(-1) , requires_equipped_item(-1) , consumable(false) , requires_targeting(false) , cooldown(0) , animation_name("") , sfx_index(-1) , directional(false) , visual_random(0) , visual_option(0) , aim_assist(false) , speed(0) , lifespan(0) , floor(false) , complete_animation(false) , use_hazard(false) , no_attack(false) , radius(0) , base_damage(BASE_DAMAGE_NONE) , starting_pos(STARTING_POS_SOURCE) , multitarget(false) , target_range(0) , target_party(false) , mod_accuracy_mode(STAT_MODIFIER_MODE_MULTIPLY) , mod_accuracy_value(100) , mod_crit_mode(STAT_MODIFIER_MODE_MULTIPLY) , mod_crit_value(100) , mod_damage_mode(STAT_MODIFIER_MODE_MULTIPLY) , mod_damage_value_min(100) , mod_damage_value_max(0) , hp_steal(0) , mp_steal(0) , missile_angle(0) , angle_variance(0) , speed_variance(0) , delay(0) , trait_elemental(-1) , trait_armor_penetration(false) , trait_crits_impaired(0) , trait_avoidance_ignore(false) , transform_duration(0) , manual_untransform(false) , keep_equipment(false) , buff(false) , buff_teleport(false) , buff_party(false) , buff_party_power_id(0) , post_power(0) , wall_power(0) , allow_power_mod(false) , spawn_type("") , target_neighbor(0) , spawn_limit_mode(SPAWN_LIMIT_MODE_UNLIMITED) , spawn_limit_qty(1) , spawn_limit_every(1) , spawn_limit_stat(SPAWN_LIMIT_STAT_MENTAL) , spawn_level_mode(SPAWN_LEVEL_MODE_DEFAULT) , spawn_level_qty(0) , spawn_level_every(0) , spawn_level_stat(SPAWN_LEVEL_STAT_MENTAL) {} }; class PowerManager { private: MapCollision *collider; void loadEffects(); void loadPowers(); int loadSFX(const std::string& filename); FPoint limitRange(float range, FPoint src, FPoint target); FPoint targetNeighbor(Point target, int range, bool ignore_blocked = false); void initHazard(int powernum, StatBlock *src_stats, FPoint target, Hazard *haz); void buff(int power_index, StatBlock *src_stats, FPoint target); void playSound(int power_index, StatBlock *src_stats); bool fixed(int powernum, StatBlock *src_stats, FPoint target); bool missile(int powernum, StatBlock *src_stats, FPoint target); bool repeater(int powernum, StatBlock *src_stats, FPoint target); bool spawn(int powernum, StatBlock *src_stats, FPoint target); bool transform(int powernum, StatBlock *src_stats, FPoint target); void payPowerCost(int power_index, StatBlock *src_stats); public: PowerManager(); ~PowerManager(); std::string log_msg; void handleNewMap(MapCollision *_collider); bool activate(int power_index, StatBlock *src_stats, FPoint target); const Power &getPower(unsigned id) {assert(id < powers.size()); return powers[id];} bool canUsePower(unsigned id) const; bool hasValidTarget(int power_index, StatBlock *src_stats, FPoint target); bool spawn(const std::string& enemy_type, Point target); bool effect(StatBlock *src_stats, StatBlock *caster_stats, int power_index, int source_type); void activatePassives(StatBlock *src_stats); void activateSinglePassive(StatBlock *src_stats, int id); std::map<std::string,EffectDef> effects; std::vector<Power> powers; std::queue<Hazard *> hazards; // output; read by HazardManager std::queue<Map_Enemy> enemies; // output; read by PowerManager std::queue<int> party_buffs; // shared sounds for power special effects std::vector<SoundManager::SoundID> sfx; std::vector<int> used_items; std::vector<int> used_equipped_items; }; #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/QuestLog.cpp������������������������������������������������������������������0000664�0000000�0000000�00000007013�12247171015�0017036�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class QuestLog * * Helper text to remind the player of active quests */ #include "CommonIncludes.h" #include "FileParser.h" #include "Menu.h" #include "MenuLog.h" #include "QuestLog.h" #include "Settings.h" #include "SharedResources.h" #include "UtilsFileSystem.h" #include "UtilsParsing.h" #include "SharedGameResources.h" using namespace std; QuestLog::QuestLog(MenuLog *_log) { log = _log; newQuestNotification = false; resetQuestNotification = false; loadAll(); } QuestLog::~QuestLog() { } /** * Load each [mod]/quests/index.txt file */ void QuestLog::loadAll() { // load each items.txt file. Individual item IDs can be overwritten with mods. vector<string> files = mods->list("quests/index.txt"); for (unsigned int i = 0; i < files.size(); i++) this->loadIndex(files[i]); } /** * Load all the quest files from the given index * It simply contains a list of quest files * Generally each quest arc has its own file * * @param filename The full path and filename to the [mod]/quests/index.txt file */ void QuestLog::loadIndex(const std::string& filename) { ifstream infile; string line; infile.open(filename.c_str(), ios::in); if (infile.is_open()) { while (infile.good()) { line = getLine(infile); if (line.length() > 0) { // each line contains a quest file name load(line); } } infile.close(); } } /** * Load the quests in the specific quest file. * Searches for the last-defined such file in all mods * * @param filename The quest file name and extension, no path */ void QuestLog::load(const std::string& filename) { FileParser infile; if (!infile.open("quests/" + filename)) return; while (infile.next()) { if (infile.new_section) { if (infile.section == "quest") quests.push_back(vector<Event_Component>()); } Event_Component ev; ev.type = infile.key; ev.s = msg->get(infile.val); quests.back().push_back(ev); } infile.close(); } void QuestLog::logic() { if (camp->quest_update) { resetQuestNotification = true; camp->quest_update = false; createQuestList(); } } /** * All active quests are placed in the Quest tab of the Log Menu */ void QuestLog::createQuestList() { log->clear(LOG_TYPE_QUESTS); for (unsigned int i=0; i<quests.size(); i++) { for (unsigned int j=0; j<quests[i].size(); j++) { // check requirements // break (skip to next dialog node) if any requirement fails // if we reach an event that is not a requirement, succeed if (quests[i][j].type == "requires_status") { if (!camp->checkStatus(quests[i][j].s)) break; } else if (quests[i][j].type == "requires_not_status") { if (camp->checkStatus(quests[i][j].s)) break; } else if (quests[i][j].type == "quest_text") { log->add(quests[i][j].s, LOG_TYPE_QUESTS); newQuestNotification = true; break; } else if (quests[i][j].type == "") { break; } } } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/QuestLog.h��������������������������������������������������������������������0000664�0000000�0000000�00000002433�12247171015�0016504�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class QuestLog * * Helper text to remind the player of active quests */ #pragma once #ifndef QUEST_LOG_H #define QUEST_LOG_H #include "CommonIncludes.h" #include "Utils.h" class MenuLog; class QuestLog { private: MenuLog *log; // inner vector is a chain of events per quest, outer vector is a // list of quests. std::vector<std::vector<Event_Component> >quests; public: QuestLog(MenuLog *_log); ~QuestLog(); void loadAll(); void loadIndex(const std::string& filename); void load(const std::string& filename); void logic(); void createQuestList(); bool newQuestNotification; bool resetQuestNotification; }; #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/SDL_gfxBlitFunc.c�������������������������������������������������������������0000664�0000000�0000000�00000032244�12247171015�0017654�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* SDL_gfxBlitFunc.c: custom blitters Copyright (C) 2001-2011 Andreas Schiffler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Andreas Schiffler -- aschiffler at ferzkopp dot net */ #include "SDL_gfxBlitFunc.h" /*! \brief Alpha adjustment table for custom blitter. The table provides values for a modified, non-linear transfer function which maintain brightness. */ static unsigned int GFX_ALPHA_ADJUST_ARRAY[256] = { 0, /* 0 */ 15, /* 1 */ 22, /* 2 */ 27, /* 3 */ 31, /* 4 */ 35, /* 5 */ 39, /* 6 */ 42, /* 7 */ 45, /* 8 */ 47, /* 9 */ 50, /* 10 */ 52, /* 11 */ 55, /* 12 */ 57, /* 13 */ 59, /* 14 */ 61, /* 15 */ 63, /* 16 */ 65, /* 17 */ 67, /* 18 */ 69, /* 19 */ 71, /* 20 */ 73, /* 21 */ 74, /* 22 */ 76, /* 23 */ 78, /* 24 */ 79, /* 25 */ 81, /* 26 */ 82, /* 27 */ 84, /* 28 */ 85, /* 29 */ 87, /* 30 */ 88, /* 31 */ 90, /* 32 */ 91, /* 33 */ 93, /* 34 */ 94, /* 35 */ 95, /* 36 */ 97, /* 37 */ 98, /* 38 */ 99, /* 39 */ 100, /* 40 */ 102, /* 41 */ 103, /* 42 */ 104, /* 43 */ 105, /* 44 */ 107, /* 45 */ 108, /* 46 */ 109, /* 47 */ 110, /* 48 */ 111, /* 49 */ 112, /* 50 */ 114, /* 51 */ 115, /* 52 */ 116, /* 53 */ 117, /* 54 */ 118, /* 55 */ 119, /* 56 */ 120, /* 57 */ 121, /* 58 */ 122, /* 59 */ 123, /* 60 */ 124, /* 61 */ 125, /* 62 */ 126, /* 63 */ 127, /* 64 */ 128, /* 65 */ 129, /* 66 */ 130, /* 67 */ 131, /* 68 */ 132, /* 69 */ 133, /* 70 */ 134, /* 71 */ 135, /* 72 */ 136, /* 73 */ 137, /* 74 */ 138, /* 75 */ 139, /* 76 */ 140, /* 77 */ 141, /* 78 */ 141, /* 79 */ 142, /* 80 */ 143, /* 81 */ 144, /* 82 */ 145, /* 83 */ 146, /* 84 */ 147, /* 85 */ 148, /* 86 */ 148, /* 87 */ 149, /* 88 */ 150, /* 89 */ 151, /* 90 */ 152, /* 91 */ 153, /* 92 */ 153, /* 93 */ 154, /* 94 */ 155, /* 95 */ 156, /* 96 */ 157, /* 97 */ 158, /* 98 */ 158, /* 99 */ 159, /* 100 */ 160, /* 101 */ 161, /* 102 */ 162, /* 103 */ 162, /* 104 */ 163, /* 105 */ 164, /* 106 */ 165, /* 107 */ 165, /* 108 */ 166, /* 109 */ 167, /* 110 */ 168, /* 111 */ 168, /* 112 */ 169, /* 113 */ 170, /* 114 */ 171, /* 115 */ 171, /* 116 */ 172, /* 117 */ 173, /* 118 */ 174, /* 119 */ 174, /* 120 */ 175, /* 121 */ 176, /* 122 */ 177, /* 123 */ 177, /* 124 */ 178, /* 125 */ 179, /* 126 */ 179, /* 127 */ 180, /* 128 */ 181, /* 129 */ 182, /* 130 */ 182, /* 131 */ 183, /* 132 */ 184, /* 133 */ 184, /* 134 */ 185, /* 135 */ 186, /* 136 */ 186, /* 137 */ 187, /* 138 */ 188, /* 139 */ 188, /* 140 */ 189, /* 141 */ 190, /* 142 */ 190, /* 143 */ 191, /* 144 */ 192, /* 145 */ 192, /* 146 */ 193, /* 147 */ 194, /* 148 */ 194, /* 149 */ 195, /* 150 */ 196, /* 151 */ 196, /* 152 */ 197, /* 153 */ 198, /* 154 */ 198, /* 155 */ 199, /* 156 */ 200, /* 157 */ 200, /* 158 */ 201, /* 159 */ 201, /* 160 */ 202, /* 161 */ 203, /* 162 */ 203, /* 163 */ 204, /* 164 */ 205, /* 165 */ 205, /* 166 */ 206, /* 167 */ 206, /* 168 */ 207, /* 169 */ 208, /* 170 */ 208, /* 171 */ 209, /* 172 */ 210, /* 173 */ 210, /* 174 */ 211, /* 175 */ 211, /* 176 */ 212, /* 177 */ 213, /* 178 */ 213, /* 179 */ 214, /* 180 */ 214, /* 181 */ 215, /* 182 */ 216, /* 183 */ 216, /* 184 */ 217, /* 185 */ 217, /* 186 */ 218, /* 187 */ 218, /* 188 */ 219, /* 189 */ 220, /* 190 */ 220, /* 191 */ 221, /* 192 */ 221, /* 193 */ 222, /* 194 */ 222, /* 195 */ 223, /* 196 */ 224, /* 197 */ 224, /* 198 */ 225, /* 199 */ 225, /* 200 */ 226, /* 201 */ 226, /* 202 */ 227, /* 203 */ 228, /* 204 */ 228, /* 205 */ 229, /* 206 */ 229, /* 207 */ 230, /* 208 */ 230, /* 209 */ 231, /* 210 */ 231, /* 211 */ 232, /* 212 */ 233, /* 213 */ 233, /* 214 */ 234, /* 215 */ 234, /* 216 */ 235, /* 217 */ 235, /* 218 */ 236, /* 219 */ 236, /* 220 */ 237, /* 221 */ 237, /* 222 */ 238, /* 223 */ 238, /* 224 */ 239, /* 225 */ 240, /* 226 */ 240, /* 227 */ 241, /* 228 */ 241, /* 229 */ 242, /* 230 */ 242, /* 231 */ 243, /* 232 */ 243, /* 233 */ 244, /* 234 */ 244, /* 235 */ 245, /* 236 */ 245, /* 237 */ 246, /* 238 */ 246, /* 239 */ 247, /* 240 */ 247, /* 241 */ 248, /* 242 */ 248, /* 243 */ 249, /* 244 */ 249, /* 245 */ 250, /* 246 */ 250, /* 247 */ 251, /* 248 */ 251, /* 249 */ 252, /* 250 */ 252, /* 251 */ 253, /* 252 */ 253, /* 253 */ 254, /* 254 */ 255 /* 255 */ }; /*! \brief Internal blitter using adjusted destination alpha during RGBA->RGBA blits. Performs the blit based on the 'info' structure and applies the transfer function to the destination 'a' values. \param info The blit info to use. */ void _SDL_gfxBlitBlitterRGBA(SDL_gfxBlitInfo * info) { int width = info->d_width; int height = info->d_height; Uint8 *src = info->s_pixels; int srcskip = info->s_skip; Uint8 *dst = info->d_pixels; int dstskip = info->d_skip; SDL_PixelFormat *srcfmt = info->src; SDL_PixelFormat *dstfmt = info->dst; Uint8 srcbpp = srcfmt->BytesPerPixel; Uint8 dstbpp = dstfmt->BytesPerPixel; while (height--) { GFX_DUFFS_LOOP4( { Uint32 pixel; unsigned sR; unsigned sG; unsigned sB; unsigned sA; unsigned dR; unsigned dG; unsigned dB; unsigned dA; unsigned sAA; GFX_DISASSEMBLE_RGBA(src, srcbpp, srcfmt, pixel, sR, sG, sB, sA); GFX_DISASSEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA); sAA=GFX_ALPHA_ADJUST_ARRAY[sA & 255]; GFX_ALPHA_BLEND(sR, sG, sB, sAA, dR, dG, dB); dA |= sAA; GFX_ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); src += srcbpp; dst += dstbpp; }, width); src += srcskip; dst += dstskip; } } /*! \brief Internal blitter setup wrapper for RGBA->RGBA blits. Sets up the blitter info based on the 'src' and 'dst' surfaces and rectangles. \param src The source surface. \param srcrect The source rectangle. \param dst The destination surface. \param dstrect The destination rectangle. \returns Returns 1 if blit was performed, 0 otherwise. */ int _SDL_gfxBlitRGBACall(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect) { /* * Set up source and destination buffer pointers, then blit */ if (srcrect->w && srcrect->h) { SDL_gfxBlitInfo info; /* * Set up the blit information */ #if (SDL_MINOR_VERSION == 3) info.s_pixels = (Uint8 *) src->pixels + (Uint16) srcrect->y * src->pitch + (Uint16) srcrect->x * src->format->BytesPerPixel; #else info.s_pixels = (Uint8 *) src->pixels + src->offset + (Uint16) srcrect->y * src->pitch + (Uint16) srcrect->x * src->format->BytesPerPixel; #endif info.s_width = srcrect->w; info.s_height = srcrect->h; info.s_skip = (int)(src->pitch - info.s_width * src->format->BytesPerPixel); #if (SDL_MINOR_VERSION == 3) info.d_pixels = (Uint8 *) dst->pixels + (Uint16) dstrect->y * dst->pitch + (Uint16) dstrect->x * dst->format->BytesPerPixel; #else info.d_pixels = (Uint8 *) dst->pixels + dst->offset + (Uint16) dstrect->y * dst->pitch + (Uint16) dstrect->x * dst->format->BytesPerPixel; #endif info.d_width = dstrect->w; info.d_height = dstrect->h; info.d_skip = (int)(dst->pitch - info.d_width * dst->format->BytesPerPixel); info.aux_data = NULL; info.src = src->format; info.table = NULL; info.dst = dst->format; /* * Run the actual software blitter */ _SDL_gfxBlitBlitterRGBA(&info); return 1; } return (0); } /*! \brief Blitter for RGBA->RGBA blits with alpha adjustment. Verifies the input 'src' and 'dst' surfaces and rectangles and performs blit. The destination clip rectangle is honored. \param src The source surface. \param srcrect The source rectangle. \param dst The destination surface. \param dstrect The destination rectangle. \returns Returns 1 if blit was performed, 0 otherwise, or -1 if an error occured. */ int SDL_gfxBlitRGBA(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect) { SDL_Rect sr, dr; int srcx, srcy, w, h; /* * Make sure the surfaces aren't locked */ if (!src || !dst) { SDL_SetError("SDL_UpperBlit: passed a NULL surface"); return (-1); } if ((src->locked) || (dst->locked)) { SDL_SetError("Surfaces must not be locked during blit"); return (-1); } /* * If the destination rectangle is NULL, use the entire dest surface */ if (dstrect == NULL) { dr.x = dr.y = 0; dr.w = dst->w; dr.h = dst->h; } else { dr = *dstrect; } /* * Clip the source rectangle to the source surface */ if (srcrect) { int maxw, maxh; srcx = srcrect->x; w = srcrect->w; if (srcx < 0) { w += srcx; dr.x -= srcx; srcx = 0; } maxw = src->w - srcx; if (maxw < w) w = maxw; srcy = srcrect->y; h = srcrect->h; if (srcy < 0) { h += srcy; dr.y -= srcy; srcy = 0; } maxh = src->h - srcy; if (maxh < h) h = maxh; } else { srcx = srcy = 0; w = src->w; h = src->h; } /* * Clip the destination rectangle against the clip rectangle */ { SDL_Rect *clip = &dst->clip_rect; int dx, dy; dx = clip->x - dr.x; if (dx > 0) { w -= dx; dr.x += dx; srcx += dx; } dx = dr.x + w - clip->x - clip->w; if (dx > 0) w -= dx; dy = clip->y - dr.y; if (dy > 0) { h -= dy; dr.y += dy; srcy += dy; } dy = dr.y + h - clip->y - clip->h; if (dy > 0) h -= dy; } if (w > 0 && h > 0) { sr.x = srcx; sr.y = srcy; sr.w = dr.w = w; sr.h = dr.h = h; return (_SDL_gfxBlitRGBACall(src, &sr, dst, &dr)); } return 0; } /*! \brief Sets the alpha channel in a 32 bit surface. Helper function that sets the alpha channel in a 32 bit surface to a constant value. Only 32 bit surfaces can be used with this function. \param src Pointer to the target surface to change. \param a The alpha value to set. \return Returns 1 if alpha was changed, -1 otherwise. */ int SDL_gfxSetAlpha(SDL_Surface *src, Uint8 a) { #if SDL_BYTEORDER == SDL_BIG_ENDIAN const int alpha_offset = 0; #else const int alpha_offset = 3; #endif int i, j, row_skip; Uint8 *pixels; /* Check if we have a 32bit surface */ if ( (src==NULL) || (src->format==NULL) || (src->format->BytesPerPixel!=4) ) { SDL_SetError("SDL_gfxSetAlpha: Invalid input surface."); return -1; } /* * Lock the surface */ if (SDL_MUSTLOCK(src)) { if (SDL_LockSurface(src) < 0) { return (-1); } } /* Process */ pixels = (Uint8 *)src->pixels; row_skip = (src->pitch - (4*src->w)); pixels += alpha_offset; for ( i=0; i<src->h; i++ ) { for ( j=0; j<src->w; j++ ) { *pixels = a; pixels += 4; } pixels += row_skip; } /* * Unlock surface */ if (SDL_MUSTLOCK(src)) { SDL_UnlockSurface(src); } return 1; } /*! \brief Multiply the alpha channel in a 32bit surface. Helper function that multiplies the alpha channel in a 32 bit surface with a constant value. The final alpha is always scaled to the range 0-255 (i.e. the factor is a/256). Only 32 bit surfaces can be used with this function. \param src Pointer to the target surface to change. \param a The alpha value to multiply with. When a is 255, this function is a NoOp. \return Returns 1 if alpha was changed, 0 otherwise. Returns -1 if input surface is invalid. */ int SDL_gfxMultiplyAlpha(SDL_Surface *src, Uint8 a) { #if SDL_BYTEORDER == SDL_BIG_ENDIAN const int alpha_offset = 0; #else const int alpha_offset = 3; #endif int i, j, row_skip; Uint8 *pixels; /* Check if we have a 32bit surface */ if ( (src==NULL) || (src->format==NULL) || (src->format->BytesPerPixel!=4) ) { SDL_SetError("SDL_gfxMultiplyAlpha: Invalid input surface."); return -1; } /* Check if multiplication is needed */ if (a==255) { return 0; } /* * Lock the surface */ if (SDL_MUSTLOCK(src)) { if (SDL_LockSurface(src) < 0) { return (-1); } } /* Process */ pixels = (Uint8 *)src->pixels; row_skip = (src->pitch - (4*src->w)); pixels += alpha_offset; for ( i=0; i<src->h; i++ ) { for ( j=0; j<src->w; j++ ) { *pixels = (Uint8)(((int)(*pixels)*a)>>8); pixels += 4; } pixels += row_skip; } /* * Unlock surface */ if (SDL_MUSTLOCK(src)) { SDL_UnlockSurface(src); } return 1; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/SDL_gfxBlitFunc.h�������������������������������������������������������������0000664�0000000�0000000�00000010562�12247171015�0017660�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* SDL_gfxBlitFunc.h: custom blitters Copyright (C) 2001-2011 Andreas Schiffler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Andreas Schiffler -- aschiffler at ferzkopp dot net */ #pragma once #ifndef _SDL_gfxBlitFunc_h #define _SDL_gfxBlitFunc_h /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus extern "C" { #endif #include <stdio.h> #include <stdlib.h> #include <SDL.h> #include <SDL_video.h> /* ---- Function Prototypes */ #ifdef _MSC_VER # if defined(DLL_EXPORT) && !defined(LIBSDL_GFX_DLL_IMPORT) # define SDL_GFXBLITFUNC_SCOPE __declspec(dllexport) # else # ifdef LIBSDL_GFX_DLL_IMPORT # define SDL_GFXBLITFUNC_SCOPE __declspec(dllimport) # endif # endif #endif #ifndef SDL_GFXBLITFUNC_SCOPE # define SDL_GFXBLITFUNC_SCOPE extern #endif SDL_GFXBLITFUNC_SCOPE int SDL_gfxBlitRGBA(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect); SDL_GFXBLITFUNC_SCOPE int SDL_gfxSetAlpha(SDL_Surface * src, Uint8 a); SDL_GFXBLITFUNC_SCOPE int SDL_gfxMultiplyAlpha(SDL_Surface * src, Uint8 a); /* -------- Macros */ /* Define SDL macros locally as a substitute for an #include "SDL_blit.h", */ /* which doesn't work since the include file doesn't get installed. */ /*! \brief The structure passed to the low level blit functions. */ typedef struct { Uint8 *s_pixels; int s_width; int s_height; int s_skip; Uint8 *d_pixels; int d_width; int d_height; int d_skip; void *aux_data; SDL_PixelFormat *src; Uint8 *table; SDL_PixelFormat *dst; } SDL_gfxBlitInfo; /*! \brief Unwrap RGBA values from a pixel using mask, shift and loss for surface. */ #define GFX_RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a) \ { \ r = ((pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss; \ g = ((pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss; \ b = ((pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss; \ a = ((pixel&fmt->Amask)>>fmt->Ashift)<<fmt->Aloss; \ } /*! \brief Disassemble buffer pointer into a pixel and separate RGBA values. */ #define GFX_DISASSEMBLE_RGBA(buf, bpp, fmt, pixel, r, g, b, a) \ do { \ pixel = *((Uint32 *)(buf)); \ GFX_RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a); \ pixel &= ~fmt->Amask; \ } while(0) /*! \brief Wrap a pixel from RGBA values using mask, shift and loss for surface. */ #define GFX_PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a) \ { \ pixel = ((r>>fmt->Rloss)<<fmt->Rshift)| \ ((g>>fmt->Gloss)<<fmt->Gshift)| \ ((b>>fmt->Bloss)<<fmt->Bshift)| \ ((a<<fmt->Aloss)<<fmt->Ashift); \ } /*! \brief Assemble pixel into buffer pointer from separate RGBA values. */ #define GFX_ASSEMBLE_RGBA(buf, bpp, fmt, r, g, b, a) \ { \ Uint32 pixel; \ \ GFX_PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a); \ *((Uint32 *)(buf)) = pixel; \ } /*! \brief Blend the RGB values of two pixels based on a source alpha value. */ #define GFX_ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB) \ do { \ dR = (((sR-dR)*(A))/255)+dR; \ dG = (((sG-dG)*(A))/255)+dG; \ dB = (((sB-dB)*(A))/255)+dB; \ } while(0) /*! \brief 4-times unrolled DUFFs loop. This is a very useful loop for optimizing blitters. */ #define GFX_DUFFS_LOOP4(pixel_copy_increment, width) \ { int n = (width+3)/4; \ switch (width & 3) { \ case 0: do { pixel_copy_increment; \ case 3: pixel_copy_increment; \ case 2: pixel_copy_increment; \ case 1: pixel_copy_increment; \ } while ( --n > 0 ); \ } \ } /* Ends C function definitions when using C++ */ #ifdef __cplusplus } #endif #endif /* _SDL_gfxBlitFunc_h */ ����������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/SaveLoad.cpp������������������������������������������������������������������0000664�0000000�0000000�00000031232�12247171015�0016771�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * Save and Load functions for the GameStatePlay. * * I put these in a separate cpp file just to keep GameStatePlay.cpp devoted to its core. * * class GameStatePlay */ #include "CommonIncludes.h" #include "FileParser.h" #include "GameStatePlay.h" #include "MapRenderer.h" #include "MenuActionBar.h" #include "MenuCharacter.h" #include "Menu.h" #include "MenuInventory.h" #include "MenuManager.h" #include "MenuStash.h" #include "MenuTalker.h" #include "Settings.h" #include "UtilsFileSystem.h" #include "UtilsParsing.h" #include "SharedGameResources.h" using namespace std; /** * Before exiting the game, save to file */ void GameStatePlay::saveGame() { // game slots are currently 1-4 if (game_slot == 0) return; // remove items with zero quantity from inventory menu->inv->inventory[EQUIPMENT].clean(); menu->inv->inventory[CARRIED].clean(); ofstream outfile; stringstream ss; ss.str(""); ss << PATH_USER; if (GAME_PREFIX.length() > 0) ss << GAME_PREFIX << "_"; ss << "save" << game_slot << ".txt"; outfile.open(ss.str().c_str(), ios::out); if (outfile.is_open()) { // hero name outfile << "name=" << pc->stats.name << "\n"; // permadeath outfile << "permadeath=" << pc->stats.permadeath << "\n"; // hero visual option outfile << "option=" << pc->stats.gfx_base << "," << pc->stats.gfx_head << "," << pc->stats.gfx_portrait << "\n"; // hero class outfile << "class=" << pc->stats.character_class << "\n"; // current experience outfile << "xp=" << pc->stats.xp << "\n"; // hp and mp if (SAVE_HPMP) outfile << "hpmp=" << pc->stats.hp << "," << pc->stats.mp << "\n"; // stat spec outfile << "build=" << pc->stats.physical_character << "," << pc->stats.mental_character << "," << pc->stats.offense_character << "," << pc->stats.defense_character << "\n"; // equipped gear outfile << "equipped_quantity=" << menu->inv->inventory[EQUIPMENT].getQuantities() << "\n"; outfile << "equipped=" << menu->inv->inventory[EQUIPMENT].getItems() << "\n"; // carried items outfile << "carried_quantity=" << menu->inv->inventory[CARRIED].getQuantities() << "\n"; outfile << "carried=" << menu->inv->inventory[CARRIED].getItems() << "\n"; // spawn point outfile << "spawn=" << mapr->respawn_map << "," << (int)mapr->respawn_point.x << "," << (int)mapr->respawn_point.y << "\n"; // action bar outfile << "actionbar="; for (int i=0; i<12; i++) { if (pc->stats.transformed) outfile << menu->act->actionbar[i]; else outfile << menu->act->hotkeys[i]; if (i<11) outfile << ","; } outfile << "\n"; //shapeshifter value if (pc->stats.transform_type == "untransform" || pc->stats.transform_duration != -1) outfile << "transformed=" << "\n"; else outfile << "transformed=" << pc->stats.transform_type << "," << pc->stats.manual_untransform << "\n"; // restore hero powers if (pc->stats.transformed && pc->hero_stats) { pc->stats.powers_list = pc->hero_stats->powers_list; } // enabled powers outfile << "powers="; for (unsigned int i=0; i<pc->stats.powers_list.size(); i++) { if (i < pc->stats.powers_list.size()-1) { if (pc->stats.powers_list[i] > 0) outfile << pc->stats.powers_list[i] << ","; } else { if (pc->stats.powers_list[i] > 0) outfile << pc->stats.powers_list[i]; } } outfile << "\n"; // restore transformed powers if (pc->stats.transformed && pc->charmed_stats) { pc->stats.powers_list = pc->charmed_stats->powers_list; } // campaign data outfile << "campaign="; outfile << camp->getAll(); outfile << endl; if (outfile.bad()) fprintf(stderr, "Unable to save the game. No write access or disk is full!\n"); outfile.close(); outfile.clear(); } // Save stash ss.str(""); ss << PATH_USER; if (GAME_PREFIX.length() > 0) ss << GAME_PREFIX << "_"; ss << "stash"; if (pc->stats.permadeath) ss << "_HC" << game_slot; ss << ".txt"; outfile.open(ss.str().c_str(), ios::out); if (outfile.is_open()) { outfile << "quantity=" << menu->stash->stock.getQuantities() << "\n"; outfile << "item=" << menu->stash->stock.getItems() << "\n"; outfile << endl; if (outfile.bad()) fprintf(stderr, "Unable to save stash. No write access or disk is full!\n"); outfile.close(); outfile.clear(); } } /** * When loading the game, load from file if possible */ void GameStatePlay::loadGame() { int saved_hp = 0; int saved_mp = 0; int currency = 0; // game slots are currently 1-4 if (game_slot == 0) return; FileParser infile; int hotkeys[12]; for (int i=0; i<12; i++) { hotkeys[i] = -1; } stringstream ss; ss.str(""); ss << PATH_USER; if (GAME_PREFIX.length() > 0) ss << GAME_PREFIX << "_"; ss << "save" << game_slot << ".txt"; if (infile.open(ss.str(), false)) { while (infile.next()) { if (infile.key == "name") pc->stats.name = infile.val; else if (infile.key == "permadeath") { pc->stats.permadeath = toBool(infile.val); } else if (infile.key == "option") { pc->stats.gfx_base = infile.nextValue(); pc->stats.gfx_head = infile.nextValue(); pc->stats.gfx_portrait = infile.nextValue(); } else if (infile.key == "class") { pc->stats.character_class = infile.nextValue(); } else if (infile.key == "xp") { pc->stats.xp = toUnsignedLong(infile.val); } else if (infile.key == "hpmp") { saved_hp = toInt(infile.nextValue()); saved_mp = toInt(infile.nextValue()); } else if (infile.key == "build") { pc->stats.physical_character = toInt(infile.nextValue()); pc->stats.mental_character = toInt(infile.nextValue()); pc->stats.offense_character = toInt(infile.nextValue()); pc->stats.defense_character = toInt(infile.nextValue()); if (pc->stats.physical_character < 0 || pc->stats.physical_character > pc->stats.max_points_per_stat || pc->stats.mental_character < 0 || pc->stats.mental_character > pc->stats.max_points_per_stat || pc->stats.offense_character < 0 || pc->stats.offense_character > pc->stats.max_points_per_stat || pc->stats.defense_character < 0 || pc->stats.defense_character > pc->stats.max_points_per_stat) { fprintf(stderr, "Some basic stats are out of bounds, setting to zero\n"); pc->stats.physical_character = 0; pc->stats.mental_character = 0; pc->stats.offense_character = 0; pc->stats.defense_character = 0; } } else if (infile.key == "currency") { currency = toInt(infile.val); } else if (infile.key == "equipped") { menu->inv->inventory[EQUIPMENT].setItems(infile.val); } else if (infile.key == "equipped_quantity") { menu->inv->inventory[EQUIPMENT].setQuantities(infile.val); } else if (infile.key == "carried") { menu->inv->inventory[CARRIED].setItems(infile.val); } else if (infile.key == "carried_quantity") { menu->inv->inventory[CARRIED].setQuantities(infile.val); } else if (infile.key == "spawn") { mapr->teleport_mapname = infile.nextValue(); if (fileExists(mods->locate("maps/" + mapr->teleport_mapname))) { mapr->teleport_destination.x = toInt(infile.nextValue()) + 0.5f; mapr->teleport_destination.y = toInt(infile.nextValue()) + 0.5f; mapr->teleportation = true; // prevent spawn.txt from putting us on the starting map mapr->clearEvents(); } else { fprintf(stderr, "Unable to find maps/%s, loading spawn.txt\n", mapr->teleport_mapname.c_str()); mapr->teleport_mapname = "spawn.txt"; mapr->teleport_destination.x = 1; mapr->teleport_destination.y = 1; mapr->teleportation = true; } } else if (infile.key == "actionbar") { for (int i=0; i<12; i++) { hotkeys[i] = toInt(infile.nextValue()); if (hotkeys[i] < 0) { fprintf(stderr, "Hotkey power on position %d has negative id, skipping\n", i); hotkeys[i] = 0; } else if ((unsigned)hotkeys[i] > powers->powers.size()-1) { fprintf(stderr, "Hotkey power id (%d) out of bounds 1-%d, skipping\n", hotkeys[i], (int)powers->powers.size()); hotkeys[i] = 0; } else if (hotkeys[i] != 0 && powers->powers[hotkeys[i]].name == "") { fprintf(stderr, "Hotkey power with id=%d, found on position %d does not exist, skipping\n", hotkeys[i], i); hotkeys[i] = 0; } } menu->act->set(hotkeys); } else if (infile.key == "transformed") { pc->stats.transform_type = infile.nextValue(); if (pc->stats.transform_type != "") { pc->stats.transform_duration = -1; pc->stats.manual_untransform = toBool(infile.nextValue()); } } else if (infile.key == "powers") { string power; while ( (power = infile.nextValue()) != "") { if (toInt(power) > 0) pc->stats.powers_list.push_back(toInt(power)); } } else if (infile.key == "campaign") camp->setAll(infile.val); } infile.close(); } else fprintf(stderr, "Unable to open %s!\n", ss.str().c_str()); menu->inv->inventory[EQUIPMENT].fillEquipmentSlots(); menu->inv->addCurrency(currency); // remove items with zero quantity from inventory menu->inv->inventory[EQUIPMENT].clean(); menu->inv->inventory[CARRIED].clean(); // Load stash loadStash(); // initialize vars pc->stats.recalc(); menu->inv->applyEquipment(menu->inv->inventory[EQUIPMENT].storage); // trigger passive effects here? Saved HP/MP values might depend on passively boosted HP/MP // powers->activatePassives(pc->stats); pc->stats.logic(); // run stat logic once to apply items bonuses if (SAVE_HPMP) { if (saved_hp < 0 || saved_hp > pc->stats.get(STAT_HP_MAX)) { fprintf(stderr, "HP value is out of bounds, setting to maximum\n"); pc->stats.hp = pc->stats.get(STAT_HP_MAX); } else pc->stats.hp = saved_hp; if (saved_mp < 0 || saved_mp > pc->stats.get(STAT_MP_MAX)) { fprintf(stderr, "MP value is out of bounds, setting to maximum\n"); pc->stats.mp = pc->stats.get(STAT_MP_MAX); } else pc->stats.mp = saved_mp; } else { pc->stats.hp = pc->stats.get(STAT_HP_MAX); pc->stats.mp = pc->stats.get(STAT_MP_MAX); } // reset character menu menu->chr->refreshStats(); // just for aesthetics, turn the hero to face the camera pc->stats.direction = 6; // set up MenuTalker for this hero menu->talker->setHero(pc->stats.name, pc->stats.character_class, pc->stats.gfx_portrait); // load sounds (gender specific) pc->loadSounds(); // apply power upgrades menu->pow->applyPowerUpgrades(); } /** * Load a class definition, index */ void GameStatePlay::loadClass(int index) { // game slots are currently 1-4 if (game_slot == 0) return; pc->stats.character_class = HERO_CLASSES[index].name; pc->stats.physical_character += HERO_CLASSES[index].physical; pc->stats.mental_character += HERO_CLASSES[index].mental; pc->stats.offense_character += HERO_CLASSES[index].offense; pc->stats.defense_character += HERO_CLASSES[index].defense; menu->inv->addCurrency(HERO_CLASSES[index].currency); menu->inv->inventory[EQUIPMENT].setItems(HERO_CLASSES[index].equipment); for (unsigned i=0; i<HERO_CLASSES[index].powers.size(); i++) { pc->stats.powers_list.push_back(HERO_CLASSES[index].powers[i]); } for (unsigned i=0; i<HERO_CLASSES[index].statuses.size(); i++) { camp->setStatus(HERO_CLASSES[index].statuses[i]); } menu->act->set(HERO_CLASSES[index].hotkeys); menu->inv->inventory[EQUIPMENT].fillEquipmentSlots(); // initialize vars pc->stats.recalc(); menu->inv->applyEquipment(menu->inv->inventory[EQUIPMENT].storage); // reset character menu menu->chr->refreshStats(); } /* * This is used to load the stash when starting a new game */ void GameStatePlay::loadStash() { // Load stash FileParser infile; stringstream ss; ss.str(""); ss << PATH_USER; if (GAME_PREFIX.length() > 0) ss << GAME_PREFIX << "_"; ss << "stash"; if (pc->stats.permadeath) ss << "_HC" << game_slot; ss << ".txt"; if (infile.open(ss.str(), false)) { while (infile.next()) { if (infile.key == "item") { menu->stash->stock.setItems(infile.val); } else if (infile.key == "quantity") { menu->stash->stock.setQuantities(infile.val); } } infile.close(); } else fprintf(stderr, "Unable to open %s!\n", ss.str().c_str()); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/Settings.cpp������������������������������������������������������������������0000664�0000000�0000000�00000054232�12247171015�0017100�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * Settings */ #include <cstring> #include <typeinfo> #include <cmath> using namespace std; #include "CommonIncludes.h" #include "FileParser.h" #include "Settings.h" #include "Utils.h" #include "UtilsParsing.h" #include "UtilsFileSystem.h" #include "SharedResources.h" #ifdef _MSC_VER #define log2(x) logf(x)/logf(2) #endif class ConfigEntry { public: const char * name; const type_info * type; const char * default_val; void * storage; const char * comment; }; ConfigEntry config[] = { { "fullscreen", &typeid(FULLSCREEN), "0", &FULLSCREEN, "fullscreen mode. 1 enable, 0 disable."}, { "resolution_w", &typeid(VIEW_W), "640", &VIEW_W, "display resolution. 640x480 minimum."}, { "resolution_h", &typeid(VIEW_H), "480", &VIEW_H, NULL}, { "audio", &typeid(AUDIO), "1", &AUDIO, "Enable music and sound subsystem."}, { "music_volume", &typeid(MUSIC_VOLUME), "96", &MUSIC_VOLUME, "music and sound volume (0 = silent, 128 = max)"}, { "sound_volume", &typeid(SOUND_VOLUME), "128", &SOUND_VOLUME, NULL}, { "combat_text", &typeid(COMBAT_TEXT), "0", &COMBAT_TEXT, "display floating damage text. 1 enable, 0 disable."}, { "mouse_move", &typeid(MOUSE_MOVE), "0", &MOUSE_MOVE, "use mouse to move (experimental). 1 enable, 0 disable."}, { "hwsurface", &typeid(HWSURFACE), "1", &HWSURFACE, "hardware surfaces, double buffering. Try disabling for performance. 1 enable, 0 disable."}, { "doublebuf", &typeid(DOUBLEBUF), "1", &DOUBLEBUF, NULL}, { "animated_tiles", &typeid(ANIMATED_TILES), "1", &ANIMATED_TILES, "animated tiles. Try disabling for performance. 1 enable, 0 disable."}, { "enable_joystick", &typeid(ENABLE_JOYSTICK), "0", &ENABLE_JOYSTICK, "joystick settings."}, { "joystick_device", &typeid(JOYSTICK_DEVICE), "0", &JOYSTICK_DEVICE, NULL}, { "joystick_deadzone",&typeid(JOY_DEADZONE), "100", &JOY_DEADZONE, NULL}, { "language", &typeid(LANGUAGE), "en", &LANGUAGE, "2-letter language code."}, { "change_gamma", &typeid(CHANGE_GAMMA), "0", &CHANGE_GAMMA, "allow changing gamma (experimental). 1 enable, 0 disable."}, { "gamma", &typeid(GAMMA), "1.0", &GAMMA, "screen gamma (0.5 = darkest, 2.0 = lightest)"}, { "texture_quality", &typeid(TEXTURE_QUALITY), "1", &TEXTURE_QUALITY, "texture quality (0 = low quality, 1 = high quality)"}, { "mouse_aim", &typeid(MOUSE_AIM), "1", &MOUSE_AIM, "use mouse to aim. 1 enable, 0 disable."}, { "no_mouse", &typeid(NO_MOUSE), "0", &NO_MOUSE, "make using mouse secondary, give full control to keyboard. 1 enable, 0 disable."}, { "show_fps", &typeid(SHOW_FPS), "0", &SHOW_FPS, "show frames per second. 1 enable, 0 disable."}, { "show_hotkeys", &typeid(SHOW_HOTKEYS), "1", &SHOW_HOTKEYS, "show hotkeys names on power bar. 1 enable, 0 disable."}, { "colorblind", &typeid(COLORBLIND), "0", &COLORBLIND, "enable colorblind tooltips. 1 enable, 0 disable"} }; const int config_size = sizeof(config) / sizeof(ConfigEntry); // Paths string GAME_FOLDER = "default"; string DEFAULT_FOLDER = "default"; string PATH_CONF = ""; string PATH_USER = ""; string PATH_DATA = ""; string CUSTOM_PATH_DATA = ""; string PATH_DEFAULT_USER = ""; string PATH_DEFAULT_DATA = ""; // Filenames string FILE_SETTINGS = "settings.txt"; string FILE_KEYBINDINGS = "keybindings.txt"; // Tile Settings float UNITS_PER_PIXEL_X = 2; float UNITS_PER_PIXEL_Y = 4; unsigned short TILE_W = 64; unsigned short TILE_H = 32; unsigned short TILE_W_HALF = TILE_W/2; unsigned short TILE_H_HALF = TILE_H/2; unsigned short TILESET_ISOMETRIC = 0; unsigned short TILESET_ORTHOGONAL = 1; unsigned short TILESET_ORIENTATION = TILESET_ISOMETRIC; // Main Menu frame size unsigned short FRAME_W; unsigned short FRAME_H; unsigned short ICON_SIZE; // Video Settings bool FULLSCREEN; unsigned short MAX_FRAMES_PER_SEC = 30; unsigned char BITS_PER_PIXEL = 32; unsigned short VIEW_W; unsigned short VIEW_H; unsigned short VIEW_W_HALF = VIEW_W/2; unsigned short VIEW_H_HALF = VIEW_H/2; short MIN_VIEW_W = -1; short MIN_VIEW_H = -1; bool DOUBLEBUF; bool HWSURFACE; bool CHANGE_GAMMA; float GAMMA; bool TEXTURE_QUALITY; bool ANIMATED_TILES; // Audio Settings bool AUDIO; unsigned short MUSIC_VOLUME; unsigned short SOUND_VOLUME; // User Preferences bool COMBAT_TEXT; // Input Settings bool MOUSE_MOVE; bool ENABLE_JOYSTICK; int JOYSTICK_DEVICE; bool MOUSE_AIM; bool NO_MOUSE; int JOY_DEADZONE; // Language Settings std::string LANGUAGE = "en"; // Autopickup Settings bool AUTOPICKUP_CURRENCY = false; // Combat calculation caps (percentage) short MAX_ABSORB = 90; short MAX_RESIST = 90; short MAX_BLOCK = 100; short MAX_AVOIDANCE = 99; short MIN_ABSORB = 0; short MIN_RESIST = 0; short MIN_BLOCK = 0; short MIN_AVOIDANCE = 0; // Elemental types std::vector<Element> ELEMENTS; // Equipment flags std::map<std::string,std::string> EQUIP_FLAGS; // Hero classes std::vector<HeroClass> HERO_CLASSES; // Currency settings std::string CURRENCY = "Gold"; float VENDOR_RATIO = 0.25; // Death penalty settings bool DEATH_PENALTY = true; bool DEATH_PENALTY_PERMADEATH = false; int DEATH_PENALTY_CURRENCY = 50; int DEATH_PENALTY_XP = 0; int DEATH_PENALTY_XP_CURRENT = 0; bool DEATH_PENALTY_ITEM = false; // Other Settings bool MENUS_PAUSE = false; bool SAVE_HPMP = false; bool ENABLE_PLAYGAME = false; bool SHOW_FPS = false; bool SHOW_HOTKEYS = true; bool COLORBLIND = false; int CORPSE_TIMEOUT = 1800; bool SELL_WITHOUT_VENDOR = true; int AIM_ASSIST = 0; std::string GAME_PREFIX = ""; std::string WINDOW_TITLE = "Flare"; int SOUND_FALLOFF = 15; int PARTY_EXP_PERCENTAGE = 100; bool ENABLE_ALLY_COLLISION_AI = true; bool ENABLE_ALLY_COLLISION = true; int CURRENCY_ID = 1; float INTERACT_RANGE = 3; /** * Set system paths * PATH_CONF is for user-configurable settings files (e.g. keybindings) * PATH_USER is for user-specific data (e.g. save games) * PATH_DATA is for common game data (e.g. images, music) */ #ifdef _WIN32 // Windows paths void setPaths() { // handle Windows-specific path options PATH_CONF = "config"; PATH_USER = "saves"; PATH_DATA = ""; PATH_DEFAULT_USER = ""; PATH_DEFAULT_DATA = ""; if (dirExists(CUSTOM_PATH_DATA)) PATH_DATA = CUSTOM_PATH_DATA; else if (!CUSTOM_PATH_DATA.empty()) fprintf(stderr, "Error: Could not find specified game data directory.\n"); // TODO: place config and save data in the user's home, windows style createDir(PATH_CONF); createDir(PATH_USER); PATH_CONF = PATH_CONF + "/"; PATH_USER = PATH_USER + "/"; } #elif __amigaos4__ // AmigaOS paths void setPaths() { PATH_CONF = "PROGDIR:"; PATH_USER = "PROGDIR:"; PATH_DATA = "PROGDIR:"; PATH_DEFAULT_USER = "PROGDIR:"; PATH_DEFAULT_DATA = "PROGDIR:"; if (dirExists(CUSTOM_PATH_DATA)) PATH_DATA = CUSTOM_PATH_DATA; else if (!CUSTOM_PATH_DATA.empty()) fprintf(stderr, "Error: Could not find specified game data directory.\n"); } #else void setPaths() { // attempting to follow this spec: // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html // Note: If the GAME_FOLDER isn't defined, we fall back to using the current directory // set config path (settings, keybindings) // $XDG_CONFIG_HOME/flare/ if (getenv("XDG_CONFIG_HOME") != NULL) { PATH_CONF = (string)getenv("XDG_CONFIG_HOME") + "/flare/"; createDir(PATH_CONF); PATH_CONF += GAME_FOLDER + "/"; createDir(PATH_CONF); } // $HOME/.config/flare/ else if (getenv("HOME") != NULL) { PATH_CONF = (string)getenv("HOME") + "/.config/"; createDir(PATH_CONF); PATH_CONF += "flare/"; createDir(PATH_CONF); PATH_CONF += GAME_FOLDER + "/"; createDir(PATH_CONF); } // ./config/ else { PATH_CONF = "./config/"; createDir(PATH_CONF); } // set user path (save games) // $XDG_DATA_HOME/flare/ if (getenv("XDG_DATA_HOME") != NULL) { PATH_USER = (string)getenv("XDG_DATA_HOME") + "/flare/"; createDir(PATH_USER); PATH_DEFAULT_USER = PATH_USER + DEFAULT_FOLDER + "/"; PATH_USER += GAME_FOLDER + "/"; createDir(PATH_USER); createDir(PATH_USER + "mods/"); createDir(PATH_DEFAULT_USER); createDir(PATH_DEFAULT_USER + "mods/"); } // $HOME/.local/share/flare/ else if (getenv("HOME") != NULL) { PATH_USER = (string)getenv("HOME") + "/.local/"; createDir(PATH_USER); PATH_USER += "share/"; createDir(PATH_USER); PATH_USER += "flare/"; createDir(PATH_USER); PATH_DEFAULT_USER = PATH_USER + DEFAULT_FOLDER + "/"; PATH_USER += GAME_FOLDER + "/"; createDir(PATH_USER); createDir(PATH_USER + "mods/"); createDir(PATH_DEFAULT_USER); createDir(PATH_DEFAULT_USER + "mods/"); } // ./saves/ else { PATH_USER = "./saves/"; createDir(PATH_USER); PATH_DEFAULT_USER = "./saves/"; createDir(PATH_DEFAULT_USER); } // data folder // while PATH_CONF and PATH_USER are created if not found, // PATH_DATA must already have the game data for the game to work. // in most releases the data will be in the same folder as the executable // - Windows apps are released as a simple folder // - OSX apps are released in a .app folder // Official linux distros might put the executable and data files // in a more standard location. // these flags are set to true when a valid directory is found bool path_data = false; bool path_default_data = false; // if the user specified a data path, try to use it if (dirExists(CUSTOM_PATH_DATA)) { if (!path_data) PATH_DATA = CUSTOM_PATH_DATA; if (!path_default_data) PATH_DEFAULT_DATA = CUSTOM_PATH_DATA; path_data = path_default_data = true; } else if (!CUSTOM_PATH_DATA.empty()) fprintf(stderr, "Error: Could not find specified game data directory.\n"); // Check for the local data before trying installed ones. if (dirExists("./mods")) { if (!path_data) PATH_DATA = "./"; if (!path_default_data) PATH_DEFAULT_DATA = "./"; path_data = path_default_data = true; } // check $XDG_DATA_DIRS options // a list of directories in preferred order separated by : if (getenv("XDG_DATA_DIRS") != NULL) { string pathlist = (string)getenv("XDG_DATA_DIRS"); string pathtest; pathtest = eatFirstString(pathlist,':'); while (pathtest != "") { if (!path_data) { PATH_DATA = pathtest + "/flare/" + GAME_FOLDER + "/"; if (dirExists(PATH_DATA)) path_data = true; } if (!path_default_data) { PATH_DEFAULT_DATA = pathtest + "/flare/" + DEFAULT_FOLDER + "/"; if (dirExists(PATH_DEFAULT_DATA)) path_default_data = true; } if (path_data && path_default_data) break; pathtest = eatFirstString(pathlist,':'); } } #if defined DATA_INSTALL_DIR if (!path_data) PATH_DATA = DATA_INSTALL_DIR "/" + GAME_FOLDER + "/"; if (!path_data && dirExists(PATH_DATA)) path_data = true; if (!path_default_data) PATH_DEFAULT_DATA = DATA_INSTALL_DIR "/" + DEFAULT_FOLDER + "/"; if (!path_default_data && dirExists(PATH_DEFAULT_DATA)) path_default_data = true; #endif // check /usr/local/share/flare/ and /usr/share/flare/ next if (!path_data) PATH_DATA = "/usr/local/share/flare/" + GAME_FOLDER + "/"; if (!path_data && dirExists(PATH_DATA)) path_data = true; if (!path_default_data) PATH_DEFAULT_DATA = "/usr/local/share/flare/" + DEFAULT_FOLDER + "/"; if (!path_default_data && dirExists(PATH_DEFAULT_DATA)) path_default_data = true; if (!path_data) PATH_DATA = "/usr/share/flare/" + GAME_FOLDER + "/"; if (!path_data && dirExists(PATH_DATA)) path_data = true; if (!path_default_data) PATH_DEFAULT_DATA = "/usr/share/flare/" + DEFAULT_FOLDER + "/"; if (!path_default_data && dirExists(PATH_DEFAULT_DATA)) path_default_data = true; // check "games" variants of these if (!path_data) PATH_DATA = "/usr/local/share/games/flare/" + GAME_FOLDER + "/"; if (!path_data && dirExists(PATH_DATA)) path_data = true; if (!path_default_data) PATH_DEFAULT_DATA = "/usr/local/share/games/flare/" + DEFAULT_FOLDER + "/"; if (!path_default_data && dirExists(PATH_DEFAULT_DATA)) path_default_data = true; if (!path_data) PATH_DATA = "/usr/share/games/flare/" + GAME_FOLDER + "/"; if (!path_data && dirExists(PATH_DATA)) path_data = true; if (!path_default_data) PATH_DEFAULT_DATA = "/usr/share/games/flare/" + DEFAULT_FOLDER + "/"; if (!path_default_data && dirExists(PATH_DEFAULT_DATA)) path_default_data = true; // finally assume the local folder if (!path_data) PATH_DATA = "./"; if (!path_default_data) PATH_DEFAULT_DATA = "./"; } #endif static ConfigEntry * getConfigEntry(const char * name) { for (int i = 0; i < config_size; i++) { if (std::strcmp(config[i].name, name) == 0) return config + i; } return NULL; } static ConfigEntry * getConfigEntry(const std::string & name) { return getConfigEntry(name.c_str()); } void loadTilesetSettings() { FileParser infile; // load tileset settings from engine config if (infile.open("engine/tileset_config.txt", true, true, "Unable to open engine/tileset_config.txt! Defaulting to 64x32 isometric tiles.\n")) { while (infile.next()) { if (infile.key == "tile_size") { TILE_W = toInt(infile.nextValue()); TILE_H = toInt(infile.nextValue()); TILE_W_HALF = TILE_W /2; TILE_H_HALF = TILE_H /2; } else if (infile.key == "orientation") { if (infile.val == "isometric") TILESET_ORIENTATION = TILESET_ISOMETRIC; else if (infile.val == "orthogonal") TILESET_ORIENTATION = TILESET_ORTHOGONAL; } } infile.close(); } // Init automatically calculated parameters VIEW_W_HALF = VIEW_W / 2; VIEW_H_HALF = VIEW_H / 2; if (TILESET_ORIENTATION == TILESET_ISOMETRIC) { UNITS_PER_PIXEL_X = 2.0f / TILE_W; UNITS_PER_PIXEL_Y = 2.0f / TILE_H; } else { // TILESET_ORTHOGONAL UNITS_PER_PIXEL_X = 1.0f / TILE_W; UNITS_PER_PIXEL_Y = 1.0f / TILE_H; } if (UNITS_PER_PIXEL_X == 0 || UNITS_PER_PIXEL_Y == 0) { fprintf(stderr, "One of UNITS_PER_PIXEL values is zero! %dx%d\n", (int)UNITS_PER_PIXEL_X, (int)UNITS_PER_PIXEL_Y); SDL_Quit(); exit(1); } } void loadMiscSettings() { FileParser infile; // load miscellaneous settings from engine config // misc.txt if (infile.open("engine/misc.txt")) { while (infile.next()) { if (infile.key == "save_hpmp") SAVE_HPMP = toBool(infile.val); else if (infile.key == "corpse_timeout") CORPSE_TIMEOUT = toInt(infile.val); else if (infile.key == "sell_without_vendor") SELL_WITHOUT_VENDOR = toBool(infile.val); else if (infile.key == "aim_assist") AIM_ASSIST = toInt(infile.val); else if (infile.key == "window_title") WINDOW_TITLE = infile.val; else if (infile.key == "game_prefix") GAME_PREFIX = infile.val; else if (infile.key == "sound_falloff") SOUND_FALLOFF = toInt(infile.val); else if (infile.key == "party_exp_percentage") PARTY_EXP_PERCENTAGE = toInt(infile.val); else if (infile.key == "enable_ally_collision") ENABLE_ALLY_COLLISION = toBool(infile.val); else if (infile.key == "enable_ally_collision_ai") ENABLE_ALLY_COLLISION_AI = toBool(infile.val); else if (infile.key == "currency_id") { CURRENCY_ID = toInt(infile.val); if (CURRENCY_ID < 1) { CURRENCY_ID = 1; fprintf(stderr, "Currency ID below the minimum allowed value. Resetting it to %d\n", CURRENCY_ID); } } else if (infile.key == "interact_range") INTERACT_RANGE = toFloat(infile.val); else if (infile.key == "menus_pause") MENUS_PAUSE = toBool(infile.val); } infile.close(); } // resolutions.txt if (infile.open("engine/resolutions.txt")) { while (infile.next()) { if (infile.key == "menu_frame_width") FRAME_W = toInt(infile.val); else if (infile.key == "menu_frame_height") FRAME_H = toInt(infile.val); else if (infile.key == "icon_size") ICON_SIZE = toInt(infile.val); else if (infile.key == "required_width") { MIN_VIEW_W = toInt(infile.val); if (VIEW_W < MIN_VIEW_W) VIEW_W = MIN_VIEW_W; VIEW_W_HALF = VIEW_W/2; } else if (infile.key == "required_height") { MIN_VIEW_H = toInt(infile.val); if (VIEW_H < MIN_VIEW_H) VIEW_H = MIN_VIEW_H; VIEW_H_HALF = VIEW_H/2; } } infile.close(); } // gameplay.txt if (infile.open("engine/gameplay.txt")) { while (infile.next()) { if (infile.key == "enable_playgame") { ENABLE_PLAYGAME = toBool(infile.val); } } infile.close(); } // combat.txt if (infile.open("engine/combat.txt")) { while (infile.next()) { if (infile.key == "max_absorb_percent") MAX_ABSORB = toInt(infile.val); else if (infile.key == "max_resist_percent") MAX_RESIST = toInt(infile.val); else if (infile.key == "max_block_percent") MAX_BLOCK = toInt(infile.val); else if (infile.key == "max_avoidance_percent") MAX_AVOIDANCE = toInt(infile.val); else if (infile.key == "min_absorb_percent") MIN_ABSORB = toInt(infile.val); else if (infile.key == "min_resist_percent") MIN_RESIST = toInt(infile.val); else if (infile.key == "min_block_percent") MIN_BLOCK = toInt(infile.val); else if (infile.key == "min_avoidance_percent") MIN_AVOIDANCE = toInt(infile.val); } infile.close(); } // elements.txt if (infile.open("engine/elements.txt")) { Element e; ELEMENTS.clear(); while (infile.next()) { if (infile.key == "name") e.name = infile.val; else if (infile.key == "description") e.description = infile.val; if (e.name != "" && e.description != "") { ELEMENTS.push_back(e); e.name = e.description = ""; } } infile.close(); } // equip_flags.txt if (infile.open("engine/equip_flags.txt", true, false)) { string type,description; type = description = ""; while (infile.next()) { if (infile.key == "name") type = infile.val; else if (infile.key == "description") description = infile.val; if (type != "" && description != "") { EQUIP_FLAGS[type] = description; type = description = ""; } } infile.close(); } // classes.txt if (infile.open("engine/classes.txt")) { HeroClass c; HERO_CLASSES.clear(); while (infile.next()) { if (infile.key == "name") c.name = infile.val; if (c.name != "") { HERO_CLASSES.push_back(c); c.name = ""; } if (!HERO_CLASSES.empty()) { if (infile.key == "description") HERO_CLASSES.back().description = infile.val; else if (infile.key == "currency") HERO_CLASSES.back().currency = toInt(infile.val); else if (infile.key == "equipment") HERO_CLASSES.back().equipment = infile.val; else if (infile.key == "physical") HERO_CLASSES.back().physical = toInt(infile.val); else if (infile.key == "mental") HERO_CLASSES.back().mental = toInt(infile.val); else if (infile.key == "offense") HERO_CLASSES.back().offense = toInt(infile.val); else if (infile.key == "defense") HERO_CLASSES.back().defense = toInt(infile.val); else if (infile.key == "actionbar") { for (int i=0; i<12; i++) { HERO_CLASSES.back().hotkeys[i] = toInt(infile.nextValue()); } } else if (infile.key == "powers") { string power; while ( (power = infile.nextValue()) != "") { HERO_CLASSES.back().powers.push_back(toInt(power)); } } else if (infile.key == "campaign") { string status; while ( (status = infile.nextValue()) != "") { HERO_CLASSES.back().statuses.push_back(status); } } } } infile.close(); } // Make a default hero class if none were found if (HERO_CLASSES.empty()) { HeroClass c; c.name = msg->get("Adventurer"); HERO_CLASSES.push_back(c); } // death_penalty.txt if (infile.open("engine/death_penalty.txt")) { while (infile.next()) { if (infile.key == "enable") DEATH_PENALTY = toBool(infile.val); else if (infile.key == "permadeath") DEATH_PENALTY_PERMADEATH = toBool(infile.val); else if (infile.key == "currency") DEATH_PENALTY_CURRENCY = toInt(infile.val); else if (infile.key == "xp_total") DEATH_PENALTY_XP = toInt(infile.val); else if (infile.key == "xp_current_level") DEATH_PENALTY_XP_CURRENT = toInt(infile.val); else if (infile.key == "random_item") DEATH_PENALTY_ITEM = toBool(infile.val); } infile.close(); } } bool loadSettings() { // init defaults for (int i = 0; i < config_size; i++) { // TODO: handle errors ConfigEntry * entry = config + i; tryParseValue(*entry->type, entry->default_val, entry->storage); } // try read from file FileParser infile; if (!infile.open(PATH_CONF + FILE_SETTINGS, false, true, "")) { if (!infile.open("engine/default_settings.txt", true, true, "")) { saveSettings(); return true; } else saveSettings(); } while (infile.next()) { ConfigEntry * entry = getConfigEntry(infile.key); if (entry) { // TODO: handle errors tryParseValue(*entry->type, infile.val, entry->storage); } } infile.close(); return true; } /** * Save the current main settings (primary video and audio settings) */ bool saveSettings() { ofstream outfile; outfile.open((PATH_CONF + FILE_SETTINGS).c_str(), ios::out); if (outfile.is_open()) { for (int i = 0; i < config_size; i++) { // write additional newline before the next section if (i != 0 && config[i].comment != NULL) outfile<<"\n"; if (config[i].comment != NULL) { outfile<<"# "<<config[i].comment<<"\n"; } outfile<<config[i].name<<"="<<toString(*config[i].type, config[i].storage)<<"\n"; } if (outfile.bad()) fprintf(stderr, "Unable to write settings file. No write access or disk is full!\n"); outfile.close(); outfile.clear(); } return true; } /** * Load all default settings, except video settings. */ bool loadDefaults() { // HACK init defaults except video for (int i = 3; i < config_size; i++) { // TODO: handle errors ConfigEntry * entry = config + i; tryParseValue(*entry->type, entry->default_val, entry->storage); } // Init automatically calculated parameters VIEW_W_HALF = VIEW_W / 2; VIEW_H_HALF = VIEW_H / 2; return true; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/Settings.h��������������������������������������������������������������������0000664�0000000�0000000�00000011335�12247171015�0016542�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * Settings */ #pragma once #ifndef SETTINGS_H #define SETTINGS_H #include "CommonIncludes.h" class Element{ public: std::string name; std::string description; }; class HeroClass{ public: std::string name; std::string description; int currency; std::string equipment; int physical; int mental; int offense; int defense; int hotkeys[12]; std::vector<int> powers; std::vector<std::string> statuses; HeroClass() : name("") , description("") , currency(0) , equipment("") , physical(0) , mental(0) , offense(0) , defense(0) { for (int i=0; i<12; i++) { hotkeys[i] = 0; } powers.clear(); } }; // Path info extern std::string GAME_FOLDER; extern std::string DEFAULT_FOLDER; extern std::string PATH_CONF; // user-configurable settings files extern std::string PATH_USER; // important per-user data (saves) extern std::string PATH_DATA; // common game data extern std::string CUSTOM_PATH_DATA; // user-defined replacement for PATH_DATA extern std::string PATH_DEFAULT_USER; // similar to PATH_USER, except for the default game extern std::string PATH_DEFAULT_DATA; // similar to PATH_DATA, except for the default game // Filenames extern std::string FILE_SETTINGS; // Name of the settings file (e.g. "settings.txt"). extern std::string FILE_KEYBINDINGS; // Name of the key bindings file (e.g. "keybindings.txt"). // Main Menu frame size extern unsigned short FRAME_W; extern unsigned short FRAME_H; extern unsigned short ICON_SIZE; // Audio and Video Settings extern bool AUDIO; // initialize the audio subsystem at all? extern unsigned short MUSIC_VOLUME; extern unsigned short SOUND_VOLUME; extern bool FULLSCREEN; extern unsigned char BITS_PER_PIXEL; extern unsigned short MAX_FRAMES_PER_SEC; extern unsigned short VIEW_W; extern unsigned short VIEW_H; extern unsigned short VIEW_W_HALF; extern unsigned short VIEW_H_HALF; extern short MIN_VIEW_W; extern short MIN_VIEW_H; extern bool DOUBLEBUF; extern bool HWSURFACE; extern bool CHANGE_GAMMA; extern float GAMMA; extern bool TEXTURE_QUALITY; extern bool ANIMATED_TILES; // Input Settings extern bool MOUSE_MOVE; extern bool ENABLE_JOYSTICK; extern int JOYSTICK_DEVICE; extern bool MOUSE_AIM; extern bool NO_MOUSE; extern int JOY_DEADZONE; // User Options extern bool COMBAT_TEXT; // Engine Settings extern bool MENUS_PAUSE; extern bool SAVE_HPMP; extern bool ENABLE_PLAYGAME; extern bool SHOW_FPS; extern bool SHOW_HOTKEYS; extern bool COLORBLIND; extern int CORPSE_TIMEOUT; extern bool SELL_WITHOUT_VENDOR; extern int AIM_ASSIST; extern std::string WINDOW_TITLE; extern std::string GAME_PREFIX; extern int SOUND_FALLOFF; extern int PARTY_EXP_PERCENTAGE; extern bool ENABLE_ALLY_COLLISION_AI; extern bool ENABLE_ALLY_COLLISION; extern int CURRENCY_ID; extern float INTERACT_RANGE; // Tile Settings extern float UNITS_PER_PIXEL_X; extern float UNITS_PER_PIXEL_Y; extern unsigned short TILE_W; extern unsigned short TILE_H; extern unsigned short TILE_W_HALF; extern unsigned short TILE_H_HALF; extern unsigned short TILESET_ORIENTATION; extern unsigned short TILESET_ISOMETRIC; extern unsigned short TILESET_ORTHOGONAL; // Language Settings extern std::string LANGUAGE; // Autopickup Settings extern bool AUTOPICKUP_CURRENCY; // Combat calculation caps extern short MAX_ABSORB; extern short MAX_RESIST; extern short MAX_BLOCK; extern short MAX_AVOIDANCE; extern short MIN_ABSORB; extern short MIN_RESIST; extern short MIN_BLOCK; extern short MIN_AVOIDANCE; // Elemental types extern std::vector<Element> ELEMENTS; // Equip flags extern std::map<std::string,std::string> EQUIP_FLAGS; // Hero classes extern std::vector<HeroClass> HERO_CLASSES; // Currency settings extern std::string CURRENCY; extern float VENDOR_RATIO; // Death penalty settings extern bool DEATH_PENALTY; extern bool DEATH_PENALTY_PERMADEATH; extern int DEATH_PENALTY_CURRENCY; extern int DEATH_PENALTY_XP; extern int DEATH_PENALTY_XP_CURRENT; extern bool DEATH_PENALTY_ITEM; void setPaths(); void loadTilesetSettings(); void loadMiscSettings(); bool loadSettings(); bool saveSettings(); bool loadDefaults(); #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/SharedGameResources.cpp�������������������������������������������������������0000664�0000000�0000000�00000001661�12247171015�0021171�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2013 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "SharedGameResources.h" MenuPowers *menu_powers = NULL; LootManager *loot = NULL; EnemyGroupManager *enemyg = NULL; PowerManager *powers = NULL; MapRenderer *mapr = NULL; EnemyManager *enemies = NULL; CampaignManager *camp = NULL; ItemManager *items = NULL; Avatar *pc = NULL; �������������������������������������������������������������������������������flare-engine-0.19/src/SharedGameResources.h���������������������������������������������������������0000664�0000000�0000000�00000002526�12247171015�0020637�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2013 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #ifndef SHAREDGAMEOBJECTS_H #define SHAREDGAMEOBJECTS_H #include "LootManager.h" #include "MenuPowers.h" #include "EnemyGroupManager.h" #include "PowerManager.h" #include "CampaignManager.h" #include "Avatar.h" extern MenuPowers *menu_powers; /* These objects are created in the GameStatePlay constructor and deleted in the GameStatePlay destructor * so can be accessed safely anywhere in between. The objects must not be changed by any other class. */ extern LootManager *loot; extern EnemyGroupManager *enemyg; extern PowerManager *powers; extern MapRenderer *mapr; extern EnemyManager *enemies; extern CampaignManager *camp; extern ItemManager *items; extern Avatar *pc; #endif // SHAREDGAMEOBJECTS_H ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/SharedResources.cpp�����������������������������������������������������������0000664�0000000�0000000�00000002232�12247171015�0020372�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** SharedResources "Global" sort of system resources that are used by most game classes. Only one instance of these classes are needed by the engine. Generic objects only. Game-specific objects don't belong here. Created and destroyed by main.cpp **/ #include "SharedResources.h" AnimationManager *anim; ImageManager *imag; SDL_Surface *screen; ModManager *mods; MessageEngine *msg; InputState *inpt; FontEngine *font; CombatText *comb; SoundManager *snd; SDL_Joystick *joy; ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/SharedResources.h�������������������������������������������������������������0000664�0000000�0000000�00000002771�12247171015�0020047�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** SharedResources "Global" sort of system resources that are used by most game classes. Only one instance of these classes are needed by the engine. Generic objects only. Game-specific objects don't belong here. Created and destroyed by main.cpp **/ #pragma once #ifndef SHARED_RESOURCES_H #define SHARED_RESOURCES_H #include "CommonIncludes.h" #include "AnimationManager.h" #include "CombatText.h" #include "FontEngine.h" #include "ImageManager.h" #include "InputState.h" #include "MessageEngine.h" #include "ModManager.h" #include "SoundManager.h" extern SDL_Surface *screen; extern SDL_Joystick *joy; extern AnimationManager *anim; extern CombatText *comb; extern FontEngine *font; extern ImageManager *imag; extern InputState *inpt; extern MessageEngine *msg; extern ModManager *mods; extern SoundManager *snd; #endif �������flare-engine-0.19/src/SoundManager.cpp��������������������������������������������������������������0000664�0000000�0000000�00000013620�12247171015�0017657�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** SoundManager SoundManager take care of loading and playing of sound effects, each sound is references with a hash SoundID for playing. If a sound is already loaded the SoundID for currently loaded sound will be returned by SoundManager::load(). **/ #include "CommonIncludes.h" #include "Settings.h" #include "SharedResources.h" #include "SoundManager.h" #include "UtilsMath.h" #include <locale> #include <math.h> using namespace std; class Sound { public: Mix_Chunk *chunk; Sound() : chunk(0), refCnt(0) {} private: friend class SoundManager; int refCnt; }; class Playback { public: SoundManager::SoundID sid; std::string virtual_channel; FPoint location; bool loop; bool finished; }; SoundManager::SoundManager() { Mix_AllocateChannels(50); } SoundManager::~SoundManager() { SoundManager::SoundMapIterator it; while((it = sounds.begin()) != sounds.end()) unload(it->first); } void SoundManager::logic(FPoint c) { PlaybackMapIterator it = playback.begin(); if (it == playback.end()) return; lastPos = c; std::vector<int> cleanup; while(it != playback.end()) { /* if sound is finished add it to cleanup and continue with next */ if (it->second.finished) { cleanup.push_back(it->first); ++it; continue; } /* dont process playback sounds without location */ if (it->second.location.x == 0 && it->second.location.y == 0) { ++it; continue; } /* control mixing playback depending on distance */ float v = calcDist(c, it->second.location) / (SOUND_FALLOFF); if (it->second.loop) { if (v < 1.0) Mix_Resume(it->first); else Mix_Pause(it->first); } /* update sound mix with new distance/location to hero */ clamp(v, 0.0, 1.0); Uint8 dist = 255.0 * v; Mix_SetPosition(it->first, 0, dist); ++it; } /* clenaup finished soundplayback */ while (!cleanup.empty()) { it = playback.find(cleanup.back()); unload(it->second.sid); /* find and erase virtual channel for playback if exists */ VirtualChannelMapIterator vcit = channels.find(it->second.virtual_channel); if (vcit != channels.end()) channels.erase(vcit); playback.erase(it); cleanup.pop_back(); } } void SoundManager::reset() { PlaybackMapIterator it = playback.begin(); if (it == playback.end()) return; while(it != playback.end()) { if (it->second.loop) Mix_HaltChannel(it->first); ++it; } logic(Point(0,0)); } SoundManager::SoundID SoundManager::load(const std::string& filename, const std::string& errormessage) { Sound lsnd; SoundID sid = 0; SoundMapIterator it; std::locale loc; if (!AUDIO || !SOUND_VOLUME) return 0; const collate<char>& coll = use_facet<collate<char> >(loc); const string realfilename = mods->locate(filename); /* create sid hash and check if already loaded */ sid = coll.hash(realfilename.data(), realfilename.data()+realfilename.length()); it = sounds.find(sid); if (it != sounds.end()) { it->second->refCnt++; return sid; } /* load non existing sound */ lsnd.chunk = Mix_LoadWAV(realfilename.c_str()); lsnd.refCnt = 1; if (!lsnd.chunk) { fprintf(stderr, "%s: Loading sound %s (%s) failed: %s \n", errormessage.c_str(), realfilename.c_str(), filename.c_str(), Mix_GetError()); return 0; } /* instantiate and add sound to manager */ Sound *psnd = new Sound; *psnd = lsnd; sounds.insert(pair<SoundID,Sound *>(sid, psnd)); return sid; } void SoundManager::unload(SoundManager::SoundID sid) { SoundMapIterator it; it = sounds.find(sid); if (it == sounds.end()) return; if (--it->second->refCnt == 0) { Mix_FreeChunk(it->second->chunk); delete it->second; sounds.erase(it); } } void SoundManager::play(SoundManager::SoundID sid, std::string channel, FPoint pos, bool loop) { SoundMapIterator it; VirtualChannelMapIterator vcit = channels.end(); if (!sid || !AUDIO || !SOUND_VOLUME) return; it = sounds.find(sid); if (it == sounds.end()) return; /* create playback object and start playback of sound chunk */ Playback p; p.sid = sid; p.location = pos; p.virtual_channel = channel; p.loop = loop; p.finished = false; if (p.virtual_channel != GLOBAL_VIRTUAL_CHANNEL) { /* if playback exists, stop it befor playin next sound */ vcit = channels.find(p.virtual_channel); if (vcit != channels.end()) Mix_HaltChannel(vcit->second); vcit = channels.insert(pair<std::string, int>(p.virtual_channel, -1)).first; } // Let playback own a reference to prevent unloading playbacked sound. if (!loop) it->second->refCnt++; Mix_ChannelFinished(&channel_finished); int c = Mix_PlayChannel(-1, it->second->chunk, (loop ? -1 : 0)); if (c == -1) fprintf(stderr,"Failed to play sound, no more channels available.\n"); // precalculate mixing volume if sound has a location Uint8 d = 0; if (p.location.x != 0 || p.location.y != 0) { float v = 255.0f * (calcDist(lastPos, p.location) / (SOUND_FALLOFF)); clamp(v, 0.f, 255.f); d = v; } Mix_SetPosition(c, 0, d); if (vcit != channels.end()) vcit->second = c; playback.insert(pair<int, Playback>(c, p)); } void SoundManager::on_channel_finished(int channel) { PlaybackMapIterator pit = playback.find(channel); if (pit == playback.end()) return; pit->second.finished = true; Mix_SetPosition(channel, 0, 0); } void SoundManager::channel_finished(int channel) { snd->on_channel_finished(channel); } ����������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/SoundManager.h����������������������������������������������������������������0000664�0000000�0000000�00000003401�12247171015�0017320�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class SoundManager */ #pragma once #ifndef SOUND_MANAGER_H #define SOUND_MANAGER_H #include "CommonIncludes.h" #include "Utils.h" #include <stdint.h> const std::string GLOBAL_VIRTUAL_CHANNEL = "__global__"; class SoundManager { public: typedef unsigned long SoundID; SoundManager(); ~SoundManager(); SoundManager::SoundID load(const std::string& filename, const std::string& errormessage); void unload(SoundManager::SoundID); void play(SoundManager::SoundID, std::string channel = GLOBAL_VIRTUAL_CHANNEL, FPoint pos = FPoint(0,0), bool loop = false); void logic(FPoint center); void reset(); private: typedef std::map<std::string, int> VirtualChannelMap; typedef VirtualChannelMap::iterator VirtualChannelMapIterator; typedef std::map<SoundID, class Sound *> SoundMap; typedef SoundMap::iterator SoundMapIterator; typedef std::map<int, class Playback> PlaybackMap; typedef PlaybackMap::iterator PlaybackMapIterator; static void channel_finished(int channel); void on_channel_finished(int channel); SoundMap sounds; VirtualChannelMap channels; PlaybackMap playback; FPoint lastPos; }; #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/StatBlock.cpp�����������������������������������������������������������������0000664�0000000�0000000�00000050003�12247171015�0017156�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class StatBlock * * Character stats and calculations */ #include "StatBlock.h" #include "FileParser.h" #include "SharedGameResources.h" #include "SharedResources.h" #include "Settings.h" #include "UtilsParsing.h" #include "MapCollision.h" #include "MenuPowers.h" #include "UtilsMath.h" #include <limits> using namespace std; StatBlock::StatBlock() : statsLoaded(false) , alive(true) , corpse(false) , corpse_ticks(0) , hero(false) , hero_ally(false) , humanoid(false) , permadeath(false) , transformed(false) , refresh_stats(false) , converted(false) , summoned(false) , summoned_power_index(0) , movement_type(MOVEMENT_NORMAL) , flying(false) , intangible(false) , facing(true) , name("") , sfx_prefix("") , level(0) , xp(0) , level_up(false) , check_title(false) , stat_points_per_level(1) , power_points_per_level(1) , offense_character(0) , defense_character(0) , physical_character(0) , mental_character(0) , starting() , base() , current() , per_level() , per_physical() , per_mental() , per_offense() , per_defense() , offense_additional(0) , defense_additional(0) , physical_additional(0) , mental_additional(0) , character_class("") , hp(0) , hp_ticker(0) , mp(0) , mp_ticker(0) , dmg_melee_min_default(1) , dmg_melee_max_default(4) , dmg_ment_min_default(1) , dmg_ment_max_default(4) , dmg_ranged_min_default(1) , dmg_ranged_max_default(4) , absorb_min_default(0) , absorb_max_default(0) , speed_default(0.2) , dmg_melee_min_add(0) , dmg_melee_max_add(0) , dmg_ment_min_add(0) , dmg_ment_max_add(0) , dmg_ranged_min_add(0) , dmg_ranged_max_add(0) , absorb_min_add(0) , absorb_max_add(0) , speed(0.2) , vulnerable(ELEMENTS.size(), 100) , vulnerable_base(ELEMENTS.size(), 100) , transform_duration(0) , transform_duration_total(0) , manual_untransform(false) , transform_with_equipment(false) , effects() , pos() , forced_speed() , direction(0) , cooldown_hit(0) , cooldown_hit_ticks(0) , cur_state(0) , waypoints() // enemy only , waypoint_pause(0) // enemy only , waypoint_pause_ticks(0) // enemy only , wander(false) // enemy only , wander_area() // enemy only , wander_ticks(0) // enemy only , wander_pause_ticks(0) // enemy only , chance_pursue(0) , chance_flee(0) // enemy only , powers_list() // hero only , powers_list_items() // hero only , powers_passive() , power_chance(POWERSLOT_COUNT, 0) // enemy only , power_index(POWERSLOT_COUNT, 0) // both , power_cooldown(POWERSLOT_COUNT, 0) // enemy only , power_ticks(POWERSLOT_COUNT, 0) // enemy only , melee_range(1.0) //both , threat_range(0) // enemy , passive_attacker(false)//enemy , hero_stealth(0) , turn_delay(0) , turn_ticks(0) , in_combat(false) //enemy only , join_combat(false) , cooldown_ticks(0) , cooldown(0) , activated_powerslot(0)// enemy only , on_half_dead_casted(false) // enemy only , suppress_hp(false) , teleportation(false) , teleport_destination() , melee_weapon_power(0) , mental_weapon_power(0) , ranged_weapon_power(0) , currency(0) , death_penalty(false) , defeat_status("") // enemy only , convert_status("") // enemy only , quest_loot_requires_status("") // enemy only , quest_loot_requires_not_status("") // enemy only , quest_loot_id(0) // enemy only , first_defeat_loot(0) // enemy only , gfx_base("male") , gfx_head("head_short") , gfx_portrait("male01") , transform_type("") , animations("") , sfx_step("cloth") , prev_maxhp(0) , prev_maxmp(0) , pres_hp(0) , pres_mp(0) , summons() , summoner(NULL) { max_spendable_stat_points = 0; max_points_per_stat = 0; activated_powerslot = 0; on_half_dead_casted = false; } bool sortLoot(const EnemyLoot &a, const EnemyLoot &b) { return a.chance < b.chance; } bool StatBlock::loadCoreStat(FileParser *infile) { int value = toInt(infile->val, 0); float fvalue = toFloat(infile->val, 0); if (infile->key == "speed") { speed = speed_default = fvalue / MAX_FRAMES_PER_SEC; return true; } else if (infile->key == "categories") { string cat; while ((cat = infile->nextValue()) != "") { categories.push_back(cat); } return true; } else { for (unsigned i=0; i<STAT_COUNT; i++) { if (infile->key == STAT_NAME[i]) { starting[i] = value; return true; } else if (infile->key == STAT_NAME[i] + "_per_level") { per_level[i] = value; return true; } else if (infile->key == STAT_NAME[i] + "_per_physical") { per_physical[i] = value; return true; } else if (infile->key == STAT_NAME[i] + "_per_mental") { per_mental[i] = value; return true; } else if (infile->key == STAT_NAME[i] + "_per_offense") { per_offense[i] = value; return true; } else if (infile->key == STAT_NAME[i] + "_per_defense") { per_defense[i] = value; return true; } } for (unsigned int i=0; i<ELEMENTS.size(); i++) { if (infile->key == "vulnerable_" + ELEMENTS[i].name) { vulnerable[i] = vulnerable_base[i] = value; return true; } } } return false; } /** * load a statblock, typically for an enemy definition */ void StatBlock::load(const string& filename) { FileParser infile; if (!infile.open(filename)) return; string loot_token; while (infile.next()) { int num = toInt(infile.val); float fnum = toFloat(infile.val); bool valid = loadCoreStat(&infile); if (infile.key == "name") name = msg->get(infile.val); else if (infile.key == "humanoid") humanoid = toBool(infile.val); else if (infile.key == "sfx_prefix") sfx_prefix = infile.val; else if (infile.key == "level") level = num; // enemy death rewards and events else if (infile.key == "xp") xp = num; else if (infile.key == "loot") { // loot entries format: // loot=[id],[percent_chance] // optionally allow range: // loot=[id],[percent_chance],[count_min],[count_max] EnemyLoot el; std::string loot_id = infile.nextValue(); // id 0 means currency. The keyword "currency" can also be used. if (loot_id == "currency") el.id = 0; else el.id = toInt(loot_id); el.chance = toInt(infile.nextValue()); // check for optional range. loot_token = infile.nextValue(); if (loot_token != "") { el.count_min = toInt(loot_token); el.count_max = el.count_min; } loot_token = infile.nextValue(); if (loot_token != "") { el.count_max = toInt(loot_token); } loot.push_back(el); } else if (infile.key == "defeat_status") defeat_status = infile.val; else if (infile.key == "convert_status") convert_status = infile.val; else if (infile.key == "first_defeat_loot") first_defeat_loot = num; else if (infile.key == "quest_loot") { quest_loot_requires_status = infile.nextValue(); quest_loot_requires_not_status = infile.nextValue(); quest_loot_id = toInt(infile.nextValue()); } // combat stats else if (infile.key == "cooldown") cooldown = parse_duration(infile.val); // behavior stats else if (infile.key == "flying") flying = toBool(infile.val); else if (infile.key == "intangible") intangible = toBool(infile.val); else if (infile.key == "facing") facing = toBool(infile.val); else if (infile.key == "waypoint_pause") waypoint_pause = num; else if (infile.key == "turn_delay") turn_delay = num; else if (infile.key == "chance_pursue") chance_pursue = num; else if (infile.key == "chance_flee") chance_flee = num; else if (infile.key == "chance_melee_phys") power_chance[MELEE_PHYS] = num; else if (infile.key == "chance_melee_ment") power_chance[MELEE_MENT] = num; else if (infile.key == "chance_ranged_phys") power_chance[RANGED_PHYS] = num; else if (infile.key == "chance_ranged_ment") power_chance[RANGED_MENT] = num; else if (infile.key == "power_melee_phys") power_index[MELEE_PHYS] = num; else if (infile.key == "power_melee_ment") power_index[MELEE_MENT] = num; else if (infile.key == "power_ranged_phys") power_index[RANGED_PHYS] = num; else if (infile.key == "power_ranged_ment") power_index[RANGED_MENT] = num; else if (infile.key == "power_beacon") power_index[BEACON] = num; else if (infile.key == "cooldown_melee_phys") power_cooldown[MELEE_PHYS] = parse_duration(infile.val); else if (infile.key == "cooldown_melee_ment") power_cooldown[MELEE_MENT] = parse_duration(infile.val); else if (infile.key == "cooldown_ranged_phys") power_cooldown[RANGED_PHYS] = parse_duration(infile.val); else if (infile.key == "cooldown_ranged_ment") power_cooldown[RANGED_MENT] = parse_duration(infile.val); else if (infile.key == "power_on_hit") power_index[ON_HIT] = num; else if (infile.key == "power_on_death") power_index[ON_DEATH] = num; else if (infile.key == "power_on_half_dead") power_index[ON_HALF_DEAD] = num; else if (infile.key == "power_on_debuff") power_index[ON_DEBUFF] = num; else if (infile.key == "power_on_join_combat") power_index[ON_JOIN_COMBAT] = num; else if (infile.key == "chance_on_hit") power_chance[ON_HIT] = num; else if (infile.key == "chance_on_death") power_chance[ON_DEATH] = num; else if (infile.key == "chance_on_half_dead") power_chance[ON_HALF_DEAD] = num; else if (infile.key == "chance_on_debuff") power_chance[ON_DEBUFF] = num; else if (infile.key == "chance_on_join_combat") power_chance[ON_JOIN_COMBAT] = num; else if (infile.key == "cooldown_hit") cooldown_hit = num; else if (infile.key == "passive_powers") { std::string p = infile.nextValue(); while (p != "") { powers_passive.push_back(toInt(p)); p = infile.nextValue(); } } else if (infile.key == "melee_range") melee_range = fnum; else if (infile.key == "threat_range") threat_range = fnum; else if (infile.key == "passive_attacker") passive_attacker = toBool(infile.val); // animation stats else if (infile.key == "melee_weapon_power") melee_weapon_power = num; else if (infile.key == "mental_weapon_power") mental_weapon_power = num; else if (infile.key == "ranged_weapon_power") ranged_weapon_power = num; else if (infile.key == "animations") animations = infile.val; // hide enemy HP bar else if (infile.key == "suppress_hp") suppress_hp = toBool(infile.val); // this is only used for EnemyGroupManager // we check for them here so that we don't get an error saying they are invalid else if (infile.key == "rarity") ; // but do nothing else if (!valid) { fprintf(stderr, "%s=%s not a valid StatBlock parameter\n", infile.key.c_str(), infile.val.c_str()); } } infile.close(); hp = starting[STAT_HP_MAX]; mp = starting[STAT_MP_MAX]; // sort loot table std::sort(loot.begin(), loot.end(), sortLoot); applyEffects(); } /** * Reduce temphp first, then hp */ void StatBlock::takeDamage(int dmg) { hp -= effects.damageShields(dmg); if (hp <= 0) { hp = 0; } } /** * Recalc level and stats * Refill HP/MP * Creatures might skip these formulas. */ void StatBlock::recalc() { if (!statsLoaded) loadHeroStats(); refresh_stats = true; level = 0; for (unsigned i=0; i<xp_table.size(); i++) { if (xp >= xp_table[i]) { level=i+1; check_title = true; } } applyEffects(); hp = get(STAT_HP_MAX); mp = get(STAT_MP_MAX); } /** * Base damage and absorb is 0 * Plus an optional bonus_per_[base stat] */ void StatBlock::calcBase() { // bonuses are skipped for the default level 1 of a stat int lev0 = level -1; int phys0 = get_physical() -1; int ment0 = get_mental() -1; int off0 = get_offense() -1; int def0 = get_defense() -1; clampFloor(lev0,0); clampFloor(phys0,0); clampFloor(ment0,0); clampFloor(off0,0); clampFloor(def0,0); for (int i=0; i<STAT_COUNT; i++) { base[i] = starting[i]; base[i] += lev0 * per_level[i]; base[i] += phys0 * per_physical[i]; base[i] += ment0 * per_mental[i]; base[i] += off0 * per_offense[i]; base[i] += def0 * per_defense[i]; } // add damage/absorb from equipment base[STAT_DMG_MELEE_MIN] += dmg_melee_min_add; base[STAT_DMG_MELEE_MAX] += dmg_melee_max_add; base[STAT_DMG_MENT_MIN] += dmg_ment_min_add; base[STAT_DMG_MENT_MAX] += dmg_ment_max_add; base[STAT_DMG_RANGED_MIN] += dmg_ranged_min_add; base[STAT_DMG_RANGED_MAX] += dmg_ranged_max_add; base[STAT_ABS_MIN] += absorb_min_add; base[STAT_ABS_MAX] += absorb_max_add; // increase damage and absorb to minimum amounts clampFloor(base[STAT_DMG_MELEE_MIN], dmg_melee_min_default); clampFloor(base[STAT_DMG_MELEE_MAX], dmg_melee_max_default); clampFloor(base[STAT_DMG_RANGED_MIN], dmg_ranged_min_default); clampFloor(base[STAT_DMG_RANGED_MAX], dmg_ranged_max_default); clampFloor(base[STAT_DMG_MENT_MIN], dmg_ment_min_default); clampFloor(base[STAT_DMG_MENT_MAX], dmg_ment_max_default); clampFloor(base[STAT_ABS_MIN], absorb_min_default); clampFloor(base[STAT_ABS_MAX], absorb_max_default); } /** * Recalc derived stats from base stats + effect bonuses */ void StatBlock::applyEffects() { // preserve hp/mp states prev_maxhp = get(STAT_HP_MAX); prev_maxmp = get(STAT_MP_MAX); pres_hp = hp; pres_mp = mp; // calculate primary stats // refresh the character menu if there has been a change if (get_physical() != physical_character + effects.bonus_physical || get_mental() != mental_character + effects.bonus_mental || get_offense() != offense_character + effects.bonus_offense || get_defense() != defense_character + effects.bonus_defense) refresh_stats = true; offense_additional = effects.bonus_offense; defense_additional = effects.bonus_defense; physical_additional = effects.bonus_physical; mental_additional = effects.bonus_mental; calcBase(); for (int i=0; i<STAT_COUNT; i++) { current[i] = base[i] + effects.bonus[i]; } for (unsigned i=0; i<effects.bonus_resist.size(); i++) { vulnerable[i] = vulnerable_base[i] - effects.bonus_resist[i]; } current[STAT_HP_MAX] += (current[STAT_HP_MAX] * current[STAT_HP_PERCENT]) / 100; current[STAT_MP_MAX] += (current[STAT_MP_MAX] * current[STAT_MP_PERCENT]) / 100; if (hp > get(STAT_HP_MAX)) hp = get(STAT_HP_MAX); if (mp > get(STAT_MP_MAX)) mp = get(STAT_MP_MAX); speed = speed_default; } /** * Process per-frame actions */ void StatBlock::logic() { if (hp <= 0 && !effects.triggered_death && !effects.revive) alive = false; else alive = true; // handle effect timers effects.logic(); // apply bonuses from items/effects to base stats applyEffects(); // preserve ratio on maxmp and maxhp changes float ratio; if (prev_maxhp != get(STAT_HP_MAX)) { ratio = (float)pres_hp / (float)prev_maxhp; hp = (int)(ratio * get(STAT_HP_MAX)); } if (prev_maxmp != get(STAT_MP_MAX)) { ratio = (float)pres_mp / (float)prev_maxmp; mp = (int)(ratio * get(STAT_MP_MAX)); } // handle cooldowns if (cooldown_ticks > 0) cooldown_ticks--; // global cooldown for (int i=0; i<POWERSLOT_COUNT; i++) { // NPC/enemy powerslot cooldown if (power_ticks[i] > 0) power_ticks[i]--; } // HP regen if (get(STAT_HP_REGEN) > 0 && hp < get(STAT_HP_MAX) && hp > 0) { hp_ticker++; if (hp_ticker >= (60 * MAX_FRAMES_PER_SEC)/get(STAT_HP_REGEN)) { hp++; hp_ticker = 0; } } // MP regen if (get(STAT_MP_REGEN) > 0 && mp < get(STAT_MP_MAX) && hp > 0) { mp_ticker++; if (mp_ticker >= (60 * MAX_FRAMES_PER_SEC)/get(STAT_MP_REGEN)) { mp++; mp_ticker = 0; } } // handle buff/debuff durations if (transform_duration > 0) transform_duration--; // apply bleed if (effects.damage > 0) { takeDamage(effects.damage); } if(effects.death_sentence) hp = 0; if(cooldown_hit_ticks > 0) cooldown_hit_ticks--; // apply healing over time if (effects.hpot > 0) { comb->addMessage(msg->get("+%d HP",effects.hpot), pos, COMBAT_MESSAGE_BUFF); hp += effects.hpot; if (hp > get(STAT_HP_MAX)) hp = get(STAT_HP_MAX); } if (effects.mpot > 0) { comb->addMessage(msg->get("+%d MP",effects.mpot), pos, COMBAT_MESSAGE_BUFF); mp += effects.mpot; if (mp > get(STAT_MP_MAX)) mp = get(STAT_MP_MAX); } // set movement type // some creatures may shift between movement types if (intangible) movement_type = MOVEMENT_INTANGIBLE; else if (flying) movement_type = MOVEMENT_FLYING; else movement_type = MOVEMENT_NORMAL; } StatBlock::~StatBlock() { removeFromSummons(); } bool StatBlock::canUsePower(const Power &power, unsigned powerid) const { // needed to unlock shapeshifter powers if (transformed) return mp >= power.requires_mp; //don't use untransform power if hero is not transformed else if (power.spawn_type == "untransform" && !transformed) return false; else { return std::includes(equip_flags.begin(), equip_flags.end(), power.requires_flags.begin(), power.requires_flags.end()) && mp >= power.requires_mp && (!power.sacrifice == false || hp > power.requires_hp) && menu_powers->meetsUsageStats(powerid) && !power.passive && (power.type == POWTYPE_SPAWN ? !summonLimitReached(powerid) : true); } } void StatBlock::loadHeroStats() { // Redefine numbers from config file if present FileParser infile; if (!infile.open("engine/stats.txt")) return; while (infile.next()) { int value = toInt(infile.val); loadCoreStat(&infile); if (infile.key == "max_points_per_stat") { max_points_per_stat = value; } else if (infile.key == "sfx_step") { sfx_step = infile.val; } else if (infile.key == "stat_points_per_level") { stat_points_per_level = value; } else if (infile.key == "power_points_per_level") { power_points_per_level = value; } else if (infile.key == "cooldown_hit") { cooldown_hit = value; } } infile.close(); if (max_points_per_stat == 0) max_points_per_stat = max_spendable_stat_points / 4 + 1; statsLoaded = true; if (!infile.open("engine/xp_table.txt")) return; while(infile.next()) { unsigned key = toInt(infile.key); if (key > 0) { if (key > xp_table.size()) xp_table.resize(key); xp_table[key - 1] = toInt(infile.val); } } max_spendable_stat_points = toInt(infile.key) * stat_points_per_level; infile.close(); } void StatBlock::removeFromSummons() { if(summoner != NULL) { vector<StatBlock*>::iterator parent_ref = find(summoner->summons.begin(), summoner->summons.end(), this); if(parent_ref != summoner->summons.end()) summoner->summons.erase(parent_ref); summoner = NULL; } for (vector<StatBlock*>::iterator it=summons.begin(); it != summons.end(); ++it) (*it)->summoner = NULL; summons.clear(); } bool StatBlock::summonLimitReached(int power_id) const { //find the limit Power *spawn_power = &powers->powers[power_id]; int max_summons = 0; if(spawn_power->spawn_limit_mode == SPAWN_LIMIT_MODE_FIXED) max_summons = spawn_power->spawn_limit_qty; else if(spawn_power->spawn_limit_mode == SPAWN_LIMIT_MODE_STAT) { int stat_val = 1; switch(spawn_power->spawn_limit_stat) { case SPAWN_LIMIT_STAT_PHYSICAL: stat_val = get_physical(); break; case SPAWN_LIMIT_STAT_MENTAL: stat_val = get_mental(); break; case SPAWN_LIMIT_STAT_OFFENSE: stat_val = get_offense(); break; case SPAWN_LIMIT_STAT_DEFENSE: stat_val = get_defense(); break; } max_summons = (stat_val / (spawn_power->spawn_limit_every == 0 ? 1 : spawn_power->spawn_limit_every)) * spawn_power->spawn_limit_qty; } else return false;//unlimited or unknown mode //if the power is available, there should be at least 1 allowed summon if(max_summons < 1) max_summons = 1; //find out how many there are currently int qty_summons = 0; for (unsigned int i=0; i < summons.size(); i++) { if(!summons[i]->corpse && summons[i]->summoned_power_index == power_id && summons[i]->cur_state != ENEMY_SPAWN && summons[i]->cur_state != ENEMY_DEAD && summons[i]->cur_state != ENEMY_CRITDEAD) { qty_summons++; } } return qty_summons >= max_summons; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/StatBlock.h�������������������������������������������������������������������0000664�0000000�0000000�00000017220�12247171015�0016627�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Igor Paliychuk This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class StatBlock * * Character stats and calculations */ #pragma once #ifndef STAT_BLOCK_H #define STAT_BLOCK_H #include "CommonIncludes.h" #include "EffectManager.h" #include "MapCollision.h" #include "Stats.h" #include "Utils.h" #include <queue> class Power; class FileParser; const int POWERSLOT_COUNT = 10; const int MELEE_PHYS = 0; const int MELEE_MENT = 1; const int RANGED_PHYS = 2; const int RANGED_MENT = 3; const int BEACON = 4; const int ON_HIT = 5; const int ON_DEATH = 6; const int ON_HALF_DEAD = 7; const int ON_DEBUFF = 8; const int ON_JOIN_COMBAT = 9; // active states const int ENEMY_STANCE = 0; const int ENEMY_MOVE = 1; const int ENEMY_CHARGE = 2; const int ENEMY_MELEE_PHYS = 3; const int ENEMY_MELEE_MENT = 4; const int ENEMY_RANGED_PHYS = 5; const int ENEMY_RANGED_MENT = 6; const int ENEMY_SPAWN = 7; // interrupt states const int ENEMY_BLOCK = 9; const int ENEMY_HIT = 10; const int ENEMY_DEAD = 11; const int ENEMY_CRITDEAD = 12; const int ENEMY_HALF_DEAD = 13; const int ENEMY_JOIN_COMBAT = 14; // final shared states const int ENEMY_POWER = 15; // enemy performing a power. anim/sfx based on power class EnemyLoot { public: int id; int chance; int count_min; int count_max; EnemyLoot() : id(0) , chance(0) , count_min(1) , count_max(1) {} }; class StatBlock { private: bool loadCoreStat(FileParser *infile); void loadHeroStats(); bool statsLoaded; public: StatBlock(); ~StatBlock(); void load(const std::string& filename); void takeDamage(int dmg); void recalc(); void applyEffects(); void calcBase(); void logic(); bool alive; bool corpse; // creature is dead and done animating int corpse_ticks; bool hero; // else, enemy or other bool hero_ally; bool humanoid; // true for human, sceleton...; false for wyvern, snake... bool permadeath; bool transformed; bool refresh_stats; bool converted; bool summoned; int summoned_power_index; MOVEMENTTYPE movement_type; bool flying; bool intangible; bool facing; // does this creature turn to face the hero std::vector<std::string> categories; std::string name; std::string sfx_prefix; int level; unsigned long xp; std::vector<unsigned long> xp_table; bool level_up; bool check_title; int stat_points_per_level; int power_points_per_level; // base stats ("attributes") int offense_character; int defense_character; int physical_character; int mental_character; // combat stats int starting[STAT_COUNT]; // default level 1 values per stat. Read from file and never changes at runtime. int base[STAT_COUNT]; // values before any active effects are applied int current[STAT_COUNT]; // values after all active effects are applied int per_level[STAT_COUNT]; // value increases each level after level 1 int per_physical[STAT_COUNT]; int per_mental[STAT_COUNT]; int per_offense[STAT_COUNT]; int per_defense[STAT_COUNT]; int get(STAT stat) {return current[stat];} // additional values to base stats, given by items int offense_additional; int defense_additional; int physical_additional; int mental_additional; // getters for full base stats (character + additional) int get_offense() const { return offense_character + offense_additional; } int get_defense() const { return defense_character + defense_additional; } int get_physical() const { return physical_character + physical_additional; } int get_mental() const { return mental_character + mental_additional; } // derived stats ("disciplines") int physoff() { return get_physical() + get_offense(); } int physdef() { return get_physical() + get_defense(); } int mentoff() { return get_mental() + get_offense(); } int mentdef() { return get_mental() + get_defense(); } int physment() { return get_physical() + get_mental(); } int offdef() { return get_offense() + get_defense(); } // in Flare there are no distinct character classes. // instead each class is given a descriptor based on their base stat builds std::string character_class; // physical stats int hp; int hp_ticker; // mental stats int mp; int mp_ticker; // default equipment stats int dmg_melee_min_default; int dmg_melee_max_default; int dmg_ment_min_default; int dmg_ment_max_default; int dmg_ranged_min_default; int dmg_ranged_max_default; int absorb_min_default; int absorb_max_default; float speed_default; // addition damage and absorb granted from items int dmg_melee_min_add; int dmg_melee_max_add; int dmg_ment_min_add; int dmg_ment_max_add; int dmg_ranged_min_add; int dmg_ranged_max_add; int absorb_min_add; int absorb_max_add; float speed; std::set<std::string> equip_flags; std::vector<int> vulnerable; std::vector<int> vulnerable_base; // buff and debuff stats int transform_duration; int transform_duration_total; bool manual_untransform; bool transform_with_equipment; EffectManager effects; FPoint pos; FPoint forced_speed; unsigned char direction; int cooldown_hit; int cooldown_hit_ticks; // state int cur_state; // waypoint patrolling std::queue<FPoint> waypoints; int waypoint_pause; int waypoint_pause_ticks; // wandering area bool wander; SDL_Rect wander_area; int wander_ticks; int wander_pause_ticks; // enemy behavioral stats int chance_pursue; int chance_flee; std::vector<int> powers_list; std::vector<int> powers_list_items; std::vector<int> powers_passive; std::vector<int> power_chance; std::vector<int> power_index; std::vector<int> power_cooldown; std::vector<int> power_ticks; bool canUsePower(const Power &power, unsigned powerid) const; float melee_range; float threat_range; bool passive_attacker;//enemy will not initiate combat unless attacked int hero_stealth; int turn_delay; int turn_ticks; bool in_combat; bool join_combat; int cooldown_ticks; int cooldown; // min. # of frames between abilities int activated_powerslot; bool on_half_dead_casted; bool suppress_hp; // hide an enemy HP bar std::vector<EnemyLoot> loot; // for the teleport spell bool teleportation; FPoint teleport_destination; // weapons can modify spells int melee_weapon_power; int mental_weapon_power; int ranged_weapon_power; // for purchasing tracking int currency; // marked for death bool death_penalty; // Campaign event interaction std::string defeat_status; std::string convert_status; std::string quest_loot_requires_status; std::string quest_loot_requires_not_status; int quest_loot_id; int first_defeat_loot; // player look options std::string gfx_base; // folder in /images/avatar std::string gfx_head; // png in /images/avatar/[base] std::string gfx_portrait; // png in /images/portraits std::string transform_type; std::string animations; // default sounds std::string sfx_step; // formula numbers int max_spendable_stat_points; int max_points_per_stat; // preserve state before calcs int prev_maxhp; int prev_maxmp; int pres_hp; int pres_mp; // links to summoned creatures and the entity which summoned this std::vector<StatBlock*> summons; StatBlock* summoner; void removeFromSummons(); bool summonLimitReached(int power_id) const; }; #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/Stats.cpp���������������������������������������������������������������������0000664�0000000�0000000�00000003356�12247171015�0016377�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2013 Justin Jacobs This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "Stats.h" std::string STAT_NAME[STAT_COUNT]; // these names aren't visible in-game // but they are used for parsing config files like engine/stats.txt void setStatNames() { STAT_NAME[STAT_DMG_MELEE_MIN] = "dmg_melee_min"; STAT_NAME[STAT_DMG_MELEE_MAX] = "dmg_melee_max"; STAT_NAME[STAT_DMG_RANGED_MIN] = "dmg_ranged_min"; STAT_NAME[STAT_DMG_RANGED_MAX] = "dmg_ranged_max"; STAT_NAME[STAT_DMG_MENT_MIN] = "dmg_ment_min"; STAT_NAME[STAT_DMG_MENT_MAX] = "dmg_ment_max"; STAT_NAME[STAT_ABS_MIN] = "absorb_min"; STAT_NAME[STAT_ABS_MAX] = "absorb_max"; STAT_NAME[STAT_HP_MAX] = "hp"; STAT_NAME[STAT_HP_REGEN] = "hp_regen"; STAT_NAME[STAT_HP_PERCENT] = "hp_percent"; STAT_NAME[STAT_MP_MAX] = "mp"; STAT_NAME[STAT_MP_REGEN] = "mp_regen"; STAT_NAME[STAT_MP_PERCENT] = "mp_percent"; STAT_NAME[STAT_ACCURACY] = "accuracy"; STAT_NAME[STAT_AVOIDANCE] = "avoidance"; STAT_NAME[STAT_CRIT] = "crit"; STAT_NAME[STAT_XP_GAIN] = "xp_gain"; STAT_NAME[STAT_CURRENCY_FIND] = "currency_find"; STAT_NAME[STAT_ITEM_FIND] = "item_find"; STAT_NAME[STAT_STEALTH] = "stealth"; STAT_NAME[STAT_POISE] = "poise"; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/Stats.h�����������������������������������������������������������������������0000664�0000000�0000000�00000002447�12247171015�0016044�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2013 Justin Jacobs This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #pragma once #ifndef STATS_H #define STATS_H #include "CommonIncludes.h" #define STAT_COUNT 22 enum STAT { STAT_DMG_MELEE_MIN = 0, STAT_DMG_MELEE_MAX = 1, STAT_DMG_RANGED_MIN = 2, STAT_DMG_RANGED_MAX = 3, STAT_DMG_MENT_MIN = 4, STAT_DMG_MENT_MAX = 5, STAT_ABS_MIN = 6, STAT_ABS_MAX = 7, STAT_HP_MAX = 8, STAT_HP_REGEN = 9, STAT_HP_PERCENT = 10, STAT_MP_MAX = 11, STAT_MP_REGEN = 12, STAT_MP_PERCENT = 13, STAT_ACCURACY = 14, STAT_AVOIDANCE = 15, STAT_CRIT = 16, STAT_XP_GAIN = 17, STAT_CURRENCY_FIND = 18, STAT_ITEM_FIND = 19, STAT_STEALTH = 20, STAT_POISE = 21 }; extern std::string STAT_NAME[STAT_COUNT]; void setStatNames(); #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/TileSet.cpp�������������������������������������������������������������������0000664�0000000�0000000�00000007435�12247171015�0016654�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class TileSet * * TileSet storage and file loading */ #include "TileSet.h" #include "SharedResources.h" #include "FileParser.h" #include "UtilsParsing.h" #include "Settings.h" #include <cstdio> using namespace std; TileSet::TileSet() { sprites = NULL; reset(); } void TileSet::reset() { SDL_FreeSurface(sprites); alpha_background = true; trans_r = 255; trans_g = 0; trans_b = 255; sprites = NULL; tiles.clear(); anim.clear(); max_size_x = 0; max_size_y = 0; } void TileSet::loadGraphics(const std::string& filename) { if (sprites) SDL_FreeSurface(sprites); if (!TEXTURE_QUALITY) sprites = loadGraphicSurface("images/tilesets/noalpha/" + filename, "Couldn't load image", false, true); if (!sprites) sprites = loadGraphicSurface("images/tilesets/" + filename); } void TileSet::load(const std::string& filename) { if (current_map == filename) return; reset(); FileParser infile; string img; if (infile.open(filename)) { while (infile.next()) { if (infile.key == "tile") { infile.val = infile.val + ','; unsigned index = eatFirstInt(infile.val, ','); if (index >= tiles.size()) tiles.resize(index + 1); tiles[index].src.x = eatFirstInt(infile.val, ','); tiles[index].src.y = eatFirstInt(infile.val, ','); tiles[index].src.w = eatFirstInt(infile.val, ','); tiles[index].src.h = eatFirstInt(infile.val, ','); tiles[index].offset.x = eatFirstInt(infile.val, ','); tiles[index].offset.y = eatFirstInt(infile.val, ','); max_size_x = std::max(max_size_x, (tiles[index].src.w / TILE_W) + 1); max_size_y = std::max(max_size_y, (tiles[index].src.h / TILE_H) + 1); } else if (infile.key == "img") { img = infile.val; } else if (infile.key == "transparency") { alpha_background = false; infile.val = infile.val + ','; trans_r = (Uint8)eatFirstInt(infile.val, ','); trans_g = (Uint8)eatFirstInt(infile.val, ','); trans_b = (Uint8)eatFirstInt(infile.val, ','); } else if (infile.key == "animation") { int frame = 0; unsigned TILE_ID = toInt(infile.nextValue()); if (TILE_ID >= anim.size()) anim.resize(TILE_ID + 1); string repeat_val = infile.nextValue(); while (repeat_val != "") { anim[TILE_ID].frames++; anim[TILE_ID].pos.resize(frame + 1); anim[TILE_ID].frame_duration.resize(frame + 1); anim[TILE_ID].pos[frame].x = toInt(repeat_val); anim[TILE_ID].pos[frame].y = toInt(infile.nextValue()); anim[TILE_ID].frame_duration[frame] = toInt(infile.nextValue()); frame++; repeat_val = infile.nextValue(); } } } infile.close(); loadGraphics(img); } current_map = filename; } void TileSet::logic() { if (ANIMATED_TILES) { for (unsigned i = 0; i < anim.size() ; i++) { Tile_Anim &an = anim[i]; if (!an.frames) continue; if (an.duration >= an.frame_duration[an.current_frame]) { tiles[i].src.x = an.pos[an.current_frame].x; tiles[i].src.y = an.pos[an.current_frame].y; an.duration = 0; an.current_frame = (an.current_frame + 1) % an.frames; } an.duration++; } } } TileSet::~TileSet() { SDL_FreeSurface(sprites); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/TileSet.h���������������������������������������������������������������������0000664�0000000�0000000�00000004317�12247171015�0016315�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class TileSet * * TileSet storage and file loading */ #pragma once #ifndef TILE_SET_H #define TILE_SET_H #include "CommonIncludes.h" #include "Utils.h" /** * Describes a tile by its location \a src in the tileset sprite and * by the \a offset to be applied when rendering it on screen. * The offset is measured from upper left corner to the logical midpoint * of the tile at groundlevel. */ class Tile_Def { public: SDL_Rect src; Point offset; Tile_Def() { src.x = src.y = src.w = src.h = 0; offset.x = offset.y = 0; } }; class Tile_Anim { public: // Number of frames in this animation. if 0 no animation. // 1 makes no sense as it would produce astatic animation. unsigned short frames; unsigned short current_frame; // is in range 0..(frames-1) unsigned short duration; // how long the current frame is already displayed in ticks. std::vector<Point> pos; // position of each image. std::vector<unsigned short> frame_duration; // duration of each image in ticks. 0 will be treated the same as 1. Tile_Anim() { frames = 0; current_frame = 0; duration = 0; } }; class TileSet { private: void loadGraphics(const std::string& filename); void reset(); Uint8 trans_r; Uint8 trans_g; Uint8 trans_b; bool alpha_background; std::string current_map; public: // functions TileSet(); ~TileSet(); void load(const std::string& filename); void logic(); std::vector<Tile_Def> tiles; std::vector<Tile_Anim> anim; SDL_Surface *sprites; // oversize of the largest tile available, in number of tiles. int max_size_x; int max_size_y; }; #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/TooltipData.cpp���������������������������������������������������������������0000664�0000000�0000000�00000005222�12247171015�0017517�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "TooltipData.h" TooltipData::TooltipData() { tip_buffer = NULL; default_color = font->getColor("widget_normal"); } TooltipData::~TooltipData() { SDL_FreeSurface(tip_buffer); } TooltipData::TooltipData(const TooltipData &tdSource) { // DO NOT copy the buffered text render // Allow the new copy to create its own buffer // Otherwise the same buffer will be deleted twice, causing a mem error tip_buffer = NULL; lines.clear(); colors.clear(); for (unsigned int i=0; i<tdSource.lines.size(); i++) { lines.push_back(tdSource.lines[i]); colors.push_back(tdSource.colors[i]); } } TooltipData& TooltipData::operator= (const TooltipData &tdSource) { clear(); for (unsigned int i=0; i<tdSource.lines.size(); i++) { lines.push_back(tdSource.lines[i]); colors.push_back(tdSource.colors[i]); } return *this; } void TooltipData::clear() { lines.clear(); colors.clear(); SDL_FreeSurface(tip_buffer); tip_buffer = NULL; } void TooltipData::addText(const std::string &text, SDL_Color color) { lines.push_back(""); colors.push_back(color); for (unsigned int i=0; i<lines.size(); i++) { if (lines[i] == "") { colors[i] = color; for (unsigned int j=0; j<text.length(); j++) { if (text[j] == '\n') { // insert a space so intentionally blank lines are counted if (lines.back() == "") lines.back() += ' '; lines.push_back(""); colors.push_back(color); } else { lines.back() += text[j]; } } break; } } } void TooltipData::addText(const std::string &text) { addText(text, default_color); } bool TooltipData::isEmpty() { return lines.empty(); } bool TooltipData::compareFirstLine(const std::string &text) { if (lines.empty()) return false; if (lines[0] != text) return false; return true; } bool TooltipData::compare(const TooltipData *tip) { if (lines.size() != tip->lines.size()) return false; for (unsigned int i=0; i<lines.size(); i++) { if (lines[i] != tip->lines[i]) return false; } return true; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/TooltipData.h�����������������������������������������������������������������0000664�0000000�0000000�00000003611�12247171015�0017164�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #ifndef TOOLTIPDATA_H #define TOOLTIPDATA_H #include "SharedResources.h" enum STYLE { STYLE_FLOAT, STYLE_TOPLABEL }; /** * TooltipData contains the text and line colors for one tool tip. * Useful for keeping the data separate from the widget itself, so the data * can be passed around easily. * * Contains a image buffer to keep a render of the tooltip, rather than needing * to render it each frame. This buffer is not copied during copy/assign to * avoid multiple deconstructors on the same dynamically allocated memory. Thus * the new copy will recreate its own buffer next time it is displayed. */ class TooltipData { public: std::vector<std::string> lines; std::vector<SDL_Color> colors; SDL_Surface *tip_buffer; SDL_Color default_color; TooltipData(); ~TooltipData(); TooltipData(const TooltipData &tdSource); TooltipData& operator= (const TooltipData &tdSource); void clear(); // add text with support for new lines void addText(const std::string &text, SDL_Color color); void addText(const std::string &text); bool isEmpty(); // compare the first line bool compareFirstLine(const std::string &text); // compare all lines bool compare(const TooltipData *tip); }; #endif // TOOLTIPDATA_H �����������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/Utils.cpp���������������������������������������������������������������������0000664�0000000�0000000�00000030321�12247171015�0016371�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "Settings.h" #include "SharedResources.h" #include "Utils.h" #include <cmath> using namespace std; Point floor(FPoint fp) { Point result; result.x = (int)floor(fp.x); result.y = (int)floor(fp.y); return result; } FPoint screen_to_map(int x, int y, float camx, float camy) { FPoint r; if (TILESET_ORIENTATION == TILESET_ISOMETRIC) { float scrx = (x - VIEW_W_HALF) /2; float scry = (y - VIEW_H_HALF) /2; r.x = (UNITS_PER_PIXEL_X * scrx) + (UNITS_PER_PIXEL_Y * scry) + camx; r.y = (UNITS_PER_PIXEL_Y * scry) - (UNITS_PER_PIXEL_X * scrx) + camy; } else { r.x = (x - VIEW_W_HALF) * (UNITS_PER_PIXEL_X ) + camx; r.y = (y - VIEW_H_HALF) * (UNITS_PER_PIXEL_Y ) + camy; } return r; } /** * Returns a point (in map units) of a given (x,y) tupel on the screen * when the camera is at a given position. */ Point map_to_screen(float x, float y, float camx, float camy) { Point r; // adjust to the center of the viewport // we do this calculation first to avoid negative integer division float adjust_x = (VIEW_W_HALF + 0.5f) * UNITS_PER_PIXEL_X; float adjust_y = (VIEW_H_HALF + 0.5f) * UNITS_PER_PIXEL_Y; if (TILESET_ORIENTATION == TILESET_ISOMETRIC) { r.x = (x - camx - y + camy + adjust_x)/UNITS_PER_PIXEL_X; r.y = (x - camx + y - camy + adjust_y)/UNITS_PER_PIXEL_Y; } else { //TILESET_ORTHOGONAL r.x = (x - camx + adjust_x)/UNITS_PER_PIXEL_X; r.y = (y - camy + adjust_y)/UNITS_PER_PIXEL_Y; } return r; } Point center_tile(Point p) { if (TILESET_ORIENTATION == TILESET_ORTHOGONAL) { p.x += TILE_W_HALF; p.y += TILE_H_HALF; } else //TILESET_ISOMETRIC p.y += TILE_H_HALF; return p; } FPoint collision_to_map(Point p) { FPoint ret; ret.x = p.x + 0.5f; ret.y = p.y + 0.5f; return ret; } Point map_to_collision(FPoint p) { Point ret; ret.x = (int)floor(p.x); ret.y = (int)floor(p.y); return ret; } /** * Apply parameter distance to position and direction */ FPoint calcVector(FPoint pos, int direction, float dist) { FPoint p; p.x = pos.x; p.y = pos.y; float dist_straight = dist; float dist_diag = dist * 0.7071f; // 1/sqrt(2) switch (direction) { case 0: p.x -= dist_diag; p.y += dist_diag; break; case 1: p.x -= dist_straight; break; case 2: p.x -= dist_diag; p.y -= dist_diag; break; case 3: p.y -= dist_straight; break; case 4: p.x += dist_diag; p.y -= dist_diag; break; case 5: p.x += dist_straight; break; case 6: p.x += dist_diag; p.y += dist_diag; break; case 7: p.y += dist_straight; break; } return p; } float calcDist(FPoint p1, FPoint p2) { return sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y)); } /** * is target within the area defined by center and radius? */ bool isWithin(FPoint center, float radius, FPoint target) { return (calcDist(center, target) < radius); } /** * is target within the area defined by rectangle r? */ bool isWithin(SDL_Rect r, Point target) { return target.x >= r.x && target.y >= r.y && target.x < r.x+r.w && target.y < r.y+r.h; } Uint32 readPixel(SDL_Surface *surface, int x, int y) { SDL_LockSurface(surface); int bpp = surface->format->BytesPerPixel; Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; Uint32 pixel; switch (bpp) { case 1: pixel = *p; break; case 2: pixel = *(Uint16 *)p; break; case 3: if (SDL_BYTEORDER == SDL_BIG_ENDIAN) pixel = p[0] << 16 | p[1] << 8 | p[2]; else pixel = p[0] | p[1] << 8 | p[2] << 16; break; case 4: pixel = *(Uint32 *)p; break; default: SDL_UnlockSurface(surface); return 0; } SDL_UnlockSurface(surface); return pixel; } /* * Set the pixel at (x, y) to the given value * NOTE: The surface must be locked before calling this! * * Source: SDL Documentation * http://www.libsdl.org/docs/html/guidevideo.html */ void drawPixel(SDL_Surface *surface, int x, int y, Uint32 pixel) { int bpp = surface->format->BytesPerPixel; /* Here p is the address to the pixel we want to set */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; switch(bpp) { case 1: *p = pixel; break; case 2: *(Uint16 *)p = pixel; break; case 3: #if (SDL_BYTEORDER == SDL_BIG_ENDIAN) p[0] = (pixel >> 16) & 0xff; p[1] = (pixel >> 8) & 0xff; p[2] = pixel & 0xff; #else p[0] = pixel & 0xff; p[1] = (pixel >> 8) & 0xff; p[2] = (pixel >> 16) & 0xff; #endif break; case 4: *(Uint32 *)p = pixel; break; } } /** * draw line to the screen * NOTE: The surface must be locked before calling this! * * from http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#Simplification */ void drawLine(SDL_Surface *surface, int x0, int y0, int x1, int y1, Uint32 color) { const int dx = abs(x1-x0); const int dy = abs(y1-y0); const int sx = x0 < x1 ? 1 : -1; const int sy = y0 < y1 ? 1 : -1; int err = dx-dy; do { //skip draw if outside screen if (x0 > 0 && y0 > 0 && x0 < VIEW_W && y0 < VIEW_H) drawPixel(surface,x0,y0,color); int e2 = 2*err; if (e2 > -dy) { err = err - dy; x0 = x0 + sx; } if (e2 < dx) { err = err + dx; y0 = y0 + sy; } } while(x0 != x1 || y0 != y1); } void drawLine(SDL_Surface *surface, Point pos0, Point pos1, Uint32 color) { if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface); drawLine(surface, pos0.x, pos0.y, pos1.x, pos1.y, color); if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface); } void drawRectangle(SDL_Surface *surface, Point pos0, Point pos1, Uint32 color) { if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface); drawLine(surface, pos0.x, pos0.y, pos1.x, pos0.y, color); drawLine(surface, pos1.x, pos0.y, pos1.x, pos1.y, color); drawLine(surface, pos0.x, pos0.y, pos0.x, pos1.y, color); drawLine(surface, pos0.x, pos1.y, pos1.x, pos1.y, color); if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface); } void setSDL_RGBA(Uint32 *rmask, Uint32 *gmask, Uint32 *bmask, Uint32 *amask) { #if SDL_BYTEORDER == SDL_BIG_ENDIAN *rmask = 0xff000000; *gmask = 0x00ff0000; *bmask = 0x0000ff00; *amask = 0x000000ff; #else *rmask = 0x000000ff; *gmask = 0x0000ff00; *bmask = 0x00ff0000; *amask = 0xff000000; #endif } /** * create blank surface * based on example: http://www.libsdl.org/docs/html/sdlcreatergbsurface.html */ SDL_Surface* createAlphaSurface(int width, int height) { SDL_Surface *surface; Uint32 rmask, gmask, bmask, amask; setSDL_RGBA(&rmask, &gmask, &bmask, &amask); if (HWSURFACE) surface = SDL_CreateRGBSurface(SDL_HWSURFACE|SDL_SRCALPHA, width, height, BITS_PER_PIXEL, rmask, gmask, bmask, amask); else surface = SDL_CreateRGBSurface(SDL_SWSURFACE|SDL_SRCALPHA, width, height, BITS_PER_PIXEL, rmask, gmask, bmask, amask); if(surface == NULL) { fprintf(stderr, "CreateRGBSurface failed: %s\n", SDL_GetError()); } // optimize SDL_Surface *cleanup = surface; surface = SDL_DisplayFormatAlpha(surface); SDL_FreeSurface(cleanup); return surface; } SDL_Surface* createSurface(int width, int height) { SDL_Surface *surface; Uint32 rmask, gmask, bmask, amask; setSDL_RGBA(&rmask, &gmask, &bmask, &amask); if (HWSURFACE) surface = SDL_CreateRGBSurface(SDL_HWSURFACE, width, height, BITS_PER_PIXEL, rmask, gmask, bmask, amask); else surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, BITS_PER_PIXEL, rmask, gmask, bmask, amask); if(surface == NULL) { fprintf(stderr, "CreateRGBSurface failed: %s\n", SDL_GetError()); } else { SDL_SetColorKey(surface, SDL_SRCCOLORKEY, SDL_MapRGB(surface->format,255,0,255)); SDL_Surface *cleanup = surface; surface = SDL_DisplayFormat(surface); SDL_FreeSurface(cleanup); } return surface; } SDL_Surface* loadGraphicSurface(std::string filename, std::string errormessage, bool IfNotFoundExit, bool HavePinkColorKey) { SDL_Surface *ret = NULL; SDL_Surface *cleanup = IMG_Load(mods->locate(filename).c_str()); if(!cleanup) { if (!errormessage.empty()) fprintf(stderr, "%s: %s\n", errormessage.c_str(), IMG_GetError()); if (IfNotFoundExit) { SDL_Quit(); exit(1); } } else { if (HavePinkColorKey) SDL_SetColorKey(cleanup, SDL_SRCCOLORKEY, SDL_MapRGB(cleanup->format, 255, 0, 255)); ret = SDL_DisplayFormatAlpha(cleanup); SDL_FreeSurface(cleanup); } return ret; } /* * Returns false if a pixel at Point px is transparent * * Source: SDL Documentation * http://www.libsdl.org/cgi/docwiki.cgi/Introduction_to_SDL_Video#getpixel */ bool checkPixel(Point px, SDL_Surface *surface) { SDL_LockSurface(surface); int bpp = surface->format->BytesPerPixel; /* Here p is the address to the pixel we want to retrieve */ Uint8 *p = (Uint8 *)surface->pixels + px.y * surface->pitch + px.x * bpp; Uint32 pixel; switch (bpp) { case 1: pixel = *p; break; case 2: pixel = *(Uint16 *)p; break; case 3: #if (SDL_BYTEORDER == SDL_BIG_ENDIAN) pixel = p[0] << 16 | p[1] << 8 | p[2]; #else pixel = p[0] | p[1] << 8 | p[2] << 16; #endif break; case 4: pixel = *(Uint32 *)p; break; default: SDL_UnlockSurface(surface); return false; } Uint8 r,g,b,a; SDL_GetRGBA(pixel, surface->format, &r, &g, &b, &a); if (r == 255 && g == 0 && b ==255 && a == 255) { SDL_UnlockSurface(surface); return false; } if (a == 0) { SDL_UnlockSurface(surface); return false; } SDL_UnlockSurface(surface); return true; } SDL_Surface* scaleSurface(SDL_Surface *source, int width, int height) { if(!source || !width || !height) return 0; double _stretch_factor_x, _stretch_factor_y; SDL_Surface *_ret = SDL_CreateRGBSurface(source->flags, width, height, source->format->BitsPerPixel, source->format->Rmask, source->format->Gmask, source->format->Bmask, source->format->Amask); _stretch_factor_x = width / (double)source->w; _stretch_factor_y = height / (double)source->h; for(Uint32 y = 0; y < (Uint32)source->h; y++) for(Uint32 x = 0; x < (Uint32)source->w; x++) { Uint32 spixel = readPixel(source, x, y); for(Uint32 o_y = 0; o_y < _stretch_factor_y; ++o_y) for(Uint32 o_x = 0; o_x < _stretch_factor_x; ++o_x) { Uint32 dx = (Sint32)(_stretch_factor_x * x) + o_x; Uint32 dy = (Sint32)(_stretch_factor_y * y) + o_y; drawPixel(_ret, dx, dy, spixel); } } return _ret; } int calcDirection(const FPoint &src, const FPoint &dst) { return calcDirection(src.x, src.y, dst.x, dst.y); } int calcDirection(float x0, float y0, float x1, float y1) { const float pi = 3.1415926535898f; float theta = calcTheta(x0, y0, x1, y1); float val = theta / (pi/4); int dir = ((val < 0) ? ceil(val-0.5) : floor(val+0.5)) + 4; dir = (dir + 1) % 8; if (dir >= 0 && dir < 8) return dir; else return 0; } // convert cartesian to polar theta where (x1,x2) is the origin float calcTheta(float x1, float y1, float x2, float y2) { const float pi = 3.1415926535898f; // calculate base angle float dx = (float)x2 - (float)x1; float dy = (float)y2 - (float)y1; float exact_dx = x2 - x1; float theta; // convert cartesian to polar coordinates if (exact_dx == 0) { if (dy > 0.0) theta = pi/2.0f; else theta = -pi/2.0f; } else { theta = atan(dy/dx); if (dx < 0.0 && dy >= 0.0) theta += pi; if (dx < 0.0 && dy < 0.0) theta -= pi; } return theta; } void setupSDLVideoMode(unsigned width, unsigned height) { Uint32 flags = 0; if (FULLSCREEN) flags = flags | SDL_FULLSCREEN; if (DOUBLEBUF) flags = flags | SDL_DOUBLEBUF; if (HWSURFACE) flags = flags | SDL_HWSURFACE | SDL_HWACCEL; else flags = flags | SDL_SWSURFACE; screen = SDL_SetVideoMode (width, height, 0, flags); } std::string abbreviateKilo(int amount) { stringstream ss; if (amount < 1000) ss << amount; else ss << (amount/1000) << msg->get("k"); return ss.str(); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/Utils.h�����������������������������������������������������������������������0000664�0000000�0000000�00000011314�12247171015�0016037�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * Utils * * Various utility structures, enums, function */ #pragma once #ifndef UTILS_H #define UTILS_H #include "CommonIncludes.h" #include <stdint.h> class Point { public: int x, y; Point() : x(0), y(0) {} Point(int _x, int _y) : x(_x), y(_y) {} }; class FPoint { public: float x, y; FPoint(Point _p) : x((float)_p.x), y((float)_p.y) {} FPoint() : x(0), y(0) {} FPoint(float _x, float _y) : x(_x), y(_y) {} }; // message passing struct for various sprites rendered map inline class Renderable { public: SDL_Surface *sprite; // image to be used SDL_Rect src; // location on the sprite in pixel coordinates. FPoint map_pos; // The map location on the floor between someone's feet Point offset; // offset from map_pos to topleft corner of sprite uint64_t prio; // 64-32 bit for map position, 31-16 for intertile position, 15-0 user dependent, such as Avatar. Renderable() : sprite(0) , src(SDL_Rect()) , map_pos() , offset() , prio(0) {} }; class Event_Component { public: std::string type; std::string s; int x; int y; int z; int a; int b; Event_Component() : type("") , s("") , x(0) , y(0) , z(0) , a(0) , b(0) {} }; Point floor(FPoint fp); FPoint screen_to_map(int x, int y, float camx, float camy); Point map_to_screen(float x, float y, float camx, float camy); Point center_tile(Point p); Point map_to_collision(FPoint p); FPoint collision_to_map(Point p); FPoint calcVector(FPoint pos, int direction, float dist); float calcDist(FPoint p1, FPoint p2); float calcTheta(float x1, float y1, float x2, float y2); int calcDirection(float x0, float y0, float x1, float y1); int calcDirection(const FPoint &src, const FPoint &dst); bool isWithin(FPoint center, float radius, FPoint target); bool isWithin(SDL_Rect r, Point target); Uint32 readPixel(SDL_Surface *screen, int x, int y); void drawPixel(SDL_Surface *screen, int x, int y, Uint32 color); void drawLine(SDL_Surface *screen, int x0, int y0, int x1, int y1, Uint32 color); void drawLine(SDL_Surface *screen, Point pos0, Point pos1, Uint32 color); void drawRectangle(SDL_Surface *surface, Point pos0, Point pos1, Uint32 color); bool checkPixel(Point px, SDL_Surface *surface); /** * Creates a SDL_Surface. * The SDL_HWSURFACE or SDL_SWSURFACE flag is set according * to settings. The result is a surface which has the same format as the * screen surface. * Additionally the alpha flag is set, so transparent blits are possible. */ SDL_Surface* createAlphaSurface(int width, int height); /** * Creates a SDL_Surface. * The SDL_HWSURFACE or SDL_SWSURFACE flag is set according * to settings. The result is a surface which has the same format as the * screen surface. * The bright pink (rgb 0xff00ff) is set as transparent color. */ SDL_Surface* createSurface(int width, int height); SDL_Surface* scaleSurface(SDL_Surface *source, int width, int height); /** * @brief loadGraphicSurface loads an image from a file. * @param filename * The parameter filename is mandatory and specifies the image to be * loaded. The filename will be located via the modmanager. * @param errormessage * This is an optional parameter, which defines which error message * should be displayed. If the errormessage is an empty string, no error * message will be printed at all. * @param IfNotFoundExit * If this optional boolean parameter is set to true, the program will * shutdown sdl and quit, if the specified image is not found. * @param HavePinkColorKey * This optional parameter specifies whether a color key with * RGB(0xff, 0, 0xff) should be applied to the image. * @return * Returns the SDL_Surface of the specified image or NULL if not * successful */ SDL_Surface* loadGraphicSurface(std::string filename, std::string errormessage = "Couldn't load image", bool IfNotFoundExit = false, bool HavePinkColorKey = false); void setupSDLVideoMode(unsigned width, unsigned height); std::string abbreviateKilo(int amount); #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/UtilsDebug.cpp����������������������������������������������������������������0000664�0000000�0000000�00000014427�12247171015�0017351�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2012 David Bariod This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include <ostream> #include "CommonIncludes.h" #include "Utils.h" #include "UtilsDebug.h" using namespace std; ostream & operator<< (ostream & os, const SDL_Event & evt) { switch (evt.type) { case SDL_ACTIVEEVENT: os << reinterpret_cast<const SDL_ActiveEvent&>(evt); break; case SDL_KEYUP: case SDL_KEYDOWN: os << reinterpret_cast<const SDL_KeyboardEvent&>(evt); break; case SDL_MOUSEMOTION: os << reinterpret_cast<const SDL_MouseMotionEvent&>(evt); break; case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONDOWN: os << reinterpret_cast<const SDL_MouseButtonEvent&>(evt); break; case SDL_JOYAXISMOTION: os << reinterpret_cast<const SDL_JoyAxisEvent&>(evt); break; case SDL_JOYBALLMOTION: os << reinterpret_cast<const SDL_JoyBallEvent&>(evt); break; case SDL_JOYHATMOTION: os << reinterpret_cast<const SDL_JoyHatEvent&>(evt); break; case SDL_JOYBUTTONUP: case SDL_JOYBUTTONDOWN: os << reinterpret_cast<const SDL_JoyButtonEvent&>(evt); break; case SDL_QUIT: os << reinterpret_cast<const SDL_QuitEvent&>(evt); break; case SDL_SYSWMEVENT: os << reinterpret_cast<const SDL_SysWMEvent&>(evt); break; case SDL_VIDEORESIZE: os << reinterpret_cast<const SDL_ResizeEvent&>(evt); break; case SDL_VIDEOEXPOSE: os << reinterpret_cast<const SDL_ExposeEvent&>(evt); break; case SDL_USEREVENT: os << "User Event"; break; default: os << "Unknown event: " << evt.type; return os; } return os; } ostream & operator<< (ostream & os, const SDL_ActiveEvent & evt) { os << "{SDL_ACTIVE_EVENT, gain = " << static_cast<uint16_t>(evt.gain) << ", state = " << static_cast<uint16_t>(evt.state) << "}"; return os; } ostream & operator<< (ostream & os, const SDL_KeyboardEvent & evt) { os << "{"; if (SDL_KEYDOWN == evt.type) { os << "SDL_KEYDOWN"; } else if (SDL_KEYUP == evt.type) { os << "SDL_KEYUP"; } else { os << "Unexpected value type: " << evt.type << "}"; return os; } os << ", state"; if (SDL_PRESSED == evt.state) { os << " = SDL_PRESSED"; } else if (SDL_RELEASED == evt.state) { os << " = SDL_RELEASED"; } else { os << " = ??" << evt.state; } os << ", SDL_keysym: " << evt.keysym << "}"; return os; } ostream & operator<< (ostream & os, const SDL_keysym & ks) { os << "{scancode = " << static_cast<uint16_t>(ks.scancode) << ", sym = " << ks.sym << ", mod = " << ks.mod << ", unicode = " << ks.unicode << "}"; return os; } ostream & operator<< (ostream & os, const SDL_MouseMotionEvent & evt) { os << "{SDL_MOUSEMOTION, state = " << static_cast<uint16_t>(evt.state) << ", (x,y) = (" << evt.x << "," << evt.y << ")" << ", (xrel,yrel) = (" << evt.xrel << "," << evt.yrel << ")}"; return os; } ostream & operator << (ostream & os, const SDL_MouseButtonEvent & evt) { os << "{SDL_MOUSEBUTTON, type = "; if (SDL_MOUSEBUTTONDOWN == evt.type) { os << "DOWN"; } else if (SDL_MOUSEBUTTONUP == evt.type) { os << "UP"; } else { os << "??" << evt.type << "}"; return os; } os << ", button = " << static_cast<uint16_t>(evt.button) << ", state = "; if (SDL_PRESSED == evt.state) { os << "SDL_PRESSED"; } else if (SDL_RELEASED == evt.state) { os << "SDL_RELEASED"; } else { os << "??" << static_cast<uint16_t>(evt.state); } os << ", (x,y) = (" << evt.x << "," << evt.y << ")}"; return os; } ostream & operator<< (ostream & os, const SDL_JoyAxisEvent & evt) { os << "{SDL_JOYAXIS, which = " << static_cast<uint16_t>(evt.which) << ", axis = " << static_cast<uint16_t>(evt.axis) << ", value = " << evt.value << "}"; return os; } ostream & operator<< (ostream & os, const SDL_JoyBallEvent & evt) { os << "{SDL_JOYBALLMOTION, which = " << static_cast<uint16_t>(evt.which) << ", ball = " << static_cast<uint16_t>(evt.ball) << ", (xrel,yrel) = " << "(" << evt.xrel << "," << evt.yrel << ")}"; return os; } ostream & operator<< (ostream & os, const SDL_JoyHatEvent & evt) { os << "{SDL_JOYHATEVENT, which = " << static_cast<uint16_t>(evt.which) << ", hat = " << static_cast<uint16_t>(evt.hat) << ", value = " << static_cast<uint16_t>(evt.value) << "}"; return os; } ostream & operator<< (ostream & os, const SDL_JoyButtonEvent & evt) { if (SDL_JOYBUTTONDOWN == evt.type) { os << "{SDL_JOYBUTTONDOWN, "; } else if (SDL_JOYBUTTONUP == evt.type) { os << "{SDL_JOYBUTTONUP, "; } else { os << "{??unknown " << evt.type; return os; } os << "{SDL_JOYBUTTONEVENT, which = " << static_cast<uint16_t>(evt.which) << ", button = " << static_cast<uint16_t>(evt.button) << ", state = "; if (SDL_PRESSED == evt.state) { os << "SDL_PRESSED}"; } else if (SDL_RELEASED == evt.state) { os << "SDL_RELEASED}"; } else { os << "??" << static_cast<uint16_t>(evt.state) << "}"; } return os; } ostream & operator<< (ostream & os, const SDL_QuitEvent &) { os << "{SDL_QUITEVENT}"; return os; } ostream & operator<< (ostream & os, const SDL_SysWMEvent &) { os << "{SDL_SYSWMEVENT}"; return os; } ostream & operator<< (ostream & os, const SDL_ResizeEvent &evt) { os << "{SDL_RESIZE_EVENT, (w,h) = (" << evt.w << "," << evt.h << ")}"; return os; } ostream & operator<< (ostream & os, const SDL_ExposeEvent &) { os << "{SDL_EXPOSEEVENT}"; return os; } ostream & operator<< (ostream & os, const SDL_Rect & rect) { os << "(x,y,h,w) = (" << rect.x << "," << rect.y << "," << rect.h << "," << rect.w << ")"; return os; } ostream & operator<< (ostream & os, const Point & p) { os << "(x,y) = (" << p.x << "," << p.y << ")"; return os; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/UtilsDebug.h������������������������������������������������������������������0000664�0000000�0000000�00000003604�12247171015�0017011�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2012 David Bariod This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #pragma once #ifndef UTILS_DEBUG_H #define UTILS_DEBUG_H extern std::ostream & operator<< (std::ostream &, const SDL_Event &); extern std::ostream & operator<< (std::ostream &, const SDL_ActiveEvent &); extern std::ostream & operator<< (std::ostream &, const SDL_KeyboardEvent &); extern std::ostream & operator<< (std::ostream &, const SDL_keysym &); extern std::ostream & operator<< (std::ostream &, const SDL_MouseMotionEvent &); extern std::ostream & operator<< (std::ostream &, const SDL_MouseButtonEvent &); extern std::ostream & operator<< (std::ostream &, const SDL_JoyAxisEvent &); extern std::ostream & operator<< (std::ostream &, const SDL_JoyBallEvent &); extern std::ostream & operator<< (std::ostream &, const SDL_JoyHatEvent &); extern std::ostream & operator<< (std::ostream &, const SDL_JoyButtonEvent &); extern std::ostream & operator<< (std::ostream &, const SDL_QuitEvent &); extern std::ostream & operator<< (std::ostream &, const SDL_SysWMEvent &); extern std::ostream & operator<< (std::ostream &, const SDL_ResizeEvent &); extern std::ostream & operator<< (std::ostream &, const SDL_ExposeEvent &); extern std::ostream & operator<< (std::ostream &, const SDL_Rect &); extern std::ostream & operator<< (std::ostream &, const Point &); #endif ����������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/UtilsFileSystem.cpp�����������������������������������������������������������0000664�0000000�0000000�00000006156�12247171015�0020407�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * UtilsFileSystem * * Various file system function wrappers. Abstracted here to hide OS-specific implementations */ #include "CommonIncludes.h" #include "UtilsFileSystem.h" #include <sys/types.h> #include <sys/stat.h> #include <dirent.h> #include <errno.h> #include <stdlib.h> #ifndef _WIN32 #include <unistd.h> #endif /** * Check to see if a directory/folder exists */ bool dirExists(const std::string &path) { struct stat st; return (stat(path.c_str(), &st) == 0); } bool pathExists(const std::string &path) { struct stat st; return (stat(path.c_str(), &st) == 0); } /** * Create this folder if it doesn't already exist */ void createDir(std::string path) { #ifndef _WIN32 // *nix implementation mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); #endif #ifdef _WIN32 // win implementation std::string syscmd = "mkdir " + path; system(syscmd.c_str()); #endif } bool isDirectory(const std::string &path) { struct stat st; stat(path.c_str(), &st); return st.st_mode & S_IFDIR; } /** * Check to see if a file exists * The filename parameter should include the entire path to this file */ bool fileExists(std::string filename) { bool exists; std::ifstream infile(filename.c_str()); exists = infile.is_open(); if (infile.is_open()) infile.close(); return exists; } /** * Returns a vector containing all filenames in a given folder with the given extension */ int getFileList(std::string dir, std::string ext, std::vector<std::string> &files) { DIR *dp; struct dirent *dirp; if((dp = opendir(dir.c_str())) == NULL) return errno; size_t extlen = ext.length(); while ((dirp = readdir(dp)) != NULL) { std::string filename = std::string(dirp->d_name); if (filename.length() > extlen) if(filename.substr(filename.length() - extlen,extlen) == ext) files.push_back(dir + "/" + filename); } closedir(dp); return 0; } /** * Returns a vector containing all directory names in a given directory */ int getDirList(std::string dir, std::vector<std::string> &dirs) { DIR *dp; struct dirent *dirp; struct stat st; if((dp = opendir(dir.c_str())) == NULL) { return errno; } while ((dirp = readdir(dp)) != NULL) { // do not use dirp->d_type, it's not portable std::string directory = std::string(dirp->d_name); std::string mod_dir = dir + "/" + directory; if ((stat(mod_dir.c_str(), &st) != -1) && S_ISDIR(st.st_mode) && directory != "." && directory != ".." ) { dirs.push_back(directory); } } closedir(dp); return 0; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/UtilsFileSystem.h�������������������������������������������������������������0000664�0000000�0000000�00000002337�12247171015�0020051�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * UtilsFileSystem * * Various file system function wrappers. Abstracted here to hide OS-specific implementations */ #pragma once #ifndef UTILS_FILE_SYSTEM_H #define UTILS_FILE_SYSTEM_H #include "CommonIncludes.h" bool dirExists(const std::string &path); bool pathExists(const std::string &path); void createDir(std::string path); bool fileExists(std::string filename); int getFileList(std::string dir, std::string ext, std::vector<std::string> &files); int getDirList(std::string dir, std::vector<std::string> &dirs); bool isDirectory(const std::string &path); #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/UtilsMath.h�������������������������������������������������������������������0000664�0000000�0000000�00000003657�12247171015�0016664�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2012 Piotr Rak This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #pragma once #ifndef UTILS_MATH_H #define UTILS_MATH_H 1 #include <cassert> #include <cstdlib> #include <algorithm> // for std::min()/std::max() #include "math.h" /** * Clamps value to floor. * * Postcondition: value >= floor */ template <typename Ty1_, typename Ty2_> inline void clampFloor(Ty1_& value, Ty2_ floor) { value = std::max<Ty1_>(value, floor); } /** * Clamps value to ceiling. * * Postcondition: value <= ceiling */ template <typename Ty1_, typename Ty2_> inline void clampCeil(Ty1_& value, Ty2_ ceiling) { value = std::min<Ty1_>(value, ceiling); } /** * Clamps value. * * Postcondition: floor <= value <= ceiling */ template <typename Ty1_, typename Ty2_> inline void clamp(Ty1_& value, Ty2_ floor, Ty2_ ceiling) { clampFloor(value, floor); clampCeil(value, ceiling); } /** * Returns sign of value. */ template <typename Ty_> inline Ty_ signum(Ty_ value) { return (Ty_(0) < value) - (value < Ty_(0)); } /** * Returns random number between minVal and maxVal. */ inline int randBetween(int minVal, int maxVal) { if (minVal == maxVal) return minVal; int d = maxVal - minVal; return minVal + (rand() % (d + signum(d))); } /** * Returns true with random percent chance. */ inline bool percentChance(int percent) { return rand() % 100 < percent; } #endif // UTILS_MATH_H ���������������������������������������������������������������������������������flare-engine-0.19/src/UtilsParsing.cpp��������������������������������������������������������������0000664�0000000�0000000�00000014527�12247171015�0017727�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "CommonIncludes.h" #include "UtilsParsing.h" #include "Settings.h" #include <cstdlib> #include <typeinfo> using namespace std; string trim(string s, const string& delimiters) { return trim_left_inplace(trim_right_inplace(s, delimiters), delimiters); } string trim_left_inplace(string s, const string& delimiters) { return s.erase(0, s.find_first_not_of(delimiters)); } string trim_right_inplace(string s, const string& delimiters) { return s.erase(s.find_last_not_of(delimiters) + 1); } /** * Parse a duration string and return duration in frames. */ int parse_duration(const std::string& s) { int val = 0; std::string suffix = ""; std::stringstream ss; ss.str(s); ss >> val; ss >> suffix; if (suffix == "s") val *= MAX_FRAMES_PER_SEC; else if (suffix == "ms") val = (val*MAX_FRAMES_PER_SEC) / 1000; return val; } string parse_section_title(const string& s) { size_t bracket = s.find_first_of(']'); if (bracket == string::npos) return ""; // not found return s.substr(1, bracket-1); } void parse_key_pair(const string& s, string &key, string &val) { size_t separator = s.find_first_of('='); if (separator == string::npos) { key = ""; val = ""; return; // not found } key = s.substr(0, separator); val = s.substr(separator+1, s.length()); key = trim(key); val = trim(val); } /** * Given a string that starts with a decimal number then a comma * Return that int, and modify the string to remove the num and comma * * This is basically a really lazy "split" replacement */ int eatFirstInt(string &s, char separator) { size_t seppos = s.find_first_of(separator); if (seppos == string::npos) { s = ""; return 0; // not found } int num = toInt(s.substr(0, seppos)); s = s.substr(seppos+1, s.length()); return num; } string eatFirstString(string &s, char separator) { size_t seppos = s.find_first_of(separator); if (seppos == string::npos) return ""; // not found string outs = s.substr(0, seppos); s = s.substr(seppos+1, s.length()); return outs; } // similar to eatFirstString but does not alter the input string string getNextToken(const string& s, size_t &cursor, char separator) { size_t seppos = s.find_first_of(separator, cursor); if (seppos == string::npos) { // not found cursor = string::npos; return ""; } string outs = s.substr(cursor, seppos-cursor); cursor = seppos+1; return outs; } // strip carriage return if exists string stripCarriageReturn(const string& line) { if (line.length() > 0) { if ('\r' == line.at(line.length()-1)) { return line.substr(0, line.length()-1); } } return line; } string getLine(ifstream &infile) { string line; // This is the standard way to check whether a read failed. if (!getline(infile, line)) return ""; line = stripCarriageReturn(line); return line; } bool tryParseValue(const type_info & type, const char * value, void * output) { return tryParseValue(type, string(value), output); } bool tryParseValue(const type_info & type, const std::string & value, void * output) { stringstream stream(value); // TODO: add additional type parsing if (type == typeid(bool)) { stream>>(bool&)*((bool*)output); } else if (type == typeid(int)) { stream>>(int&)*((int*)output); } else if (type == typeid(unsigned int)) { stream>>(unsigned int&)*((unsigned int*)output); } else if (type == typeid(short)) { stream>>(short&)*((short*)output); } else if (type == typeid(unsigned short)) { stream>>(unsigned short&)*((unsigned short*)output); } else if (type == typeid(char)) { stream>>(char&)*((char*)output); } else if (type == typeid(unsigned char)) { stream>>(unsigned char&)*((unsigned char*)output); } else if (type == typeid(float)) { stream>>(float&)*((float*)output); } else if (type == typeid(std::string)) { *((string *)output) = value; } else { fprintf(stderr, "%s: a required type is not defined!\n", __FUNCTION__); return false; } return !stream.fail(); } std::string toString(const type_info & type, void * value) { stringstream stream; // TODO: add additional type parsing if (type == typeid(bool)) { stream<<*((bool*)value); } else if (type == typeid(int)) { stream<<*((int*)value); } else if (type == typeid(unsigned int)) { stream<<*((unsigned int*)value); } else if (type == typeid(short)) { stream<<*((short*)value); } else if (type == typeid(unsigned short)) { stream<<*((unsigned short*)value); } else if (type == typeid(char)) { stream<<*((char*)value); } else if (type == typeid(unsigned char)) { stream<<*((unsigned char*)value); } else if (type == typeid(float)) { stream<<*((float*)value); } else if (type == typeid(std::string)) { return (string &)*((string *)value); } else { fprintf(stderr, "%s: a required type is not defined!\n", __FUNCTION__); return ""; } return stream.str(); } int toInt(const string& s, int default_value) { int result; if (!(stringstream(s) >> result)) result = default_value; return result; } float toFloat(const string& s, float default_value) { float result; if (!(stringstream(s) >> result)) result = default_value; return result; } unsigned long toUnsignedLong(const string& s, unsigned long default_value) { unsigned long result; if (!(stringstream(s) >> result)) result = default_value; return result; } bool toBool(std::string value) { trim(value); std::transform(value.begin(), value.end(), value.begin(), ::tolower); if (value == "true") return true; if (value == "yes") return true; if (value == "1") return true; if (value == "false") return false; if (value == "no") return false; if (value == "0") return false; fprintf(stderr, "%s %s doesn't know how to handle %s\n", __FILE__, __FUNCTION__, value.c_str()); return false; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/UtilsParsing.h����������������������������������������������������������������0000664�0000000�0000000�00000003756�12247171015�0017376�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #pragma once #ifndef UTILS_PARSING_H #define UTILS_PARSING_H #include "CommonIncludes.h" #include <typeinfo> std::string trim(std::string s, const std::string& delimiters = " \f\n\r\t\v"); std::string trim_left_inplace(std::string s, const std::string& delimiters = " \f\n\r\t\v"); std::string trim_right_inplace(std::string s, const std::string& delimiters = " \f\n\r\t\v"); int parse_duration(const std::string& s); std::string parse_section_title(const std::string& s); void parse_key_pair(const std::string& s, std::string& key, std::string& val); int eatFirstInt(std::string& s, char separator); std::string eatFirstString(std::string& s, char separator); std::string getNextToken(const std::string& s, size_t& cursor, char separator); std::string stripCarriageReturn(const std::string& line); std::string getLine(std::ifstream& infile); bool tryParseValue(const std::type_info & type, const char * value, void * output); bool tryParseValue(const std::type_info & type, const std::string & value, void * output); std::string toString(const std::type_info & type, void * value); int toInt(const std::string& s, int default_value = 0); float toFloat(const std::string &s, float default_value = 0.0); unsigned long toUnsignedLong(const std::string& s, unsigned long default_value = 0); bool toBool(std::string value); #endif ������������������flare-engine-0.19/src/Widget.cpp��������������������������������������������������������������������0000664�0000000�0000000�00000010442�12247171015�0016516�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2012 Stefan Beller Copyright © 2013 Joseph Bleau This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "SharedResources.h" #include "Widget.h" Widget::Widget() : render_to_alpha(false) , in_focus(false) , focusable(false) , pos() { pos.x = pos.y = pos.w = pos.h = 0; } Widget::~Widget() { } void Widget::activate() { } void Widget::deactivate() { } void Widget::defocus() { in_focus = false; } bool Widget::getNext() { return false; } bool Widget::getPrev() { return false; } TabList::TabList(ScrollType _scrolltype, int _LEFT, int _RIGHT, int _ACTIVATE) : widgets() , current(-1) , previous(-1) , locked(false) , scrolltype(_scrolltype) , MV_LEFT(_LEFT) , MV_RIGHT(_RIGHT) , ACTIVATE(_ACTIVATE) { } TabList::~TabList() { } bool TabList::isLocked() { return locked; } void TabList::lock() { locked = true; if (current_is_valid()) widgets.at(current)->defocus(); } void TabList::unlock() { locked = false; if (current_is_valid()) widgets.at(current)->in_focus = true; } void TabList::add(Widget* widget) { if (widget == NULL) return; std::vector<Widget*>::iterator find = std::find( widgets.begin(), widgets.end(), widget ); if (find == widgets.end()) widgets.push_back(widget); } void TabList::remove(Widget* widget) { std::vector<Widget*>::iterator find = std::find( widgets.begin(), widgets.end(), widget ); if (find != widgets.end()) widgets.erase(find); } void TabList::clear() { widgets.clear(); } int TabList::getCurrent() { return current; } unsigned TabList::size() { return widgets.size(); } bool TabList::current_is_valid() { return current >= 0 && current < (int)widgets.size(); } bool TabList::previous_is_valid() { return previous >= 0 && previous < (int)widgets.size(); } Widget* TabList::getNext(bool inner) { if (widgets.size() == 0) return NULL; if (current_is_valid()) { if (inner && widgets.at(current)->getNext()) return NULL; widgets.at(current)->defocus(); } ++current; if (current >= (int)widgets.size()) current = 0; widgets.at(current)->in_focus = true; return widgets.at(current); } Widget* TabList::getPrev(bool inner) { if (widgets.size() == 0) return NULL; if (current_is_valid()) { if (inner && widgets.at(current)->getPrev()) return NULL; widgets.at(current)->defocus(); } --current; if (current <= -1) current = widgets.size()-1; widgets.at(current)->in_focus = true; return widgets.at(current); } void TabList::deactivatePrevious() { if (previous_is_valid() && previous != current) { widgets.at(previous)->deactivate(); } } void TabList::activate() { if (current_is_valid()) { widgets.at(current)->activate(); previous = current; } } void TabList::defocus() { for (unsigned i=0; i < widgets.size(); ++i) { widgets.at(i)->defocus(); } current = -1; } void TabList::logic() { if (locked) return; if (scrolltype == VERTICAL || scrolltype == TWO_DIRECTIONS) { if (inpt->pressing[DOWN] && !inpt->lock[DOWN]) { inpt->lock[DOWN] = true; getNext(); } else if (inpt->pressing[UP] && !inpt->lock[UP]) { inpt->lock[UP] = true; getPrev(); } } if (scrolltype == HORIZONTAL || scrolltype == TWO_DIRECTIONS) { if (inpt->pressing[MV_LEFT] && !inpt->lock[MV_LEFT]) { inpt->lock[MV_LEFT] = true; getPrev(false); } else if (inpt->pressing[MV_RIGHT] && !inpt->lock[MV_RIGHT]) { inpt->lock[MV_RIGHT] = true; getNext(false); } } if (inpt->pressing[ACTIVATE] && !inpt->lock[ACTIVATE]) { inpt->lock[ACTIVATE] = true; deactivatePrevious(); //Deactivate previously activated item activate(); // Activate the currently infocus item } // If mouse is clicked, defocus current tabindex item if (inpt->pressing[MAIN1] && !inpt->lock[MAIN1]) { defocus(); } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/Widget.h����������������������������������������������������������������������0000664�0000000�0000000�00000004434�12247171015�0016167�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2013 Joseph Bleau This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #pragma once #ifndef WIDGET_H #define WIDGET_H /** * Base interface all widget needs to implement */ #include "CommonIncludes.h" enum ScrollType {VERTICAL, HORIZONTAL, TWO_DIRECTIONS}; class Widget { public: Widget(); virtual ~Widget(); virtual void render(SDL_Surface *target = NULL) = 0; virtual void activate(); virtual void deactivate(); virtual void defocus(); virtual bool getNext(); // getNext and getPrev should be implemented virtual bool getPrev(); // if the widget has items internally that can be iterated bool render_to_alpha; bool in_focus; bool focusable; SDL_Rect pos; // This is the position of the button within the screen }; class TabList { private: std::vector<Widget*> widgets; int current; int previous; bool locked; bool current_is_valid(); bool previous_is_valid(); ScrollType scrolltype; int MV_LEFT; int MV_RIGHT; int ACTIVATE; public: TabList(ScrollType _scrolltype = TWO_DIRECTIONS, int _LEFT = 4/*LEFT*/, int _RIGHT = 5/*RIGHT*/, int _ACTIVATE = 1/*ACCEPT*/); ~TabList(); bool isLocked(); void lock(); void unlock(); void add(Widget* widget); // Add a widget void remove(Widget* widget); // Remove a widget void clear(); // Remove all widgets int getCurrent(); unsigned size(); Widget* getNext(bool inner = true); // Increment current selected, return widget Widget* getPrev(bool inner = true); // Decrement current selected, return widget void deactivatePrevious(); void activate(); // Fire off what happens when the user presses 'accept' void defocus(); // Call when user clicks outside of a widget, resets current void logic(); }; #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetButton.cpp��������������������������������������������������������������0000664�0000000�0000000�00000010203�12247171015�0017705�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetButton */ #include "SDL_gfxBlitFunc.h" #include "SharedResources.h" #include "WidgetButton.h" #include "WidgetTooltip.h" using namespace std; WidgetButton::WidgetButton(const std::string& _fileName) : Widget() , fileName(_fileName) , buttons(NULL) , wlabel() , color_normal(font->getColor("widget_normal")) , color_disabled(font->getColor("widget_disabled")) , tip_buf() , tip_new() , tip(new WidgetTooltip()) , label("") , tooltip("") , enabled(true) , pressed(false) , hover(false) { focusable = true; pos.x = pos.y = pos.w = pos.h = 0; loadArt(); pos.w = buttons->w; pos.h = (buttons->h / 4); //height of one button } void WidgetButton::activate() { pressed = true; } void WidgetButton::loadArt() { // load button images buttons = loadGraphicSurface(fileName); if (!buttons) { SDL_Quit(); exit(1); // or abort ?? } } bool WidgetButton::checkClick() { return checkClick(inpt->mouse.x,inpt->mouse.y); } /** * Sets and releases the "pressed" visual state of the button * If press and release, activate (return true) */ bool WidgetButton::checkClick(int x, int y) { Point mouse(x,y); // Change the hover state hover = isWithin(pos, mouse); // Check the tooltip tip_new = checkTooltip(mouse); // disabled buttons can't be clicked; if (!enabled) return false; // main button already in use, new click not allowed if (inpt->lock[MAIN1]) return false; if (inpt->lock[ACCEPT]) return false; // main click released, so the button state goes back to unpressed if (pressed && !inpt->lock[MAIN1] && !inpt->lock[ACCEPT]) { pressed = false; return true; } pressed = false; // detect new click if (inpt->pressing[MAIN1]) { if (isWithin(pos, mouse)) { inpt->lock[MAIN1] = true; pressed = true; } } return false; } void WidgetButton::render(SDL_Surface *target) { if (target == NULL) { target = screen; } SDL_Rect src; src.x = 0; src.w = pos.w; src.h = pos.h; // the "button" surface contains button variations. // choose which variation to display. if (!enabled) src.y = BUTTON_GFX_DISABLED * pos.h; else if (pressed) src.y = BUTTON_GFX_PRESSED * pos.h; else if (hover) src.y = BUTTON_GFX_HOVER * pos.h; else if(in_focus) src.y = BUTTON_GFX_HOVER * pos.h; else src.y = BUTTON_GFX_NORMAL * pos.h; // create a temporary rect so we don't modify pos SDL_Rect offset = pos; if (render_to_alpha) SDL_gfxBlitRGBA(buttons, &src, target, &offset); else SDL_BlitSurface(buttons, &src, target, &offset); wlabel.render(target); // render the tooltip // TODO move this to menu rendering if (!tip_new.isEmpty()) { if (!tip_new.compare(&tip_buf)) { tip_buf.clear(); tip_buf = tip_new; } tip->render(tip_buf, inpt->mouse, STYLE_FLOAT, target); } } /** * Create the text buffer */ void WidgetButton::refresh() { if (label != "") { int font_x = pos.x + (pos.w/2); int font_y = pos.y + (pos.h/2); if (enabled) wlabel.set(font_x, font_y, JUSTIFY_CENTER, VALIGN_CENTER, label, color_normal); else wlabel.set(font_x, font_y, JUSTIFY_CENTER, VALIGN_CENTER, label, color_disabled); } } /** * If mousing-over an item with a tooltip, return that tooltip data. * * @param mouse The x,y screen coordinates of the mouse cursor */ TooltipData WidgetButton::checkTooltip(Point mouse) { TooltipData _tip; if (isWithin(pos, mouse) && tooltip != "") { _tip.addText(tooltip); } return _tip; } WidgetButton::~WidgetButton() { SDL_FreeSurface(buttons); tip_buf.clear(); delete tip; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetButton.h����������������������������������������������������������������0000664�0000000�0000000�00000003161�12247171015�0017357�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetButton */ #pragma once #ifndef WIDGET_BUTTON_H #define WIDGET_BUTTON_H #include "CommonIncludes.h" #include "Widget.h" #include "WidgetLabel.h" #include "TooltipData.h" class WidgetTooltip; const int BUTTON_GFX_NORMAL = 0; const int BUTTON_GFX_PRESSED = 1; const int BUTTON_GFX_HOVER = 2; const int BUTTON_GFX_DISABLED = 3; class WidgetButton : public Widget { private: std::string fileName; // the path to the buttons background image SDL_Surface *buttons; WidgetLabel wlabel; SDL_Color color_normal; SDL_Color color_disabled; TooltipData tip_buf; TooltipData tip_new; WidgetTooltip *tip; TooltipData checkTooltip(Point mouse); public: WidgetButton(const std::string& _fileName); ~WidgetButton(); void activate(); void loadArt(); bool checkClick(); bool checkClick(int x, int y); void render(SDL_Surface *target = NULL); void refresh(); std::string label; std::string tooltip; bool enabled; bool pressed; bool hover; }; #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetCheckBox.cpp������������������������������������������������������������0000664�0000000�0000000�00000005122�12247171015�0020124�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2012 Clint Bellanger Copyright © 2012 davidriod This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetCheckBox */ #include "CommonIncludes.h" #include "SDL_gfxBlitFunc.h" #include "SharedResources.h" #include "WidgetCheckBox.h" #include "Widget.h" using namespace std; WidgetCheckBox::WidgetCheckBox (const string &fname) : enabled(true), cb(NULL), checked(false), pressed(false) { focusable = true; cb = loadGraphicSurface(fname, "Couldn't load image", true, false); pos.w = cb->w; pos.h = cb->h / 2; render_to_alpha = false; } void WidgetCheckBox::activate() { pressed = true; } WidgetCheckBox::~WidgetCheckBox () { SDL_FreeSurface(cb); } void WidgetCheckBox::Check () { checked = true; } void WidgetCheckBox::unCheck () { checked = false; } bool WidgetCheckBox::checkClick() { return checkClick(inpt->mouse.x,inpt->mouse.y); } bool WidgetCheckBox::checkClick (int x, int y) { if (!enabled) return false; Point mouse(x,y); // main button already in use, new click not allowed if (inpt->lock[MAIN1]) return false; if (inpt->lock[ACCEPT]) return false; if (pressed && !inpt->lock[MAIN1] && !inpt->lock[ACCEPT]) { // this is a button release pressed = false; checked = !checked; return true; } if (inpt->pressing[MAIN1]) { if (isWithin(pos, mouse)) { pressed = true; inpt->lock[MAIN1] = true; } } return false; } bool WidgetCheckBox::isChecked () const { return checked; } void WidgetCheckBox::render (SDL_Surface *target) { if (target == NULL) { target = screen; } SDL_Rect src; src.x = 0; src.y = checked ? pos.h : 0; src.h = pos.h; src.w = pos.w; if (render_to_alpha) SDL_gfxBlitRGBA(cb, &src, target, &pos); else SDL_BlitSurface(cb, &src, target, &pos); if (in_focus) { Point topLeft; Point bottomRight; Uint32 color; topLeft.x = pos.x; topLeft.y = pos.y; bottomRight.x = pos.x + pos.w; bottomRight.y = pos.y + pos.h; color = SDL_MapRGB(target->format, 255,248,220); drawRectangle(target, topLeft, bottomRight, color); } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetCheckBox.h��������������������������������������������������������������0000664�0000000�0000000�00000002227�12247171015�0017574�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2012 Clint Bellanger Copyright © 2012 davidriod This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetCheckBox */ #pragma once #ifndef WIDGET_CHECKBOX_H #define WIDGET_CHECKBOX_H class Widget; class WidgetCheckBox : public Widget { public: WidgetCheckBox (const std::string &fname); ~WidgetCheckBox (); void activate(); void Check (); void unCheck (); bool checkClick (); bool checkClick (int x, int y); bool isChecked () const; void render (SDL_Surface *target = NULL); bool enabled; private: SDL_Surface * cb; bool checked; bool pressed; }; #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetInput.cpp���������������������������������������������������������������0000664�0000000�0000000�00000007536�12247171015�0017550�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 kitano Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "WidgetInput.h" #include "SharedResources.h" #include "Settings.h" #include "SDL_gfxBlitFunc.h" using namespace std; WidgetInput::WidgetInput() { enabled = true; inFocus = false; pressed = false; hover = false; max_characters = 20; loadGraphics("images/menus/input.png"); // position pos.w = background->w; pos.h = background->h/2; cursor_frame = 0; render_to_alpha = false; color_normal = font->getColor("widget_normal"); } void WidgetInput::loadGraphics(const string& filename) { // load input background image background = loadGraphicSurface(filename, "Couldn't load image", true); } void WidgetInput::logic() { if (logic(inpt->mouse.x,inpt->mouse.y)) return; } bool WidgetInput::logic(int x, int y) { Point mouse(x, y); // Change the hover state hover = isWithin(pos, mouse); if (checkClick()) { inFocus = true; } // if clicking elsewhere unfocus the text box if (inpt->pressing[MAIN1]) { if (!isWithin(pos, inpt->mouse)) { inFocus = false; } } if (inFocus) { if (inpt->inkeys != "") { // handle text input text += inpt->inkeys; if (text.length() > max_characters) { text = text.substr(0, max_characters); } } // handle backspaces if (!inpt->lock[DEL] && inpt->pressing[DEL]) { inpt->lock[DEL] = true; // remove utf-8 character int n = text.length()-1; while (n > 0 && ((text[n] & 0xc0) == 0x80) ) n--; text = text.substr(0, n); } // animate cursor // cursor visible one second, invisible the next cursor_frame++; if (cursor_frame == MAX_FRAMES_PER_SEC+MAX_FRAMES_PER_SEC) cursor_frame = 0; } return true; } void WidgetInput::render(SDL_Surface *target) { if (target == NULL) { target = screen; } SDL_Rect src; src.x = 0; src.y = 0; src.w = pos.w; src.h = pos.h; if (!inFocus) src.y = 0; else src.y = pos.h; if (render_to_alpha) SDL_gfxBlitRGBA(background, &src, target, &pos); else SDL_BlitSurface(background, &src, target, &pos); font->setFont("font_regular"); if (!inFocus) { font->render(text, font_pos.x, font_pos.y, JUSTIFY_LEFT, target, color_normal); } else { if (cursor_frame < MAX_FRAMES_PER_SEC) { font->renderShadowed(text + "|", font_pos.x, font_pos.y, JUSTIFY_LEFT, target, color_normal); } else { font->renderShadowed(text, font_pos.x, font_pos.y, JUSTIFY_LEFT, target, color_normal); } } } void WidgetInput::setPosition(int x, int y) { pos.x = x; pos.y = y; font->setFont("font_regular"); font_pos.x = pos.x + (font->getFontHeight()/2); font_pos.y = pos.y + (pos.h/2) - (font->getFontHeight()/2); } bool WidgetInput::checkClick() { // disabled buttons can't be clicked; if (!enabled) return false; // main button already in use, new click not allowed if (inpt->lock[MAIN1]) return false; // main click released, so the button state goes back to unpressed if (pressed && !inpt->lock[MAIN1]) { pressed = false; if (isWithin(pos, inpt->mouse)) { // activate upon release return true; } } pressed = false; // detect new click if (inpt->pressing[MAIN1]) { if (isWithin(pos, inpt->mouse)) { inpt->lock[MAIN1] = true; pressed = true; } } return false; } WidgetInput::~WidgetInput() { SDL_FreeSurface(background); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetInput.h�����������������������������������������������������������������0000664�0000000�0000000�00000003011�12247171015�0017175�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 kitano This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetInput * * A simple text box with a label above it. * It has two images - one for focused and one for unfocused. */ #pragma once #ifndef WIDGETINPUT_H #define WIDGETINPUT_H #include "CommonIncludes.h" #include "Utils.h" #include "Widget.h" class WidgetInput : public Widget { protected: void loadGraphics(const std::string& filename); SDL_Surface *background; bool enabled; bool pressed; bool hover; std::string text; // the text that has been typed into the box unsigned int max_characters; int cursor_frame; Point font_pos; SDL_Color color_normal; public: WidgetInput(); ~WidgetInput(); void logic(); bool logic(int x, int y); void render(SDL_Surface *target = NULL); bool checkClick(); std::string getText() { return text; } void setText(std::string _text) { text = _text; } void setPosition(int x, int y); bool inFocus; }; #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetLabel.cpp���������������������������������������������������������������0000664�0000000�0000000�00000012407�12247171015�0017461�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetLabel * * A simple text display for menus */ #include "WidgetLabel.h" #include "SharedResources.h" #include "SDL_gfxBlitFunc.h" #include "UtilsParsing.h" using namespace std; LabelInfo::LabelInfo() : x(0), y(0), justify(JUSTIFY_LEFT), valign(VALIGN_TOP), hidden(false), font_style("font_regular") { } /** * This is used in menus (e.g. MenuInventory) when parsing their config files */ LabelInfo eatLabelInfo(string val) { LabelInfo info; string justify,valign,style; std::string tmp = eatFirstString(val,','); if (tmp == "hidden") { info.hidden = true; } else { info.hidden = false; info.x = toInt(tmp); info.y = eatFirstInt(val,','); justify = eatFirstString(val,','); valign = eatFirstString(val,','); style = eatFirstString(val,','); if (justify == "left") info.justify = JUSTIFY_LEFT; else if (justify == "center") info.justify = JUSTIFY_CENTER; else if (justify == "right") info.justify = JUSTIFY_RIGHT; if (valign == "top") info.valign = VALIGN_TOP; else if (valign == "center") info.valign = VALIGN_CENTER; else if (valign == "bottom") info.valign = VALIGN_BOTTOM; if (style != "") info.font_style = style; } return info; } WidgetLabel::WidgetLabel() : text("") , color(font->getColor("widget_normal")) , x_origin(0) , y_origin(0) , justify(JUSTIFY_LEFT) , valign(VALIGN_TOP) , font_style("font_regular") , text_buffer(NULL) { bounds.x = bounds.y = 0; bounds.w = bounds.h = 0; render_to_alpha = false; } /** * Draw the buffered string surface to the screen */ void WidgetLabel::render(SDL_Surface *target) { if (target == NULL) { target = screen; } SDL_Rect dest; dest.x = bounds.x; dest.y = bounds.y; dest.w = bounds.w; dest.h = bounds.h; if (text_buffer != NULL) { if (render_to_alpha) SDL_gfxBlitRGBA(text_buffer, NULL, target, &dest); else SDL_BlitSurface(text_buffer, NULL, target, &dest); } } void WidgetLabel::set(int _x, int _y, int _justify, int _valign, const string& _text, SDL_Color _color) { set(_x, _y, _justify, _valign, _text, _color, "font_regular"); } /** * A shortcut function to set all attributes simultaneously. */ void WidgetLabel::set(int _x, int _y, int _justify, int _valign, const string& _text, SDL_Color _color, std::string _font) { bool changed = false; if (justify != _justify) { justify = _justify; changed = true; } if (valign != _valign) { valign = _valign; changed = true; } if (text != _text) { text = _text; changed = true; } if (color.r != _color.r || color.g != _color.g || color.b != _color.b) { color = _color; changed = true; } if (x_origin != _x) { x_origin = _x; changed = true; } if (y_origin != _y) { y_origin = _y; changed = true; } if (font_style != _font) { font_style = _font; changed = true; } if (changed) { applyOffsets(); refresh(); } } /** * Set initial X position of label. */ void WidgetLabel::setX(int _x) { if (x_origin != _x) { x_origin = _x; applyOffsets(); refresh(); } } /** * Set initial Y position of label. */ void WidgetLabel::setY(int _y) { if (y_origin != _y) { y_origin = _y; applyOffsets(); refresh(); } } /** * Get X position of label. */ int WidgetLabel::getX() { return x_origin; } /** * Get Y position of label. */ int WidgetLabel::getY() { return y_origin; } /** * Set justify value. */ void WidgetLabel::setJustify(int _justify) { if (justify != _justify) { justify = _justify; applyOffsets(); refresh(); } } /** * Apply horizontal justify and vertical alignment to label position */ void WidgetLabel::applyOffsets() { font->setFont(font_style); bounds.w = font->calc_width(text); bounds.h = font->getFontHeight(); // apply JUSTIFY if (justify == JUSTIFY_LEFT) bounds.x = x_origin; else if (justify == JUSTIFY_RIGHT) bounds.x = x_origin - bounds.w; else if (justify == JUSTIFY_CENTER) bounds.x = x_origin - bounds.w/2; // apply VALIGN if (valign == VALIGN_TOP) { bounds.y = y_origin; } else if (valign == VALIGN_BOTTOM) { bounds.y = y_origin - bounds.h;; } else if (valign == VALIGN_CENTER) { bounds.y = y_origin - bounds.h/2; } } /** * Update the label text only */ void WidgetLabel::set(const string& _text) { if (text != _text) { this->text = _text; applyOffsets(); refresh(); } } /** * We buffer the rendered text instead of calculating it each frame * This function refreshes the buffer. */ void WidgetLabel::refresh() { SDL_FreeSurface(text_buffer); text_buffer = createAlphaSurface(bounds.w, bounds.h); font->setFont(font_style); font->renderShadowed(text, 0, 0, JUSTIFY_LEFT, text_buffer, color); } WidgetLabel::~WidgetLabel() { SDL_FreeSurface(text_buffer); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetLabel.h�����������������������������������������������������������������0000664�0000000�0000000�00000003554�12247171015�0017131�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetLabel * * A simple text display for menus. * This is preferred to directly displaying text because it helps handle positioning */ #pragma once #ifndef WIDGET_LABEL_H #define WIDGET_LABEL_H #include "CommonIncludes.h" #include "Widget.h" const int VALIGN_CENTER = 0; const int VALIGN_TOP = 1; const int VALIGN_BOTTOM = 2; class LabelInfo { public: int x,y; int justify,valign; bool hidden; std::string font_style; LabelInfo(); }; LabelInfo eatLabelInfo(std::string val); class WidgetLabel : public Widget { private: void refresh(); void applyOffsets(); std::string text; SDL_Color color; int x_origin; int y_origin; int justify; int valign; std::string font_style; SDL_Surface *text_buffer; public: WidgetLabel(); ~WidgetLabel(); void render(SDL_Surface *target = NULL); void set(int _x, int _y, int _justify, int _valign, const std::string& _text, SDL_Color _color); void set(int _x, int _y, int _justify, int _valign, const std::string& _text, SDL_Color _color, std::string _font); void setX(int _x); void setY(int _y); int getX(); int getY(); void setJustify(int _justify); void set(const std::string& _text); std::string get() {return text;} SDL_Rect bounds; }; #endif ����������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetListBox.cpp�������������������������������������������������������������0000664�0000000�0000000�00000025551�12247171015�0020032�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Justin Jacobs This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetListBox */ #include "SDL_gfxBlitFunc.h" #include "SharedResources.h" #include "WidgetLabel.h" #include "WidgetListBox.h" #include "WidgetScrollBar.h" #include "WidgetTooltip.h" using namespace std; WidgetListBox::WidgetListBox(int amount, int height, const std::string& _fileName) : Widget() , fileName(_fileName) , list_amount(amount) , list_height(height) , cursor(0) , has_scroll_bar(false) , non_empty_slots(0) , any_selected(false) , values(new std::string[list_amount]) , tooltips(new std::string[list_amount]) , vlabels(new WidgetLabel[list_height]) , rows(new SDL_Rect[list_height]) , tip( new WidgetTooltip()) , scrollbar(new WidgetScrollBar("images/menus/buttons/scrollbar_default.png")) , color_normal(font->getColor("widget_normal")) , color_disabled(font->getColor("widget_disabled")) , pos_scroll() , pressed(false) , selected(new bool[list_amount]) , multi_select(false) , can_deselect(true) , can_select(true) , scrollbar_offset(0) { // load ListBox images listboxs = loadGraphicSurface(fileName, "Couldn't load image", true); click = NULL; for (int i=0; i<list_amount; i++) { selected[i] = false; values[i] = ""; } pos.w = listboxs->w; pos.h = (listboxs->h / 3); // height of one item } bool WidgetListBox::checkClick() { return checkClick(inpt->mouse.x,inpt->mouse.y); } /** * Sets and releases the "pressed" visual state of the ListBox * If press and release, activate (return true) */ bool WidgetListBox::checkClick(int x, int y) { Point mouse(x, y); refresh(); // check scroll wheel SDL_Rect scroll_area; scroll_area.x = rows[0].x; scroll_area.y = rows[0].y; scroll_area.w = rows[0].w; scroll_area.h = rows[0].h * list_height; if (isWithin(scroll_area,mouse)) { if (inpt->scroll_up) { scrollUp(); inpt->resetScroll(); } if (inpt->scroll_down) { scrollDown(); inpt->resetScroll(); } } else { inpt->resetScroll(); } // check ScrollBar clicks if (has_scroll_bar) { switch (scrollbar->checkClick(mouse.x,mouse.y)) { case 1: scrollUp(); break; case 2: scrollDown(); break; case 3: cursor = scrollbar->getValue(); refresh(); break; default: break; } } // main ListBox already in use, new click not allowed if (inpt->lock[MAIN1]) return false; // main click released, so the ListBox state goes back to unpressed if (pressed && !inpt->lock[MAIN1] && can_select) { pressed = false; for(int i=0; i<list_height; i++) { if (i<list_amount) { if (isWithin(rows[i], mouse) && values[i+cursor] != "") { // deselect other options if multi-select is disabled if (!multi_select) { for (int j=0; j<list_amount; j++) { if (j!=i+cursor) selected[j] = false; } } // activate upon release if (selected[i+cursor]) { if (can_deselect) selected[i+cursor] = false; } else { selected[i+cursor] = true; } refresh(); return true; } } } } pressed = false; // detect new click if (inpt->pressing[MAIN1]) { for (int i=0; i<list_height; i++) { if (isWithin(rows[i], mouse)) { inpt->lock[MAIN1] = true; pressed = true; } } } return false; } /** * If mousing-over an item with a tooltip, return that tooltip data. * * @param mouse The x,y screen coordinates of the mouse cursor */ TooltipData WidgetListBox::checkTooltip(Point mouse) { TooltipData _tip; for(int i=0; i<list_height; i++) { if (i<list_amount) { if (isWithin(rows[i], mouse) && tooltips[i+cursor] != "") { _tip.addText(tooltips[i+cursor]); break; } } } return _tip; } /** * Set the value and tooltip of the first available slot */ void WidgetListBox::append(std::string value, std::string tooltip) { for (int i=0; i<list_amount; i++) { if (values[i] == "") { values[i] = value; tooltips[i] = tooltip; refresh(); return; } } } /** * Set a specific slot's value and tooltip */ void WidgetListBox::set(int index, std::string value, std::string tooltip) { if (index > list_amount || index < 0) return; values[index] = value; tooltips[index] = tooltip; } /** * Clear a slot at a specified index, shifting the other items accordingly */ void WidgetListBox::remove(int index) { for (int i=index; i<list_amount; i++) { if (i==list_amount-1) { selected[i] = false; values[i] = ""; tooltips[i] = ""; } else { selected[i] = selected[i+1]; values[i] = values[i+1]; tooltips[i] = tooltips[i+1]; } } scrollUp(); refresh(); } /* * Clear the list */ void WidgetListBox::clear() { for (int i=0; i<list_amount; i++) { selected[i] = false; values[i] = ""; tooltips[i] = ""; } refresh(); } /* * Move an item up on the list */ void WidgetListBox::shiftUp() { any_selected = false; if (!selected[0]) { for (int i=1; i < non_empty_slots; i++) { if (selected[i]) { any_selected = true; bool tmp_selected = selected[i]; std::string tmp_value = values[i]; std::string tmp_tooltip = tooltips[i]; selected[i] = selected[i-1]; values[i] = values[i-1]; tooltips[i] = tooltips[i-1]; selected[i-1] = tmp_selected; values[i-1] = tmp_value; tooltips[i-1] = tmp_tooltip; } } if (any_selected) { scrollUp(); } } } /* * Move an item down on the list */ void WidgetListBox::shiftDown() { any_selected = false; if (!selected[non_empty_slots-1]) { for (int i=non_empty_slots-2; i >= 0; i--) { if (selected[i]) { any_selected = true; bool tmp_selected = selected[i]; std::string tmp_value = values[i]; std::string tmp_tooltip = tooltips[i]; selected[i] = selected[i+1]; values[i] = values[i+1]; tooltips[i] = tooltips[i+1]; selected[i+1] = tmp_selected; values[i+1] = tmp_value; tooltips[i+1] = tmp_tooltip; } } if (any_selected) { scrollDown(); } } } int WidgetListBox::getSelected() { // return the first selected value for (int i=0; i<non_empty_slots; i++) { if (selected[i]) return i; } return -1; // nothing is selected } std::string WidgetListBox::getValue() { for (int i=0; i<non_empty_slots; i++) { if (selected[i]) return values[i]; } return ""; } /* * Get the item name at a specific index */ std::string WidgetListBox::getValue(int index) { return values[index]; } /* * Get the item tooltip at a specific index */ std::string WidgetListBox::getTooltip(int index) { return tooltips[index]; } /* * Get the amount of ListBox items */ int WidgetListBox::getSize() { return list_amount; } /* * Shift the viewing area up */ void WidgetListBox::scrollUp() { if (cursor > 0) cursor -= 1; refresh(); } /* * Shift the viewing area down */ void WidgetListBox::scrollDown() { if (cursor+list_height < non_empty_slots) cursor += 1; refresh(); } void WidgetListBox::render(SDL_Surface *target) { if (target == NULL) { target = screen; } SDL_Rect src; src.x = 0; src.w = pos.w; src.h = pos.h; for(int i=0; i<list_height; i++) { if(i==0) src.y = 0; else if(i==list_height-1) src.y = pos.h*2; else src.y = pos.h; if (render_to_alpha) SDL_gfxBlitRGBA(listboxs, &src, target, &rows[i]); else SDL_BlitSurface(listboxs, &src, target, &rows[i]); if (i<list_amount) { vlabels[i].render(target); } } if (in_focus) { Point topLeft; Point bottomRight; Uint32 color; topLeft.x = rows[0].x; topLeft.y = rows[0].y; bottomRight.x = rows[list_height - 1].x + rows[0].w; bottomRight.y = rows[list_height - 1].y + rows[0].h; color = SDL_MapRGB(target->format, 255,248,220); drawRectangle(target, topLeft, bottomRight, color); } if (has_scroll_bar) scrollbar->render(target); } /** * Create the text buffer * Also, toggle the scrollbar based on the size of the list */ void WidgetListBox::refresh() { std::string temp; int right_margin = 0; // Get the number of slots that have content non_empty_slots = 0; for (int i=0; i<list_amount; i++) { if (values[i] != "") non_empty_slots = i+1; } // Update the scrollbar if (non_empty_slots > list_height) { has_scroll_bar = true; pos_scroll.x = pos.x+pos.w-scrollbar->pos_up.w-scrollbar_offset; pos_scroll.y = pos.y+scrollbar_offset; pos_scroll.w = scrollbar->pos_up.w; pos_scroll.h = (pos.h*list_height)-scrollbar->pos_down.h-(scrollbar_offset*2); scrollbar->refresh(pos_scroll.x, pos_scroll.y, pos_scroll.h, cursor, non_empty_slots-list_height); right_margin = scrollbar->pos_knob.w + 8; } else { has_scroll_bar = false; right_margin = 8; } // Update each row's hitbox and label for(int i=0; i<list_height; i++) { rows[i].x = pos.x; rows[i].y = (pos.h*i)+pos.y; if (has_scroll_bar) { rows[i].w = pos.w - pos_scroll.w; } else { rows[i].w = pos.w; } rows[i].h = pos.h; int font_x = rows[i].x + 8; int font_y = rows[i].y + (rows[i].h/2); if (i<list_amount) { // gets the maxiumum value length that can fit in the listbox // maybe there is a better way to do this? unsigned int max_length = (unsigned int)(pos.w-right_margin)/font->calc_width("X"); if (font->calc_width(values[i+cursor]) > pos.w-right_margin) { temp = values[i+cursor].substr(0,max_length); temp.append("..."); } else { temp = values[i+cursor]; } if(selected[i+cursor]) { vlabels[i].set(font_x, font_y, JUSTIFY_LEFT, VALIGN_CENTER, temp, color_normal); } else { vlabels[i].set(font_x, font_y, JUSTIFY_LEFT, VALIGN_CENTER, temp, color_disabled); } } } } bool WidgetListBox::getNext() { if (list_amount < 1) return false; int sel = getSelected(); if (sel != -1) selected[sel] = false; if(sel == list_amount-1) { selected[0] = true; while (getSelected() < cursor) scrollUp(); } else { selected[sel+1] = true; while (getSelected() > cursor+list_height-1) scrollDown(); } return true; } bool WidgetListBox::getPrev() { if (list_amount < 1) return false; int sel = getSelected(); if (sel == -1) sel = 0; selected[sel] = false; if(sel == 0) { selected[list_amount-1] = true; while (getSelected() > cursor+list_height-1) scrollDown(); } else { selected[sel-1] = true; while (getSelected() < cursor) scrollUp(); } return true; } WidgetListBox::~WidgetListBox() { SDL_FreeSurface(listboxs); delete[] values; delete[] tooltips; delete[] vlabels; delete[] rows; delete[] selected; delete tip; delete scrollbar; } �������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetListBox.h���������������������������������������������������������������0000664�0000000�0000000�00000004211�12247171015�0017465�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Justin Jacobs This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetListBox */ #pragma once #ifndef WIDGET_ListBox_H #define WIDGET_ListBox_H #include "CommonIncludes.h" #include "Widget.h" #include "TooltipData.h" class WidgetLabel; class WidgetScrollBar; class WidgetTooltip; class WidgetListBox : public Widget { private: std::string fileName; // the path to the ListBoxs background image SDL_Surface *listboxs; Mix_Chunk *click; int list_amount; int list_height; int cursor; bool has_scroll_bar; int non_empty_slots; bool any_selected; std::string *values; std::string *tooltips; WidgetLabel *vlabels; SDL_Rect *rows; WidgetTooltip *tip; WidgetScrollBar *scrollbar; SDL_Color color_normal; SDL_Color color_disabled; public: WidgetListBox(int amount, int height, const std::string& _fileName); ~WidgetListBox(); bool checkClick(); bool checkClick(int x, int y); TooltipData checkTooltip(Point mouse); void append(std::string value, std::string tooltip); void set(int index, std::string value, std::string tooltip); void remove(int index); void clear(); void shiftUp(); void shiftDown(); int getSelected(); std::string getValue(); std::string getValue(int index); std::string getTooltip(int index); int getSize(); void scrollUp(); void scrollDown(); void render(SDL_Surface *target = NULL); void refresh(); bool getNext(); bool getPrev(); SDL_Rect pos_scroll; bool pressed; bool *selected; bool multi_select; bool can_deselect; bool can_select; int scrollbar_offset; }; #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetScrollBar.cpp�����������������������������������������������������������0000664�0000000�0000000�00000010330�12247171015�0020316�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Justin Jacobs This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetScrollBar */ #include "WidgetScrollBar.h" #include "SharedResources.h" #include "SDL_gfxBlitFunc.h" using namespace std; WidgetScrollBar::WidgetScrollBar(const std::string& _fileName) : Widget() , fileName(_fileName) , value(0) , bar_height(0) , maximum(0) , pressed_up(false) , pressed_down(false) , pressed_knob(false) { scrollbars = NULL; click = NULL; loadArt(); pos_up.w = pos_down.w = pos_knob.w = scrollbars->w; pos_up.h = pos_down.h = pos_knob.h = (scrollbars->h / 5); //height of one button } void WidgetScrollBar::loadArt() { scrollbars = loadGraphicSurface(fileName, "Couldn't load image", true); } int WidgetScrollBar::checkClick() { int r = checkClick(inpt->mouse.x,inpt->mouse.y); return r; } /** * Sets and releases the "pressed" visual state of the ScrollBar * If press and release, activate (return 1 for up, 2 for down) */ int WidgetScrollBar::checkClick(int x, int y) { Point mouse = Point(x,y); // main ScrollBar already in use, new click not allowed //if (inpt->lock[MAIN1]) return 0; // main click released, so the ScrollBar state goes back to unpressed if (pressed_up && !inpt->lock[MAIN1]) { pressed_up = false; if (isWithin(pos_up, mouse)) { // activate upon release return 1; } } if (pressed_down && !inpt->lock[MAIN1]) { pressed_down = false; if (isWithin(pos_down, mouse)) { // activate upon release return 2; } } if (pressed_knob) { if (!inpt->lock[MAIN1]) { pressed_knob = false; } int tmp = mouse.y - pos_up.y - pos_up.h; pos_knob.y = pos_up.y + tmp; if (bar_height < 1) bar_height = 1; value = (tmp * maximum)/bar_height; set(); return 3; } pressed_up = false; pressed_down = false; pressed_knob = false; // detect new click if (inpt->pressing[MAIN1]) { if (isWithin(pos_up, mouse)) { inpt->lock[MAIN1] = true; pressed_up = true; } else if (isWithin(pos_down, mouse)) { inpt->lock[MAIN1] = true; pressed_down = true; } else if (isWithin(pos_knob, mouse)) { inpt->lock[MAIN1] = true; pressed_knob = true; } } return 0; } void WidgetScrollBar::set() { if (maximum < 1) maximum = 1; value = max(0, min(maximum, value)); pos_knob.y = pos_up.y + pos_up.h + (value * (bar_height - pos_up.h) / maximum); } int WidgetScrollBar::getValue() { return value; } void WidgetScrollBar::render(SDL_Surface *target) { if (target == NULL) { target = screen; } SDL_Rect src_up, src_down, src_knob; src_up.x = 0; src_up.w = pos_up.w; src_up.h = pos_up.h; src_down.x = 0; src_down.w = pos_down.w; src_down.h = pos_down.h; src_knob.x = 0; src_knob.y = pos_knob.h * 4; src_knob.w = pos_knob.w; src_knob.h = pos_knob.h; if (pressed_up) src_up.y = pos_up.h; else src_up.y = 0; if (pressed_down) src_down.y = pos_down.h*3; else src_down.y = pos_down.h*2; if (render_to_alpha) { SDL_gfxBlitRGBA(scrollbars, &src_up, target, &pos_up); SDL_gfxBlitRGBA(scrollbars, &src_down, target, &pos_down); SDL_gfxBlitRGBA(scrollbars, &src_knob, target, &pos_knob); } else { SDL_BlitSurface(scrollbars, &src_up, target, &pos_up); SDL_BlitSurface(scrollbars, &src_down, target, &pos_down); SDL_BlitSurface(scrollbars, &src_knob, target, &pos_knob); } } /** * Updates the scrollbar's location */ void WidgetScrollBar::refresh(int x, int y, int h, int val, int max) { maximum = max; value = val; pos_up.x = pos_down.x = pos_knob.x = x; pos_up.y = y; pos_down.y = y+h; bar_height = pos_down.y-pos_down.h-pos_down.h-pos_up.y+pos_up.h; set(); } WidgetScrollBar::~WidgetScrollBar() { SDL_FreeSurface(scrollbars); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetScrollBar.h�������������������������������������������������������������0000664�0000000�0000000�00000002661�12247171015�0017773�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Justin Jacobs This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetScrollBar */ #pragma once #ifndef WIDGET_ScrollBar_H #define WIDGET_ScrollBar_H #include "CommonIncludes.h" #include "Widget.h" class WidgetScrollBar : public Widget { private: std::string fileName; // the path to the ScrollBars background image SDL_Surface *scrollbars; Mix_Chunk *click; int value; int bar_height; int maximum; public: WidgetScrollBar(const std::string& _fileName); ~WidgetScrollBar(); void loadArt(); int checkClick(); int checkClick(int x, int y); void set(); int getValue(); void render(SDL_Surface *target = NULL); void refresh(int x, int y, int h, int val, int max); SDL_Rect pos_up; SDL_Rect pos_down; SDL_Rect pos_knob; bool pressed_up; bool pressed_down; bool pressed_knob; }; #endif �������������������������������������������������������������������������������flare-engine-0.19/src/WidgetScrollBox.cpp�����������������������������������������������������������0000664�0000000�0000000�00000013673�12247171015�0020357�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Justin Jacobs This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetScrollBox */ #include "Settings.h" #include "WidgetScrollBox.h" #include "SDL_gfxBlitFunc.h" using namespace std; WidgetScrollBox::WidgetScrollBox(int width, int height) { pos.x = pos.y = 0; pos.w = width; pos.h = height; cursor = 0; bg.r = bg.g = bg.b = 0; contents = NULL; currentChild = -1; scrollbar = new WidgetScrollBar("images/menus/buttons/scrollbar_default.png"); update = true; render_to_alpha = false; transparent = true; line_height = 20; resize(height); tablist = TabList(VERTICAL); } WidgetScrollBox::~WidgetScrollBox() { if (contents != NULL) SDL_FreeSurface(contents); delete scrollbar; } void WidgetScrollBox::addChildWidget(Widget* child) { std::vector<Widget*>::iterator find = std::find( children.begin(), children.end(), child); if (find == children.end()) { children.push_back(child); tablist.add(child); } } void WidgetScrollBox::scroll(int amount) { cursor += amount; if (cursor < 0) { cursor = 0; } else if (cursor > contents->h-pos.h) { cursor = contents->h-pos.h; } refresh(); } void WidgetScrollBox::scrollTo(int amount) { cursor = amount; if (cursor < 0) { cursor = 0; } else if (cursor > contents->h-pos.h) { cursor = contents->h-pos.h; } refresh(); } void WidgetScrollBox::scrollDown() { scroll(line_height); } void WidgetScrollBox::scrollUp() { scroll(-line_height); } Point WidgetScrollBox::input_assist(Point mouse) { Point new_mouse; if (isWithin(pos,mouse)) { new_mouse.x = mouse.x-pos.x; new_mouse.y = mouse.y-pos.y+cursor; } else { new_mouse.x = -1; new_mouse.y = -1; } return new_mouse; } void WidgetScrollBox::logic() { logic(inpt->mouse.x,inpt->mouse.y); if (NO_MOUSE) { tablist.logic(); } } void WidgetScrollBox::logic(int x, int y) { Point mouse(x, y); if (isWithin(pos,mouse)) { if (inpt->scroll_up) { scrollUp(); inpt->resetScroll(); } if (inpt->scroll_down) { scrollDown(); inpt->resetScroll(); } } else { inpt->resetScroll(); } // check ScrollBar clicks if (contents->h > pos.h) { switch (scrollbar->checkClick(mouse.x,mouse.y)) { case 1: scrollUp(); break; case 2: scrollDown(); break; case 3: cursor = scrollbar->getValue(); break; default: break; } } } void WidgetScrollBox::resize(int h) { if (contents != NULL) SDL_FreeSurface(contents); if (pos.h > h) h = pos.h; contents = createAlphaSurface(pos.w,h); if (!transparent) { SDL_FillRect(contents,NULL,SDL_MapRGB(contents->format,bg.r,bg.g,bg.b)); SDL_SetAlpha(contents, 0, 0); } cursor = 0; refresh(); } void WidgetScrollBox::refresh() { if (update) { int h = pos.h; if (contents != NULL) { h = contents->h; SDL_FreeSurface(contents); } contents = createAlphaSurface(pos.w,h); if (!transparent) { SDL_FillRect(contents,NULL,SDL_MapRGB(contents->format,bg.r,bg.g,bg.b)); SDL_SetAlpha(contents, 0, 0); } } scrollbar->refresh(pos.x+pos.w, pos.y, pos.h-scrollbar->pos_down.h, cursor, contents->h-pos.h-scrollbar->pos_knob.h); } void WidgetScrollBox::render(SDL_Surface *target) { if (target == NULL) { target = screen; } for (unsigned i = 0; i < children.size(); i++) { children[i]->render(contents); } SDL_Rect src,dest; dest = pos; src.x = 0; src.y = cursor; src.w = contents->w; src.h = pos.h; if (render_to_alpha) SDL_gfxBlitRGBA(contents, &src, target, &dest); else SDL_BlitSurface(contents, &src, target, &dest); if (contents->h > pos.h) scrollbar->render(target); update = false; if (in_focus) { Point topLeft; Point bottomRight; Uint32 color; topLeft.x = dest.x; topLeft.y = dest.y; bottomRight.x = dest.x + dest.w; bottomRight.y = dest.y + dest.h; color = SDL_MapRGB(target->format, 255,248,220); drawRectangle(target, topLeft, bottomRight, color); } } bool WidgetScrollBox::getNext() { if (children.size() == 0) { scrollDown(); return true; } if (currentChild != -1) children[currentChild]->in_focus = false; currentChild+=1; currentChild = ((unsigned)currentChild == children.size()) ? 0 : currentChild; if (children[currentChild]->pos.y > (cursor + pos.h) || (children[currentChild]->pos.y + children[currentChild]->pos.h) > (cursor + pos.h)) { scrollTo(children[currentChild]->pos.y+children[currentChild]->pos.h-pos.h); } if (children[currentChild]->pos.y < cursor || (children[currentChild]->pos.y + children[currentChild]->pos.h) < cursor) { scrollTo(children[currentChild]->pos.y); } children[currentChild]->in_focus = true; return true; } bool WidgetScrollBox::getPrev() { if (children.size() == 0) { scrollUp(); return true; } if (currentChild != -1) children[currentChild]->in_focus = false; currentChild-=1; currentChild = (currentChild < 0) ? children.size() - 1 : currentChild; if (children[currentChild]->pos.y > (cursor + pos.h) || (children[currentChild]->pos.y + children[currentChild]->pos.h) > (cursor + pos.h)) { scrollTo(children[currentChild]->pos.y+children[currentChild]->pos.h-pos.h); } if (children[currentChild]->pos.y < cursor || (children[currentChild]->pos.y + children[currentChild]->pos.h) < cursor) { scrollTo(children[currentChild]->pos.y); } children[currentChild]->in_focus = true; return true; } void WidgetScrollBox::activate() { if (currentChild != -1) children[currentChild]->activate(); } ���������������������������������������������������������������������flare-engine-0.19/src/WidgetScrollBox.h�������������������������������������������������������������0000664�0000000�0000000�00000003042�12247171015�0020011�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Justin Jacobs This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetScrollBox */ #pragma once #ifndef WIDGET_SCROLLBOX_H #define WIDGET_SCROLLBOX_H #include "SharedResources.h" #include "Widget.h" #include "WidgetScrollBar.h" class Widget; class WidgetScrollBox : public Widget { public: WidgetScrollBox (int width, int height); ~WidgetScrollBox (); void addChildWidget(Widget* child); Point input_assist(Point mouse); void logic(); void logic(int x, int y); void resize(int h); void refresh(); void render(SDL_Surface *target = NULL); SDL_Surface * contents; bool update; SDL_Color bg; bool transparent; int line_height; TabList tablist; bool getNext(); bool getPrev(); void activate(); private: void scroll(int amount); void scrollTo(int amount); void scrollDown(); void scrollUp(); std::vector<Widget*> children; int currentChild; int cursor; WidgetScrollBar * scrollbar; }; #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetSlider.cpp��������������������������������������������������������������0000664�0000000�0000000�00000010110�12247171015�0017651�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2012 Justin Jacobs This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetSlider */ #include "CommonIncludes.h" #include "SDL_gfxBlitFunc.h" #include "SharedResources.h" #include "UtilsDebug.h" #include "Widget.h" #include "WidgetSlider.h" #include <assert.h> using namespace std; WidgetSlider::WidgetSlider (const string & fname) : enabled(true) , sl(NULL) , pressed(false) , minimum(0) , maximum(0) , value(0) { sl = loadGraphicSurface(fname); if (!sl) { SDL_Quit(); exit(1); } pos.w = sl->w; pos.h = sl->h / 2; pos_knob.w = sl->w / 8; pos_knob.h = sl->h / 2; render_to_alpha = false; } WidgetSlider::~WidgetSlider () { SDL_FreeSurface(sl); } bool WidgetSlider::checkClick() { if (!enabled) return false; return checkClick(inpt->mouse.x,inpt->mouse.y); } bool WidgetSlider::checkClick (int x, int y) { if (!enabled) return false; Point mouse(x, y); // // We are just grabbing the knob // if (!pressed && inpt->pressing[MAIN1] && !inpt->lock[MAIN1]) { if (isWithin(pos_knob, mouse)) { pressed = true; inpt->lock[MAIN1] = true; return true; } return false; } // buttons already in use, new click not allowed if (inpt->lock[UP]) return false; if (inpt->lock[DOWN]) return false; if (!pressed && !inpt->lock[UP] && !inpt->lock[DOWN] && !inpt->pressing[MAIN1] && !inpt->lock[MAIN1]) { return true; } if (pressed) { // // The knob has been released // // create a temporary SDL_Rect slightly wider than the slider SDL_Rect tmp_pos; tmp_pos.x = pos.x - (pos_knob.w*2); tmp_pos.y = pos.y; tmp_pos.w = pos.w + (pos_knob.w*4); tmp_pos.h = pos.h; if (!isWithin(tmp_pos, mouse)) { pressed = false; return false; } if (!inpt->lock[MAIN1]) { pressed = false; } // set the value of the slider int tmp = std::max(0, std::min(mouse.x - pos.x, static_cast<int>(pos.w))); pos_knob.x = pos.x + tmp - (pos_knob.w/2); assert(pos.w); value = minimum + (tmp*(maximum-minimum))/pos.w; return true; } return false; } void WidgetSlider::set (int min, int max, int val) { minimum = min; maximum = max; value = val; pos_knob.x = pos.x + ((val-min)* pos.w)/(max-min) - (pos_knob.w/2); pos_knob.y = pos.y; } int WidgetSlider::getValue () const { return value; } void WidgetSlider::render (SDL_Surface *target) { if (target == NULL) { target = screen; } SDL_Rect base; base.x = 0; base.y = 0; base.h = pos.h; base.w = pos.w; SDL_Rect knob; knob.x = 0; knob.y = pos.h; knob.h = pos_knob.h; knob.w = pos_knob.w; if (render_to_alpha) { SDL_gfxBlitRGBA(sl, &base, target, &pos); SDL_gfxBlitRGBA(sl, &knob, target, &pos_knob); } else { SDL_BlitSurface(sl, &base, target, &pos); SDL_BlitSurface(sl, &knob, target, &pos_knob); } if (in_focus) { Point topLeft; Point bottomRight; Uint32 color; topLeft.x = pos.x; topLeft.y = pos.y; bottomRight.x = pos.x + pos.w; bottomRight.y = pos.y + pos.h; color = SDL_MapRGB(target->format, 255,248,220); drawRectangle(target, topLeft, bottomRight, color); } } bool WidgetSlider::getNext() { if (!enabled) return false; value -= (maximum - minimum)/10; if (value < minimum) value = minimum; pos_knob.x = pos.x + ((value-minimum)* pos.w)/(maximum-minimum) - (pos_knob.w/2); pos_knob.y = pos.y; return true; } bool WidgetSlider::getPrev() { if (!enabled) return false; value += (maximum - minimum)/10; if (value > maximum) value = maximum; pos_knob.x = pos.x + ((value-minimum)* pos.w)/(maximum-minimum) - (pos_knob.w/2); pos_knob.y = pos.y; return true; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetSlider.h����������������������������������������������������������������0000664�0000000�0000000�00000002357�12247171015�0017334�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2012 Justin Jacobs This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetSlider */ #pragma once #ifndef WIDGET_SLIDER_H #define WIDGET_SLIDER_H class Widget; class WidgetSlider : public Widget { public: WidgetSlider (const std::string & fname); ~WidgetSlider (); bool checkClick (); bool checkClick (int x, int y); void set (int min, int max, int val); int getValue () const; void render (SDL_Surface *target = NULL); bool enabled; SDL_Rect pos_knob; // This is the position of the slider's knob within the screen bool getNext(); bool getPrev(); private: SDL_Surface * sl; bool pressed; int minimum; int maximum; int value; }; #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetSlot.cpp����������������������������������������������������������������0000664�0000000�0000000�00000010547�12247171015�0017366�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetButton */ #include "CommonIncludes.h" #include "WidgetSlot.h" #include "SharedResources.h" #include "SDL_gfxBlitFunc.h" #include "Settings.h" using namespace std; WidgetSlot::WidgetSlot(SDL_Surface *_icons, int _icon_id, int _ACTIVATE) : Widget() , icons(_icons) , icon_id(_icon_id) , amount(1) , max_amount(1) , amount_str("") , ACTIVATE(_ACTIVATE) , enabled(true) , checked(false) , pressed(false) , continuous(false) { focusable = true; pos.x = pos.y = 0; pos.w = ICON_SIZE; pos.h = ICON_SIZE; slot_selected = loadGraphicSurface("images/menus/slot_selected.png"); slot_checked = loadGraphicSurface("images/menus/slot_checked.png"); } void WidgetSlot::activate() { pressed = true; } void WidgetSlot::deactivate() { pressed = false; checked = false; } void WidgetSlot::defocus() { in_focus = false; pressed = false; checked = false; } bool WidgetSlot::getNext() { pressed = false; checked = false; return false; } bool WidgetSlot::getPrev() { pressed = false; checked = false; return false; } CLICK_TYPE WidgetSlot::checkClick() { return checkClick(inpt->mouse.x,inpt->mouse.y); } CLICK_TYPE WidgetSlot::checkClick(int x, int y) { Point mouse(x,y); // disabled slots can't be clicked; if (!enabled) return NO_CLICK; if (continuous && pressed && checked && (inpt->lock[MAIN2] || inpt->lock[ACTIVATE])) return ACTIVATED; // main button already in use, new click not allowed if (inpt->lock[MAIN1]) return NO_CLICK; if (inpt->lock[MAIN2]) return NO_CLICK; if (inpt->lock[ACTIVATE]) return NO_CLICK; if (pressed && !inpt->lock[MAIN1] && !inpt->lock[MAIN2] && !inpt->lock[ACTIVATE]) { // this is a button release pressed = false; checked = !checked; if (checked) return CHECKED; else return ACTIVATED; } // detect new click // use MAIN1 only for selecting if (inpt->pressing[MAIN1]) { if (isWithin(pos, mouse)) { inpt->lock[MAIN1] = true; pressed = true; checked = false; } } // use MAIN2 only for activating if (inpt->pressing[MAIN2]) { if (isWithin(pos, mouse)) { inpt->lock[MAIN2] = true; pressed = true; checked = true; } } return NO_CLICK; } void WidgetSlot::setIcon(int _icon_id) { icon_id = _icon_id; } void WidgetSlot::setAmount(int _amount, int _max_amount) { amount = _amount; max_amount = _max_amount; amount_str = abbreviateKilo(amount); } void WidgetSlot::render(SDL_Surface *target) { if (target == NULL) { target = screen; } SDL_Rect src; if (icon_id != -1 && icons != NULL) { int columns = icons->w / ICON_SIZE; src.x = (icon_id % columns) * ICON_SIZE; src.y = (icon_id / columns) * ICON_SIZE; src.w = pos.w; src.h = pos.h; if (render_to_alpha) SDL_gfxBlitRGBA(icons, &src, target, &pos); else SDL_BlitSurface(icons, &src, target, &pos); if (amount > 1 || max_amount > 1) { stringstream ss; ss << amount_str; WidgetLabel label; label.set(pos.x + 2, pos.y + 2, JUSTIFY_LEFT, VALIGN_TOP, ss.str(), font->getColor("item_normal")); label.render(); } } renderSelection(target); } /** * We can use this function if slot is grayed out to refresh selection frame */ void WidgetSlot::renderSelection(SDL_Surface *target) { if (target == NULL) { target = screen; } if (in_focus) { SDL_Rect src; src.x = src.y = 0; src.w = src.h = ICON_SIZE; if (render_to_alpha) { if (checked) SDL_gfxBlitRGBA(slot_checked, &src, target, &pos); else SDL_gfxBlitRGBA(slot_selected, &src, target, &pos); } else { if (checked) SDL_BlitSurface(slot_checked, &src, target, &pos); else SDL_BlitSurface(slot_selected, &src, target, &pos); } } } WidgetSlot::~WidgetSlot() { SDL_FreeSurface(slot_selected); SDL_FreeSurface(slot_checked); } ���������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetSlot.h������������������������������������������������������������������0000664�0000000�0000000�00000003352�12247171015�0017027�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2013 Igor Paliychuk This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetSlot */ #pragma once #ifndef WIDGET_SLOT_H #define WIDGET_SLOT_H #include "CommonIncludes.h" #include "InputState.h" #include "Widget.h" enum CLICK_TYPE { NO_CLICK = 0, CHECKED = 1, ACTIVATED = 2 }; class WidgetSlot : public Widget { private: SDL_Surface *icons; // icons surface SDL_Surface *slot_selected; SDL_Surface *slot_checked; int icon_id; // current slot id int amount; // entries amount in slot int max_amount; // if > 1 always display amount std::string amount_str; // formatted display of amount int ACTIVATE; public: WidgetSlot(SDL_Surface *_icon, int _icon_id = -1, int _ACTIVATE = ACCEPT); ~WidgetSlot(); void activate(); void deactivate(); void defocus(); bool getNext(); bool getPrev(); CLICK_TYPE checkClick(); CLICK_TYPE checkClick(int x, int y); void setIcon(int _icon_id); void setAmount(int _amount, int _max_amount = 1); void render(SDL_Surface *target = NULL); void renderSelection(SDL_Surface *target = NULL); bool enabled; bool checked; bool pressed; bool continuous; // allow holding key to keep slot activated }; #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetTabControl.cpp����������������������������������������������������������0000664�0000000�0000000�00000012166�12247171015�0020513�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include "WidgetTabControl.h" #include "WidgetLabel.h" using namespace std; /** * Class constructor. * * @param amount Amount of tabs the control will have. */ WidgetTabControl::WidgetTabControl(int amount) { // Based on given amount: tabsAmount = amount; titles = new std::string[tabsAmount]; tabs = new SDL_Rect[tabsAmount]; // Predefined: activeTab = 0; tabPadding.x = 8; tabPadding.y = 4; // Load needed graphics. loadGraphics(); color_normal = font->getColor("widget_normal"); color_disabled = font->getColor("widget_disabled"); } /** * Class destructor. */ WidgetTabControl::~WidgetTabControl() { SDL_FreeSurface(activeTabSurface); SDL_FreeSurface(inactiveTabSurface); delete[] titles; delete[] tabs; } /** * Sets the title of a tab. * * @param number Tab index. For example, 0 for the first tab. * @param title Tab title. * @param updateHeader Whether or not the header should be updated. */ void WidgetTabControl::setTabTitle(int number, const std::string& title) { titles[number] = title; } /** * Returns the index of the open tab. * * For example, if the first tab is open, it will return 0. */ int WidgetTabControl::getActiveTab() { return activeTab; } /** * Define the position and size of the tab control. * * @param x X coordinate of the top-left corner of the widget. * @param y Y coordinate of the top-left corner of the widget. * @param width Width of the widget. * @param height Height of the widget. */ void WidgetTabControl::setMainArea(int x, int y, int width, int height) { // Set tabs area. tabsArea.x = x; tabsArea.y = y; tabsArea.w = width; tabsArea.h = activeTabSurface->h; // Set content area. contentArea.x = x + 8; contentArea.y = y + tabsArea.h+8; contentArea.w = width - 16; contentArea.h = height - tabsArea.h; } /** * Updates the areas or the tabs. * * Use it right after you set the area and tab titles of the tab control. */ void WidgetTabControl::updateHeader() { for (int i=0; i<tabsAmount; i++) { tabs[i].y = tabsArea.y; tabs[i].h = tabsArea.h; if (i==0) tabs[i].x = tabsArea.x; else tabs[i].x = tabs[i-1].x + tabs[i-1].w; tabs[i].w = tabPadding.x + font->calc_width(titles[i]) + tabPadding.x; } } /** * Load the graphics for the control. */ void WidgetTabControl::loadGraphics() { activeTabSurface = loadGraphicSurface("images/menus/tab_active.png"); inactiveTabSurface = loadGraphicSurface("images/menus/tab_inactive.png"); if (!activeTabSurface || !inactiveTabSurface) { SDL_Quit(); exit(1); } } void WidgetTabControl::logic() { logic(inpt->mouse.x,inpt->mouse.y); } /** * Performs one frame of logic. * * It basically checks if it was clicked on the header, and if so changes the active tab. */ void WidgetTabControl::logic(int x, int y) { Point mouse(x, y); // If the click was in the tabs area; if(isWithin(tabsArea, mouse) && inpt->pressing[MAIN1]) { // Mark the clicked tab as activeTab. for (int i=0; i<tabsAmount; i++) { if(isWithin(tabs[i], mouse)) { activeTab = i; return; } } } } /** * Renders the widget. * * Remember to render then on top of it the actual content of the {@link getActiveTab() active tab}. */ void WidgetTabControl::render(SDL_Surface *target) { if (target == NULL) { target = screen; } for (int i=0; i<tabsAmount; i++) { renderTab(i,target); } } /** * Renders the given tab on the widget header. */ void WidgetTabControl::renderTab(int number, SDL_Surface *target) { int i = number; SDL_Rect src; SDL_Rect dest; // Draw tab’s background. src.x = src.y = 0; dest.x = tabs[i].x; dest.y = tabs[i].y; src.w = tabs[i].w; src.h = tabs[i].h; if (i == activeTab) SDL_BlitSurface(activeTabSurface, &src, target, &dest); else SDL_BlitSurface(inactiveTabSurface, &src, target, &dest); // Draw tab’s right edge. src.x = activeTabSurface->w - tabPadding.x; src.w = tabPadding.x; dest.x = tabs[i].x + tabs[i].w - tabPadding.x; if (i == activeTab) SDL_BlitSurface(activeTabSurface, &src, target, &dest); else SDL_BlitSurface(inactiveTabSurface, &src, target, &dest); // Set tab’s label font color. SDL_Color fontColor; if (i == activeTab) fontColor = color_normal; else fontColor = color_disabled; // Draw tab’s label. WidgetLabel label; label.set(tabs[i].x + tabPadding.x, tabs[i].y + tabs[i].h/2, JUSTIFY_LEFT, VALIGN_CENTER, titles[i], fontColor); label.render(target); } /** * Returns the height in pixels of the widget. */ SDL_Rect WidgetTabControl::getContentArea() { return contentArea; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetTabControl.h������������������������������������������������������������0000664�0000000�0000000�00000003761�12247171015�0020161�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #pragma once #ifndef MENU_TAB_CONTROL_H #define MENU_TAB_CONTROL_H #include "CommonIncludes.h" #include "SharedResources.h" class WidgetTabControl { private: SDL_Surface *activeTabSurface; SDL_Surface *inactiveTabSurface; std::string *titles; /** Titles of the tabs. */ int activeTab; /** Index of the currently active tab. */ int tabsAmount; /** Amount of tabs in the control. */ SDL_Rect *tabs; /** Rectangles for each tab title on the tab header. */ SDL_Rect tabsArea; /** Area the tab titles are displayed. */ SDL_Rect contentArea; /** Area where the content of the {@link activeTab active tab} is displayed. */ Point tabPadding; /** Padding between tab titles. */ SDL_Color color_normal; SDL_Color color_disabled; void loadGraphics(); void renderTab(int number, SDL_Surface *target); public: WidgetTabControl(int amount); WidgetTabControl(const WidgetTabControl ©); // copy constructor not implemented ~WidgetTabControl(); void setTabTitle(int number, const std::string& title); void setMainArea(int x, int y, int width, int height); int getActiveTab(); void setActiveTab(int tab) { activeTab = tab; } SDL_Rect getContentArea(); int getTabHeight() { return activeTabSurface->h; } void updateHeader(); void logic(); void logic(int x, int y); void render(SDL_Surface *target = NULL); }; #endif ���������������flare-engine-0.19/src/WidgetTooltip.cpp�������������������������������������������������������������0000664�0000000�0000000�00000010337�12247171015�0020074�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetTooltip */ #include "FileParser.h" #include "WidgetTooltip.h" #include "Settings.h" #include "Utils.h" #include "UtilsParsing.h" using namespace std; int TOOLTIP_CONTEXT = TOOLTIP_NONE; WidgetTooltip::WidgetTooltip() { FileParser infile; // load tooltip settings from engine config file if (infile.open("engine/tooltips.txt")) { while (infile.next()) { if (infile.key == "tooltip_offset") offset = toInt(infile.val); else if (infile.key == "tooltip_width") width = toInt(infile.val); else if (infile.key == "tooltip_margin") margin = toInt(infile.val); } infile.close(); } } /** * Knowing the total size of the text and the position of origin, * calculate the starting position of the background and text */ Point WidgetTooltip::calcPosition(STYLE style, Point pos, Point size) { Point tip_pos; // TopLabel style is fixed and centered over the origin if (style == STYLE_TOPLABEL) { tip_pos.x = pos.x - size.x/2; tip_pos.y = pos.y - offset; } // Float style changes position based on the screen quadrant of the origin // (usually used for tooltips which are long and we don't want them to overflow // off the end of the screen) else if (style == STYLE_FLOAT) { // upper left if (pos.x < VIEW_W_HALF && pos.y < VIEW_H_HALF) { tip_pos.x = pos.x + offset; tip_pos.y = pos.y + offset; } // upper right else if (pos.x >= VIEW_W_HALF && pos.y < VIEW_H_HALF) { tip_pos.x = pos.x - offset - size.x; tip_pos.y = pos.y + offset; } // lower left else if (pos.x < VIEW_W_HALF && pos.y >= VIEW_H_HALF) { tip_pos.x = pos.x + offset; tip_pos.y = pos.y - offset - size.y; } // lower right else if (pos.x >= VIEW_W_HALF && pos.y >= VIEW_H_HALF) { tip_pos.x = pos.x - offset - size.x; tip_pos.y = pos.y - offset - size.y; } } return tip_pos; } /** * Tooltip position depends on the screen quadrant of the source. * Draw the buffered tooltip if it exists, else render the tooltip and buffer it */ void WidgetTooltip::render(TooltipData &tip, Point pos, STYLE style, SDL_Surface *target) { if (target == NULL) { target = screen; } if (tip.tip_buffer == NULL) { createBuffer(tip); } Point size; size.x = tip.tip_buffer->w; size.y = tip.tip_buffer->h; Point tip_pos = calcPosition(style, pos, size); SDL_Rect dest; dest.x = tip_pos.x; dest.y = tip_pos.y; SDL_BlitSurface(tip.tip_buffer, NULL, target, &dest); } /** * Rendering a wordy tooltip (TTF to raster) can be expensive. * Instead of doing this each frame, do it once and cache the result. */ void WidgetTooltip::createBuffer(TooltipData &tip) { if (tip.lines.empty()) { tip.lines.resize(1); tip.colors.resize(1); } // concat multi-line tooltip, used in determining total display size string fulltext; fulltext = tip.lines[0]; for (unsigned int i=1; i<tip.lines.size(); i++) { fulltext = fulltext + "\n" + tip.lines[i]; } font->setFont("font_regular"); // calculate the full size to display a multi-line tooltip Point size = font->calc_size(fulltext, width); // WARNING: dynamic memory allocation. Be careful of memory leaks. tip.tip_buffer = createAlphaSurface(size.x + margin+margin, size.y + margin+margin); // Currently tooltips are always opaque SDL_SetAlpha(tip.tip_buffer, 0, 0); // style the tooltip background // currently this is plain black SDL_FillRect(tip.tip_buffer, NULL, 0); int cursor_y = margin; for (unsigned int i=0; i<tip.lines.size(); i++) { font->render(tip.lines[i], margin, cursor_y, JUSTIFY_LEFT, tip.tip_buffer, size.x, tip.colors[i]); cursor_y = font->cursor_y; } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/WidgetTooltip.h���������������������������������������������������������������0000664�0000000�0000000�00000002643�12247171015�0017542�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2012 Stefan Beller This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ /** * class WidgetTooltip */ #pragma once #ifndef WIDGET_TOOLTIP_H #define WIDGET_TOOLTIP_H #include "CommonIncludes.h" #include "SharedResources.h" #include "TooltipData.h" #include "Utils.h" extern int TOOLTIP_CONTEXT; const int TOOLTIP_NONE = 0; const int TOOLTIP_MAP = 1; const int TOOLTIP_MENU = 2; class WidgetTooltip { private: int offset; // distance between cursor and tooltip int width; // max width of tooltips (wrap text) int margin; // outer margin between tooltip text and the edge of the tooltip background public: WidgetTooltip(); Point calcPosition(STYLE style, Point pos, Point size); void render(TooltipData &tip, Point pos, STYLE style, SDL_Surface *target = NULL); void createBuffer(TooltipData &tip); }; #endif ���������������������������������������������������������������������������������������������flare-engine-0.19/src/main.cpp����������������������������������������������������������������������0000664�0000000�0000000�00000013510�12247171015�0016216�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright © 2011-2012 Clint Bellanger Copyright © 2013 Henrik Andersson This file is part of FLARE. FLARE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FLARE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLARE. If not, see http://www.gnu.org/licenses/ */ #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> using namespace std; #include "Settings.h" #include "Stats.h" #include "GameSwitcher.h" #include "SharedResources.h" #include "UtilsFileSystem.h" GameSwitcher *gswitch; SDL_Surface *titlebar_icon; /** * Game initialization. */ static void init() { setPaths(); setStatNames(); // SDL Inits if ( SDL_Init (SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0 ) { fprintf(stderr, "Could not initialize SDL: %s\n", SDL_GetError()); exit(1); } // Shared Resources set-up mods = new ModManager(); if (find(mods->mod_list.begin(), mods->mod_list.end(), FALLBACK_MOD) == mods->mod_list.end()) { fprintf(stderr, "Could not find the default mod in the following locations:\n"); if (dirExists(PATH_DATA + "mods")) fprintf(stderr, "%smods/\n", PATH_DATA.c_str()); if (dirExists(PATH_DEFAULT_DATA + "mods")) fprintf(stderr, "%smods/\n", PATH_DEFAULT_DATA.c_str()); if (dirExists(PATH_USER + "mods")) fprintf(stderr, "%smods/\n", PATH_USER.c_str()); if (dirExists(PATH_DEFAULT_USER + "mods")) fprintf(stderr, "%smods/\n", PATH_DEFAULT_USER.c_str()); fprintf(stderr, "\nA copy of the default mod is in the \"mods\" directory of the flare-engine repo.\n"); fprintf(stderr, "The repo is located at: https://github.com/clintbellanger/flare-engine\n"); fprintf(stderr, "Try again after copying the default mod to one of the above directories.\nExiting.\n"); exit(1); } if (!loadSettings()) { fprintf(stderr, "%s", ("Could not load settings file: ‘" + PATH_CONF + FILE_SETTINGS + "’.\n").c_str()); exit(1); } msg = new MessageEngine(); font = new FontEngine(); anim = new AnimationManager(); comb = new CombatText(); imag = new ImageManager(); inpt = new InputState(); // Load tileset options (must be after ModManager is initialized) loadTilesetSettings(); // Load miscellaneous settings loadMiscSettings(); // Add Window Titlebar Icon titlebar_icon = IMG_Load(mods->locate("images/logo/icon.png").c_str()); SDL_WM_SetIcon(titlebar_icon, NULL); // Create window setupSDLVideoMode(VIEW_W, VIEW_H); if (screen == NULL) { fprintf (stderr, "Error during SDL_SetVideoMode: %s\n", SDL_GetError()); SDL_Quit(); exit(1); } // Set Gamma if (CHANGE_GAMMA) SDL_SetGamma(GAMMA,GAMMA,GAMMA); if (AUDIO && Mix_OpenAudio(22050, AUDIO_S16SYS, 2, 1024)) { fprintf (stderr, "Error during Mix_OpenAudio: %s\n", SDL_GetError()); AUDIO = false; } snd = new SoundManager(); // initialize Joysticks if(SDL_NumJoysticks() == 1) { printf("1 joystick was found:\n"); } else if(SDL_NumJoysticks() > 1) { printf("%d joysticks were found:\n", SDL_NumJoysticks()); } else { printf("No joysticks were found.\n"); } for(int i = 0; i < SDL_NumJoysticks(); i++) { printf(" Joy %d) %s\n", i, SDL_JoystickName(i)); } if ((ENABLE_JOYSTICK) && (SDL_NumJoysticks() > 0)) joy = SDL_JoystickOpen(JOYSTICK_DEVICE); printf("Using joystick #%d.\n", JOYSTICK_DEVICE); // Set sound effects volume from settings file if (AUDIO) Mix_Volume(-1, SOUND_VOLUME); // Window title const char* title = msg->get(WINDOW_TITLE).c_str(); SDL_WM_SetCaption(title, title); gswitch = new GameSwitcher(); } static void mainLoop (bool debug_event) { bool done = false; int delay = 1000/MAX_FRAMES_PER_SEC; int prevTicks = SDL_GetTicks(); while ( !done ) { SDL_PumpEvents(); inpt->handle(debug_event); gswitch->logic(); // black out SDL_FillRect(screen, NULL, 0); gswitch->render(); // Engine done means the user escapes the main game menu. // Input done means the user closes the window. done = gswitch->done || inpt->done; int nowTicks = SDL_GetTicks(); if (nowTicks - prevTicks < delay) SDL_Delay(delay - (nowTicks - prevTicks)); gswitch->showFPS(1000 / (SDL_GetTicks() - prevTicks)); prevTicks = SDL_GetTicks(); SDL_Flip(screen); } } static void cleanup() { delete gswitch; delete anim; delete comb; delete font; delete imag; delete inpt; delete mods; delete msg; delete snd; SDL_FreeSurface(titlebar_icon); Mix_CloseAudio(); SDL_Quit(); } string parseArg(const string &arg) { string result = ""; // arguments must start with '--' if (arg.length() > 2 && arg[0] == '-' && arg[1] == '-') { for (unsigned i = 2; i < arg.length(); ++i) { if (arg[i] == '=') break; result += arg[i]; } } return result; } string parseArgValue(const string &arg) { string result = ""; bool found_equals = false; for (unsigned i = 0; i < arg.length(); ++i) { if (found_equals) { result += arg[i]; } if (arg[i] == '=') found_equals = true; } return result; } int main(int argc, char *argv[]) { bool debug_event = false; for (int i = 1 ; i < argc; i++) { string arg = string(argv[i]); if (parseArg(arg) == "debug-event") { debug_event = true; } else if (parseArg(arg) == "game") { GAME_FOLDER = parseArgValue(arg); } else if (parseArg(arg) == "data-path") { CUSTOM_PATH_DATA = parseArgValue(arg); if (!CUSTOM_PATH_DATA.empty() && CUSTOM_PATH_DATA.at(CUSTOM_PATH_DATA.length()-1) != '/') CUSTOM_PATH_DATA += "/"; } } srand((unsigned int)time(NULL)); init(); mainLoop(debug_event); cleanup(); return 0; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flare-engine-0.19/src/resource.h��������������������������������������������������������������������0000664�0000000�0000000�00000000057�12247171015�0016570�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#define IDI_FLARE_APP_ICON 101 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������