Merge branch 'master' into spritely-map-addition

This commit is contained in:
Ihar Hubchyk
2026-04-05 12:18:04 +08:00
82 changed files with 6679 additions and 5342 deletions
+1 -1
View File
@@ -33,7 +33,7 @@ jobs:
echo "The date specified in the LegalCopyright entry is valid.") || \
(echo "Please update the date in the LegalCopyright entry!" && false)
- name: Check format of markdown files
uses: DavidAnson/markdownlint-cli2-action@v22
uses: DavidAnson/markdownlint-cli2-action@v23
- name: Check format of HTML and CSS files
uses: creyD/[email protected]
with:
+2 -2
View File
@@ -24,7 +24,7 @@ jobs:
shell: bash
steps:
- uses: actions/checkout@v6
- uses: actions/configure-pages@v5
- uses: actions/configure-pages@v6
- name: Prepare directory structure
run: |
mkdir -p .pages/dist/play-online
@@ -55,4 +55,4 @@ jobs:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/deploy-pages@v4
- uses: actions/deploy-pages@v5
+1 -1
View File
@@ -6,7 +6,7 @@ This open source multiplatform project, written from scratch, is designed to rep
improvements in gameplay, graphics and logic (including support for high-resolution graphics, improved AI, numerous fixes
and user interface improvements), breathing new life into one of the most addictive turn-based strategy games.
You can find a complete list of all of our changes and enhancements in [**its own wiki page**](https://github.com/ihhub/fheroes2/wiki/Features-and-enhancements-of-the-project).
You can find a complete list of all of our changes and enhancements in [**this page**](docs/GAME_IMPROVEMENTS.md).
<p align="center">
<img src="docs/images/screenshots/screenshot_world_map.webp" width="820" alt="Screenshot of the world map">
+394
View File
@@ -0,0 +1,394 @@
# Features and enhancements of the project
## Description
This page is a collection of features and enhancements made in **fheroes2** project in comparison with the original Heroes of Might and Magic II game.
All information presented in this document is subject to change and does not cover every detail presented in the project.
***
### Special characteristics for each creature in creature info window
![Special Characteristics](https://user-images.githubusercontent.com/55348946/188264403-58e6b1b4-2aef-4970-8d14-6efae756ec27.png)
***
### Higher resolution selection
![Resolution select](https://github.com/ihhub/fheroes2/assets/55348946/42e29267-b1f6-41b8-9232-9270e94579ea)
***
### New configuration dialog
![Settings](https://user-images.githubusercontent.com/55348946/227176346-90caaa02-143a-4a9e-a484-ef178f2c6c1c.png)
***
### Multiple language support
![Language selection](https://user-images.githubusercontent.com/55348946/208439961-eeea82b5-d2e5-4975-a115-a808bd13d189.png)
\[*\] Language selection is available for any version of the original game, however assets containing text and voice acting will remain on the initial language.
***
### Size adaptive buttons
![Adaptive buttons](https://github.com/ihhub/fheroes2/assets/55348946/d3e78010-ccfc-43f9-8d3d-16e269e6d52f)
\[*\] Some translations require larger buttons.
***
### Hot keys list
![Hot keys](https://github.com/ihhub/fheroes2/assets/55348946/31c99f75-bd81-45a7-9ff1-ddad6df90676)
\[*\] It's also possible to re-assign hot-keys.
***
### Instant battle option
![Instant battle switch](https://github.com/ihhub/fheroes2/assets/55348946/97f32166-2795-4819-b979-a4e02ddff181)
***
### Restart battle in manual mode
![Restart button](https://user-images.githubusercontent.com/55348946/188266839-d333dda6-ecbc-4724-aa2e-dd2b4e96d1d0.png)
***
### Instant finishing of manual battles
![Finish battle](https://user-images.githubusercontent.com/55348946/190421334-68737241-5d37-4de5-bd52-67b87e70fe04.png)
\[*\] Press **Q** to finish the battle in auto mode.
***
### Auto battle confirmation/interruption dialogs
![Auto battle dialog](https://github.com/ihhub/fheroes2/assets/55348946/c9bc815c-f871-4ab9-a88c-415a6e349f07)
***
### Ctrl/Alt/Shift keys for army rearrangement
![Fast rearrangement](https://user-images.githubusercontent.com/55348946/188267046-bb6d0913-f68d-4d26-bd6a-8f152c01fe0d.gif)
***
### Buttons for splitting into several equal stacks
![Fast split buttons](https://user-images.githubusercontent.com/55348946/188267102-60111953-e5f4-4480-b813-346e1596e1d9.png)
***
### Spell duration in creature info window during battle
![Spell duration counter](https://user-images.githubusercontent.com/55348946/188267128-6e48e9e2-82a8-4978-ac32-b8f07a434a5a.png)
***
### Spell description in creature info window during battle
![Spell description](https://user-images.githubusercontent.com/55348946/188267147-ae283847-d258-4575-a0ad-013f76a3fee4.png)
***
### Creature's movement area is divided into separate hexes
![Movement hexes](https://user-images.githubusercontent.com/55348946/188267207-cca42499-5c9b-4d95-9ea8-59cf531d9648.gif)
***
### Double hex highlight for "big" creatures
![Hex highlight](https://user-images.githubusercontent.com/55348946/188267252-2f1db6cd-972e-488e-85c4-523430abeef8.gif)
***
### Double hex attack highlight
![Breath attack](https://user-images.githubusercontent.com/55348946/188267270-9f1d93dd-5d77-4989-a9ba-b49d2637cf16.gif)
***
### Attacking damage pop up window
![Damage info](https://user-images.githubusercontent.com/55348946/208454845-9cf5b81b-0e50-4152-8af5-1fc4882e6525.png)
***
### Multiple windows and dialogs adapted for "Evil" interface type
![New Evil Windows](https://github.com/ihhub/fheroes2/assets/55348946/1381fa47-94dc-4ad2-accc-48923a813841)
\[*\] In the original game they all were only in "good" (brown) colors.
***
### Attacking spell damage pop up window
![Spell damage info](https://user-images.githubusercontent.com/55348946/227178904-5d447a6f-ada6-4f0e-be10-2a672395c2fa.png)
***
### Recruit troops in well
![Well recruit](https://github.com/ihhub/fheroes2/assets/55348946/82c6ed8f-671b-4df9-83f0-41de4de76b48)
\[*\] In the original game the only way to hire creatures was to click each dwelling in castle screen.
***
### Larger creature counters
![Larger counters](https://user-images.githubusercontent.com/55348946/188267855-703418e7-5788-4366-bd7a-4507ced9fe4c.gif)
***
### Mass spell casting area
![Spell area](https://user-images.githubusercontent.com/55348946/188267866-0c1fcfae-e47d-4f88-9ec7-5d488fb9e2d2.png)
***
### Liches shooting area highlight
![Shooting Liches](https://user-images.githubusercontent.com/55348946/188268155-c993610b-0df2-4c42-a1d3-45d14745358b.png)
***
### New "Town Portal" spell UI
![Town Portal](https://user-images.githubusercontent.com/55348946/188268210-abf13020-159c-4d4a-a474-f2b2f3a4e80a.gif) ![Town Portal](https://user-images.githubusercontent.com/55348946/188268220-03df57cd-cae3-478e-8799-c11ef10ad1f6.gif)
***
### New button to check hero info in multiple game dialogs
![Hero Info](https://user-images.githubusercontent.com/55348946/188269706-ddf15060-3642-445d-8937-1efb4754953e.png)
***
### Creature upgrade selection buttons
![Upgrade selection](https://user-images.githubusercontent.com/55348946/188269746-f9da9eda-fb5c-4d08-8b87-c136be93011e.gif)
***
### Extended day counters for cursors
![Cursor counters](https://user-images.githubusercontent.com/55348946/188269761-f986ac8c-9e0b-466c-86f5-a55daf1f6070.png)
\[*\] In the original game counter was limited to 4 days.
***
### Visited status for multiple objects on an adventure map
![Visited objects](https://user-images.githubusercontent.com/55348946/188269776-03f2a472-20d7-418e-a736-1c624f5bbba1.png)
***
### Kingdom income window in castle screen
![Income window](https://user-images.githubusercontent.com/55348946/188269799-2987edad-2310-42b7-8508-1a7250ef301f.gif)
***
### New mass spell icons, rendered from the original ones
![Mass spells](https://user-images.githubusercontent.com/55348946/188269832-c955a0c6-6b4e-4f8e-861f-de95970872ed.gif)
***
### Switch town buttons at construction screen
![Switch town](https://user-images.githubusercontent.com/55348946/188310255-aec26c19-ea1f-4405-beae-ba06e3ef4860.png)
***
### Added missing part of a farm in Knight town
![Farm](https://user-images.githubusercontent.com/55348946/188310584-451818dd-c422-49ec-96b4-d4d187b28c4d.gif)
\[*\] A shadow from a castle in front of the field was also removed.
***
### Icon for original or expansion map types
![Icon](https://user-images.githubusercontent.com/55348946/188310375-d1f28d7c-25a4-46ff-9c7d-d1b519793969.gif)
***
### Added missing part of Captain's Quarters in Barbarian town
![Captain's Quarters](https://user-images.githubusercontent.com/55348946/188311479-26d81860-2c61-41ce-8461-68f725c78d0e.gif)
***
### Map name, game progress in days and location within OS could be checked through save file info
![Save file info (2)](https://user-images.githubusercontent.com/55348946/227183289-53ac244a-5d89-438d-86cc-ba25b5ff713f.png)
***
### Removed bridge for Captain's Quarters in Necromancer town
![Necromancer town](https://user-images.githubusercontent.com/55348946/188310470-f928d0c9-30eb-4763-a0c4-3969da2c52af.gif)
***
### Fixed part of Cavalry sprite being rendered with wrong colors
![Cavalry fix](https://user-images.githubusercontent.com/55348946/188310489-01e4c1c1-fe69-4899-8bb4-1f53e30d5013.gif)
***
### Added missing part of Phoenix Red Tower
![Red Tower](https://github.com/ihhub/fheroes2/assets/55348946/3bd6cc1d-f82b-428c-bf89-dfe7aea247d6)
***
### Check hero info during battle
![Hero info window](https://user-images.githubusercontent.com/55348946/188310520-6a6b382a-4052-462b-9396-e10dfa764e84.gif)
***
### Glowing frame for selected creature or artifact at hero meeting dialog
![OG selection](https://user-images.githubusercontent.com/55348946/188310636-dbfaefbc-1e12-4e95-8f52-95061b13c233.gif) ![Glowing selection](https://user-images.githubusercontent.com/55348946/188310651-e2c85acf-9801-45d1-b0aa-8015d4db8035.gif)
***
### Visited Shrine and Witch Hut info shows which skill or spell a hero can study there
![Witch Hut](https://user-images.githubusercontent.com/55348946/188311383-b2f64988-320e-41e1-a107-a2d8f9a3658a.png) ![Shrine](https://user-images.githubusercontent.com/55348946/188311407-e6351fb0-b555-43f5-92d5-f5533234f596.png)
***
### Fixed multiple objects rendering in Barbarian city
![Barbarian city](https://user-images.githubusercontent.com/55348946/188311590-1fa9cbac-2aa3-40e4-8823-a7f5e2dee5a7.gif)
***
### Fixed multiple objects rendering in Sorceress city
![Sorceress city](https://user-images.githubusercontent.com/55348946/188311620-b7947a89-1316-4059-91fc-e86eb229a310.gif)
\[*\] Note, that water was always rendered in the corner in the original game, even if town had no access to ocean.
***
### Added missing part of Captain's Quarters in Sorceress town
![Captain's Quarters](https://user-images.githubusercontent.com/55348946/227188959-332f7a92-5ffa-49b0-9f13-0fed2e0ac013.gif)
***
### Show army order during battle
![Army order](https://user-images.githubusercontent.com/55348946/188311670-d191022e-446e-4cc0-b619-5ee69f89b181.png)
***
### Extended save file list shows the date each file has been overwritten
![Save file list](https://github.com/ihhub/fheroes2/assets/55348946/6e0067fd-b446-4277-9118-a0654d30e3ba)
\[*\] Fheroes2 also allows to delete files and wheel scroll list.
***
### Move army/artifacts buttons
![Move buttons](https://user-images.githubusercontent.com/55348946/188311741-cdd2a581-0ecb-4f70-8528-b709c920acd0.gif)
\[*\] In the original game these arrows were just a part of image.
***
### Added shadow for a spell book at adventure map and battle screens
![Book Shadow](https://user-images.githubusercontent.com/55348946/188311761-c5772f48-479f-462d-b628-e8ffad2f67af.gif)
***
### All images of mage guilds are centered in guild spell window
![Sorceress guild](https://user-images.githubusercontent.com/55348946/188311799-14a94611-c448-4a84-9f28-c4f3bca7f9da.gif) ![Knight guild](https://user-images.githubusercontent.com/55348946/188311818-6ff435df-6700-4e7a-88eb-b83440256aa8.gif)
***
### Extended spell info in hero spell book
![Spell Info](https://user-images.githubusercontent.com/55348946/188311913-a2dc00eb-44e2-4574-9aa6-340166f0f973.png)
***
### Castle flags in a Knight city correspond player's color
![Original flags color](https://user-images.githubusercontent.com/55348946/188312012-6fcde1a9-e619-452b-99b9-e89902356aba.gif) ![fheroes2 new colors](https://user-images.githubusercontent.com/55348946/188311988-32caad51-5973-4f8d-93b8-e707a86bc649.gif)
***
### Castle flags in a Wizard city correspond player's color
![Original flags color](https://user-images.githubusercontent.com/55348946/188312212-334f788c-468d-4ab9-acc7-c28f68cf1d79.gif) ![fheroes2 new colors](https://user-images.githubusercontent.com/55348946/188312229-79523b80-2ba8-464d-8be9-147fd2cedeed.gif)
***
### Fixed flag overlay with tower in Knight castle
![Castle flag overlay](https://user-images.githubusercontent.com/55348946/188312071-da3c006a-db0b-4bdd-8496-bfac52fa4646.gif)
***
### Size adaptive game scroll bars
![Scrollbars](https://user-images.githubusercontent.com/55348946/188312092-d6c6b637-864f-47ed-8446-464aff1df112.gif)
***
### Rewards and bonuses in campaign have detailed info on right click
![Campaign info window](https://github.com/ihhub/fheroes2/assets/55348946/2a115b2c-a049-472a-afd0-8546b527e687)
\[*\] In the original game none of elements have info window.
***
### Campaign difficulty selection
![Difficulty](https://github.com/ihhub/fheroes2/assets/55348946/0ab9bd0e-4740-4a5e-9b66-23bbc082a17d)
\[*\] Selected difficulty will effect the result in **High Scores**.
***
### New icon for Medusa's petrification ability
![Small icon](https://user-images.githubusercontent.com/55348946/227197177-3a5793d6-a427-4649-bdcb-c626c528da50.gif) ![ezgif com-crop](https://user-images.githubusercontent.com/55348946/227199898-1516b369-10bd-456b-88a7-003f27fbc50b.gif)
***
### Battle only mode
![Battle only mode](https://github.com/ihhub/fheroes2/assets/55348946/15a24df9-3dce-4ee1-845f-87540df8997d)
***
### Spells are grayed, when conditions for use are not met
![grayed spells](https://github.com/ihhub/fheroes2/assets/55348946/7b8ac74e-ff7a-49b2-881b-7a66191c14cf)
***
+1 -1
View File
@@ -6,7 +6,7 @@ This open source multiplatform project, written from scratch, is designed to rep
improvements in gameplay, graphics and logic (including support for high-resolution graphics, improved AI, numerous fixes
and user interface improvements), breathing new life into one of the most addictive turn-based strategy games.
You can find a complete list of all of our changes and enhancements in [**its own wiki page**](https://github.com/ihhub/fheroes2/wiki/Features-and-enhancements-of-the-project).
You can find a complete list of all of our changes and enhancements in [**this page**](GAME_IMPROVEMENTS.md).
<!-- markdownlint-disable MD033 -->
<div class="image-showcase">
+4 -3
View File
@@ -8,20 +8,21 @@ subdirectory of the project source tree. The current instruction is designed for
![Belarusian](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_be.json)
![Bulgarian](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_bg.json)
![Czech](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_cs.json)
![German](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_de.json)
![Danish](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_da.json)
![Spanish](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_es.json)
![Dutch](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_nl.json)
![German](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_de.json)
![Greek](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_el.json)
![French](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_fr.json)
![Hungarian](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_hu.json)
![Italian](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_it.json)
![Lithuanian](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_lt.json)
![Norwegian](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_nb.json)
![Dutch](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_nl.json)
![Polish](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_pl.json)
![Brazilian Portuguese](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_pt.json)
![Romanian](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_ro.json)
![Russian](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_ru.json)
![Slovak](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_sk.json)
![Spanish](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_es.json)
![Swedish](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_sv.json)
![Turkish](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_tr.json)
![Ukrainian](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_uk.json)
+12
View File
@@ -199,6 +199,7 @@ $body-font: "Asul";
h3 {
font-size: 1.5em;
text-wrap: balance;
}
h4 {
@@ -437,6 +438,17 @@ $body-font: "Asul";
}
}
hr {
border: none;
border-top: 0.125em solid rgba(map-get($theme-map, secondary-color), 0.4);
margin: 2em 0;
}
#main_content img {
max-width: 100%;
height: auto;
}
@media screen and (min-width: $tablet-width) {
.shell {
border: 0.125em solid map-get($theme-map, border-color);
+1 -1
View File
@@ -12,7 +12,7 @@ $light: (
inverse-background-color: #383838,
inverse-border-color: #c0c0c0,
inverse-primary-color: #c0c0c0,
border-radius: 10px,
border-radius: 5px,
body-text-shadow: none,
header-text-shadow: -1px 2px 1px #cd853f,
table-text-color: #fff,
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"label":"Belarusian","message":"92%","color":"yellow"}
{"schemaVersion":1,"label":"Belarusian","message":"93%","color":"yellow"}
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"label":"Greek","message":"0%","color":"red"}
{"schemaVersion":1,"label":"Greek","message":"2%","color":"red"}
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"label":"Polish","message":"79%","color":"yellow"}
{"schemaVersion":1,"label":"Polish","message":"84%","color":"yellow"}
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"label":"Ukrainian","message":"99%","color":"green"}
{"schemaVersion":1,"label":"Ukrainian","message":"98%","color":"green"}
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"label":"Vietnamese","message":"78%","color":"yellow"}
{"schemaVersion":1,"label":"Vietnamese","message":"77%","color":"yellow"}
+3 -3
View File
@@ -1122,9 +1122,9 @@
}
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"dev": true,
"license": "MIT",
"engines": {
+32 -34
View File
@@ -1,5 +1,5 @@
# Belarusian translation of fheroes2
# Copyright (C) 2022 - 2025 fheroes2 team <[email protected]>
# Copyright (C) 2022 - 2026 fheroes2 team <[email protected]>
# Copyright (C) 2025 Belarusian Heroes of Might and Magic project <[email protected]>
# This file is distributed under the same license as the fheroes2 package.
#
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2022-09-23 16:01+0200\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: \n"
@@ -22,6 +22,9 @@ msgstr ""
msgid "SELECT"
msgstr "ВЫБРАЦЬ"
msgid "ABOUT"
msgstr ""
msgid "S"
msgstr "S"
@@ -563,11 +566,13 @@ msgstr ""
"з яго, ходзіць толькі адну клетку. Таксама абарона такога атрада зніжаецца "
"на %{count}."
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Хуткасць: %{speed}"
msgid "Speed"
msgstr "Хуткасць"
#, fuzzy
msgid "battleAnimation|Speed"
msgstr "Анімацыя"
msgid "Interface"
msgstr "Інтэрфейс"
@@ -1159,7 +1164,6 @@ msgstr "Чалавек"
msgid "AI"
msgstr "Камп’ютар"
#, fuzzy
msgid "Terrain"
msgstr "Зямная паверхня"
@@ -2880,7 +2884,6 @@ msgstr "Вышэйпералічаныя чары можна вывучыць т
msgid "The spells the hero can learn have been added to their book."
msgstr "Чары, якія герой мог вывучыць, перапісаны ў ягоную кнігу."
#
msgid "Exit Mage Guild"
msgstr "Выйсці з гільдыі магаў"
@@ -2969,6 +2972,9 @@ msgstr "Пашкод."
msgid "HP"
msgstr "Здароўе"
msgid "Speed"
msgstr "Хуткасць"
msgid "Growth"
msgstr "Прырост"
@@ -3266,6 +3272,13 @@ msgstr ""
"Умовы\n"
"паражэння"
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Націсніце, каб вярнуцца ў галоўнае меню."
msgid "Map Description"
msgstr "Апісанне мапы"
@@ -3767,9 +3780,8 @@ msgstr ""
msgid "Select Skill:"
msgstr "Выберыце ўменне:"
#, fuzzy
msgid "There are no spells to select."
msgstr "Няма чараў, якія можна чараваць."
msgstr "Няма чараў, якія можна выбраць."
msgid "Select Spell:"
msgstr "Выберыце чары:"
@@ -4794,9 +4806,8 @@ msgstr "Падтрымайце нас на"
msgid "Language"
msgstr "Мова"
#, fuzzy
msgid "This language already exists in the list."
msgstr "Такая чутка ўжо ёсць у спісе."
msgstr "Такая мова ўжо ёсць у спісе."
msgid "A map should have at least one language."
msgstr ""
@@ -4805,21 +4816,17 @@ msgstr ""
msgid "Click to apply changes."
msgstr "Націсніце тут, каб змяніць клас."
#, fuzzy
msgid "Add Language"
msgstr "Мова"
msgstr "Дадаць мову"
#, fuzzy
msgid "Add an additional language."
msgstr "Дадаць дадатковую чутку."
msgstr "Дадаць дадатковую мову."
#, fuzzy
msgid "Delete Language"
msgstr "Выберыце мову:"
msgstr "Выдаліць мову"
#, fuzzy
msgid "Delete an existing language."
msgstr "Выдаліць існую чутку."
msgstr "Выдаліць існуючую мову."
msgid "Failed to generate a random map with given parameters."
msgstr ""
@@ -4978,18 +4985,12 @@ msgstr "ПАДЗЕІ"
msgid "LANGUAGE"
msgstr "МОВА"
msgid "ABOUT"
msgstr ""
msgid "Change Map Name"
msgstr "Змяніць назву мапы"
msgid "Change Map Description"
msgstr "Змяніць апісанне мапы"
msgid "About"
msgstr ""
msgid "Click to edit custom rumors."
msgstr "Націсніце, каб паправіць дададзеныя ў сцэнар чуткі."
@@ -5619,6 +5620,10 @@ msgstr ""
msgid "hotkey|re-configure random map"
msgstr ""
#, fuzzy
msgid "hotkey|output all text"
msgstr "пасунуць мапу прыгод улева"
msgid "hotkey|roland campaign"
msgstr "кампанія за Раланда"
@@ -5873,7 +5878,6 @@ msgstr "Перадвызначаныя дзеянні"
msgid "Global Actions"
msgstr "Агульныя дзеянні"
#
msgid "World Map"
msgstr "Карта свету"
@@ -5883,7 +5887,6 @@ msgstr "Экран бою"
msgid "Town Screen"
msgstr "Экран горада"
#
msgid "Army Actions"
msgstr "Дзеянні арміі"
@@ -8464,7 +8467,6 @@ msgstr "У вас няма вадаплава, які можна было б в
msgid "There is no ocean adjacent to the hero where this spell will work."
msgstr "Герой не знаходзіцца на беразе, таму гэтыя чары не падзейнічаюць."
#
msgid ""
"You do not own any town or castle that is not currently occupied by a hero. "
"This spell will have no effect."
@@ -9255,9 +9257,8 @@ msgid ""
"%{morale-type} morale may give the hero's units extra attacks in combat."
msgstr "Атрады з высокім баявым духам могуць атрымліваць дадатковыя хады."
#, fuzzy
msgid "Blood"
msgstr "Крывавацарства"
msgstr "Гатовыя біцца на смерць"
msgid "Knight"
msgstr "Рыцар"
@@ -9485,9 +9486,8 @@ msgstr ""
msgid "monster_strength|Weak"
msgstr ""
#, fuzzy
msgid "monster_strength|Normal"
msgstr "Нармальны"
msgstr "Нармальная"
msgid "monster_strength|Strong"
msgstr ""
@@ -9612,7 +9612,6 @@ msgstr[0] "Водны млын"
msgstr[1] "Водныя млыны"
msgstr[2] "Водных млыноў"
#
msgid "Monster"
msgstr "Монстр"
@@ -12357,7 +12356,6 @@ msgstr ""
msgid "Mirror Image"
msgstr "Люстраны двайнік"
#
msgid ""
"Creates an illusionary unit that duplicates one of your existing units. This "
"illusionary unit does the same damages as the original, but will vanish if "
+23 -10
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2022-11-08 16:44+0000\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: \n"
@@ -20,6 +20,9 @@ msgstr ""
msgid "SELECT"
msgstr "ИЗБЕРИ"
msgid "ABOUT"
msgstr ""
msgid "S"
msgstr ""
@@ -536,11 +539,13 @@ msgstr ""
"Ровът намалява с -%{count} умението за защита на всяка единица и забавя "
"наполовина скоростта на движение."
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Скорост: %{speed}"
msgid "Speed"
msgstr "Скорост"
#, fuzzy
msgid "battleAnimation|Speed"
msgstr "Анексирам"
msgid "Interface"
msgstr "Интерфейс"
@@ -2974,6 +2979,9 @@ msgstr "Щети"
msgid "HP"
msgstr "Живот"
msgid "Speed"
msgstr "Скорост"
msgid "Growth"
msgstr "Растеж"
@@ -3276,6 +3284,13 @@ msgstr ""
"Условия за\n"
"Загуба"
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Кликни, за да се върнеш към главното меню."
#, fuzzy
msgid "Map Description"
msgstr ""
@@ -5158,9 +5173,6 @@ msgstr ""
msgid "LANGUAGE"
msgstr ""
msgid "ABOUT"
msgstr ""
msgid "Change Map Name"
msgstr ""
@@ -5168,9 +5180,6 @@ msgstr ""
msgid "Change Map Description"
msgstr "Избрано описание"
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to edit custom rumors."
msgstr "Кликни, за да запазиш текущата игра."
@@ -5844,6 +5853,10 @@ msgstr "нова случайна игра"
msgid "hotkey|re-configure random map"
msgstr "нова случайна игра"
#, fuzzy
msgid "hotkey|output all text"
msgstr "превъртете наляво"
msgid "hotkey|roland campaign"
msgstr "кампания на роланд"
+23 -18
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2025-04-09 11:06+0200\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: Czech <[email protected]>\n"
@@ -21,6 +21,9 @@ msgstr ""
msgid "SELECT"
msgstr "ZVOLIT"
msgid "ABOUT"
msgstr ""
msgid "S"
msgstr "S"
@@ -539,11 +542,13 @@ msgstr ""
"Příkop přeruší jakýkoli pohyb skrz něj a snižuje obrannou sílu jednotek, "
"které se v něm nacházejí, o %{count}."
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Rychlost: %{speed}"
msgid "Speed"
msgstr "Rychlost"
#, fuzzy
msgid "battleAnimation|Speed"
msgstr "Animace"
msgid "Interface"
msgstr "Rozhraní"
@@ -2905,6 +2910,9 @@ msgstr "Škody"
msgid "HP"
msgstr "Zdravi"
msgid "Speed"
msgstr "Rychlost"
msgid "Growth"
msgstr "Růst"
@@ -3205,6 +3213,13 @@ msgstr ""
"Podmínky\n"
"prohry"
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Klikni pro návrat do hlavního menu."
msgid "Map Description"
msgstr "Popis mapy"
@@ -4967,18 +4982,12 @@ msgstr "UDÁLOSTI"
msgid "LANGUAGE"
msgstr "JAZYK"
msgid "ABOUT"
msgstr ""
msgid "Change Map Name"
msgstr "Změnit název mapy"
msgid "Change Map Description"
msgstr "Změnit popis mapy"
msgid "About"
msgstr ""
msgid "Click to edit custom rumors."
msgstr "Klikněte pro úpravu vlastních pověstí."
@@ -5624,6 +5633,10 @@ msgstr "Nová náhodná mapa"
msgid "hotkey|re-configure random map"
msgstr "Nová náhodná mapa"
#, fuzzy
msgid "hotkey|output all text"
msgstr "Posun vlevo"
msgid "hotkey|roland campaign"
msgstr "Rolandova kampaň"
@@ -12541,11 +12554,3 @@ msgstr "On jí řekl: Yada yada yada... ona pak řekla: Bla, bla, bla..."
msgid "An unknown force is being resurrected..."
msgstr "Neznámá síla se probouzí..."
#~ msgid ""
#~ "You are about to change the map's language from %{oldLanguage} to "
#~ "%{newLanguage}. Some texts might not be displayed properly after this. Do "
#~ "you want to proceed?"
#~ msgstr ""
#~ "Chystáte se změnit jazyk mapy z %{oldLanguage} na %{newLanguage}. Některé "
#~ "texty nemusí být po této změně zobrazeny správně.Chcete pokračovat?"
+23 -19
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2025-04-19 17:45+0200\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: Danish (Denmark)\n"
@@ -23,6 +23,9 @@ msgstr ""
msgid "SELECT"
msgstr "VÆLG"
msgid "ABOUT"
msgstr "OM"
msgid "S"
msgstr "S"
@@ -537,11 +540,13 @@ msgstr ""
"Voldgraven afbryder enhver bevægelse gennem den og reducerer forsvarsevnen "
"for tropperne, der er til stede i den, med %{count} point."
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Hastighed: %{speed}"
msgid "Speed"
msgstr "Hastighed"
#, fuzzy
msgid "battleAnimation|Speed"
msgstr "Animation"
msgid "Interface"
msgstr "Interface"
@@ -2978,6 +2983,9 @@ msgstr "Skade"
msgid "HP"
msgstr "Liv"
msgid "Speed"
msgstr "Hastighed"
msgid "Growth"
msgstr "Vækst"
@@ -3282,6 +3290,13 @@ msgstr ""
"Tabs-\n"
"vilkår"
msgid "About"
msgstr "Om"
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Klik her for at vende tilbage til hovedmenuen."
msgid "Map Description"
msgstr "Kortbeskrivelse"
@@ -5040,18 +5055,12 @@ msgstr "BEGIVENHEDER"
msgid "LANGUAGE"
msgstr "SPROG"
msgid "ABOUT"
msgstr "OM"
msgid "Change Map Name"
msgstr "Skift kortnavn"
msgid "Change Map Description"
msgstr "Skift kortbeskrivelse"
msgid "About"
msgstr "Om"
msgid "Click to edit custom rumors."
msgstr "Klik for at redigere tilpassede rygter."
@@ -5699,6 +5708,10 @@ msgstr "Generer nyt kort"
msgid "hotkey|re-configure random map"
msgstr "Generer nyt kort"
#, fuzzy
msgid "hotkey|output all text"
msgstr "Rul til venstre"
msgid "hotkey|roland campaign"
msgstr "Felttoget: Roland"
@@ -12750,12 +12763,3 @@ msgstr ""
msgid "An unknown force is being resurrected..."
msgstr "En ukendt styrke er ved at genopstå..."
#~ msgid ""
#~ "You are about to change the map's language from %{oldLanguage} to "
#~ "%{newLanguage}. Some texts might not be displayed properly after this. Do "
#~ "you want to proceed?"
#~ msgstr ""
#~ "Du er ved at ændre kortets sprog fra %{oldLanguage} til %{newLanguage}. "
#~ "Nogle tekster vil måske ikke blive vist korrekt efter dette. Ønsker du at "
#~ "fortsætte?"
+23 -10
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2025-03-31 15:35+0200\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: felix-schneider, do-ut-des\n"
@@ -20,6 +20,9 @@ msgstr ""
msgid "SELECT"
msgstr "AUSW."
msgid "ABOUT"
msgstr "ÜBER"
msgid "S"
msgstr "S"
@@ -548,11 +551,13 @@ msgstr ""
"die Verteidigungsfertigkeit von Truppen, die sich in ihm befinden, um "
"%{count}."
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Geschw.: %{speed}"
msgid "Speed"
msgstr "Bewegung"
#, fuzzy
msgid "battleAnimation|Speed"
msgstr "Animation"
msgid "Interface"
msgstr "Anzeige"
@@ -2964,6 +2969,9 @@ msgstr "Schaden"
msgid "HP"
msgstr "TP"
msgid "Speed"
msgstr "Bewegung"
msgid "Growth"
msgstr "Wachstum"
@@ -3265,6 +3273,13 @@ msgstr ""
"Verlust-\n"
"bedingungen"
msgid "About"
msgstr "Über"
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Klicken, um zum Hauptmenü zurückzukehren."
msgid "Map Description"
msgstr "Kartenbeschreibung"
@@ -5026,18 +5041,12 @@ msgstr "EREIGNISSE"
msgid "LANGUAGE"
msgstr "SPRACHE"
msgid "ABOUT"
msgstr "ÜBER"
msgid "Change Map Name"
msgstr "Kartennamen ändern"
msgid "Change Map Description"
msgstr "Kartenbeschreibung ändern"
msgid "About"
msgstr "Über"
msgid "Click to edit custom rumors."
msgstr "Klickt, um Gerüchte hinzuzufügen oder zu bearbeiten."
@@ -5679,6 +5688,10 @@ msgstr "Zufällige Karte neu generieren"
msgid "hotkey|re-configure random map"
msgstr "Zufällige Karte neu konfigurieren"
#, fuzzy
msgid "hotkey|output all text"
msgstr "Links scrollen"
msgid "hotkey|roland campaign"
msgstr "Roland-Feldzug"
+154 -55
View File
@@ -1,45 +1,55 @@
# Greek translation of fheroes2
# Copyright (C) 2022-2025 fheroes2 team <[email protected]>
# Copyright (C) 2025-2026 fheroes2 team <[email protected]>
# This file is distributed under the same license as the fheroes2 package.
#
msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"PO-Revision-Date: 2025-05-19 07:06+0200\n"
"Last-Translator: PlatoHero <[email protected]>\n"
"Language-Team: [email protected]\n"
"POT-Creation-Date: 2026-03-29 15:04+0000\n"
"PO-Revision-Date: 2026-04-01 14:30+0100\n"
"Last-Translator: Yannis Anthymidis <[email protected]>\n"
"Language-Team: Greek\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: Poedit 3.6\n"
"X-Generator: Poedit 3.9\n"
msgid "SELECT"
msgstr ""
msgstr "ΕΠΙΛΟΓΗ"
# η λέξη «ΠΛΗΡΟΦΟΡΙΕΣ» είναι πιο σωστή, αλλά ήταν υπερβολικά μεγάλη
msgid "ABOUT"
msgstr "ΣΧΕΤΙΚΑ"
# δεν υπάρχει ελληνικό αντίστοιχο, και S, M, L, X-L είναι πλήρως κατανοητά
msgid "S"
msgstr ""
msgstr "S"
# δεν υπάρχει ελληνικό αντίστοιχο, και S, M, L, X-L είναι πλήρως κατανοητά
msgid "M"
msgstr ""
msgstr "M"
# δεν υπάρχει ελληνικό αντίστοιχο, και S, M, L, X-L είναι πλήρως κατανοητά
msgid "L"
msgstr ""
msgstr "L"
# δεν υπάρχει ελληνικό αντίστοιχο, και S, M, L, X-L είναι πλήρως κατανοητά
msgid "X-L"
msgstr ""
msgstr "X-L"
# (οι χάρτες)
msgid "ALL"
msgstr ""
msgstr "ΟΛΟΙ"
msgid "EXIT"
msgstr ""
msgstr "ΕΞΟΔΟΣ"
# ΕΞΟΔΟΣ δεν χωράει για έναν χαρακτήρα. Μπορούμε εναλλακτικά να το γράψουμε ως ΤΕΛΟΣ, αλλά αυτό χάνει το θεματικό στοιχείο του κουμπιού, επείδη π.χ. «παίρνεις την έξοδο» του κάστρου
msgid "smallerButton|EXIT"
msgstr ""
msgstr "ΕΞΟΔ."
msgid "OKAY"
msgstr "ΕΝΤΑΞΕΙ"
@@ -55,7 +65,7 @@ msgstr ""
"ΚΑΣΤΡΑ"
msgid "CANCEL"
msgstr "ΑΚΥΡΩΣΗ"
msgstr "ΑΚΥΡΟ"
msgid "ACCEPT"
msgstr "ΑΠΟΔΟΧΗ"
@@ -76,22 +86,24 @@ msgid "NO"
msgstr "ΟΧΙ"
msgid "DISMISS"
msgstr ""
msgstr "ΑΠΟΛΥΣΗ"
msgid "UPGRADE"
msgstr ""
msgstr "ΑΝΑΒΑΘΜΙΣΗ"
# εναλλακτικά «ΠΡΟΣΦΟΡΑ», αλλά επέλεξα δώρο επειδή δεν χρειάζεται να την αποδεχτεί ο παραλήπτης
msgid "GIFT"
msgstr ""
msgstr "ΔΩΡΟ"
# ταιριάζει με «ΕΝΑΡΞΗ»
msgid "RESTART"
msgstr ""
msgstr "ΕΠΑΝΕΝΑΡΞΗ"
msgid "MAX"
msgstr ""
msgstr "ΜΕΓ"
msgid "MIN"
msgstr ""
msgstr "ΕΛΑΧ"
msgid ""
"D\n"
@@ -102,6 +114,13 @@ msgid ""
"S\n"
"S"
msgstr ""
"Α\n"
"Π\n"
"Ο\n"
"Λ\n"
"Υ\n"
"Σ\n"
"Η"
msgid ""
"E\n"
@@ -109,6 +128,12 @@ msgid ""
"I\n"
"T"
msgstr ""
"Ε\n"
"Ξ\n"
"Ο\n"
"Δ\n"
"Ο\n"
"Σ"
msgid ""
"C\n"
@@ -120,6 +145,13 @@ msgid ""
"G\n"
"N"
msgstr ""
"Ι\n"
"Σ\n"
"Τ\n"
"Ο\n"
"Ρ\n"
"Ι\n"
"Α"
msgid ""
"S\n"
@@ -131,137 +163,184 @@ msgid ""
"R\n"
"D"
msgstr ""
"Κ\n"
"Α\n"
"Ν\n"
"Ο\n"
"Ν\n"
"Ι\n"
"Κ\n"
"Ο"
msgid ""
"NEW\n"
"GAME"
msgstr ""
"ΝΕΟ\n"
"ΠΑΙΧΝΙΔΙ"
msgid ""
"LOAD\n"
"GAME"
msgstr ""
"ΦΟΡΤΩΣΗ\n"
"ΠΑΙΧΝΙΔΙΟΥ"
# ταιριάζει με «ΕΝΑΡΞΗ»
msgid ""
"RESTART\n"
"GAME"
msgstr ""
"ΕΠΑΝΕΝΑΡΞΗ\n"
"ΠΑΙΧΝΙΔΙΟΥ"
msgid ""
"SAVE\n"
"GAME"
msgstr ""
"ΑΠΟΘΗΚΕΥΣΗ\n"
"ΠΑΙΧΝΙΔΙΟΥ"
msgid ""
"QUICK\n"
"SAVE"
msgstr ""
"ΓΡΗΓΟΡΗ\n"
"ΑΠΟΘΗΚΕΥΣΗ"
msgid "QUIT"
msgstr ""
msgstr "ΕΓΚΑΤΑΛΕΙΨΗ"
msgid ""
"START\n"
"MAP"
msgstr ""
"ΠΑΙΞΕ\n"
"ΣΤΟΝ\n"
"ΧΑΡΤΗ"
msgid ""
"MAIN\n"
"MENU"
msgstr ""
"ΚΥΡΙΟ\n"
"ΜΕΝΟΥ"
msgid ""
"NEW\n"
"MAP"
msgstr ""
"ΝΕΟΣ\n"
"ΧΑΡΤΗΣ"
msgid ""
"LOAD\n"
"MAP"
msgstr ""
"ΦΟΡΤΩΣΗ\n"
"ΧΑΡΤΗ"
msgid ""
"SAVE\n"
"MAP"
msgstr ""
"ΑΠΟΘΗΚΕΥΣΗ\n"
"ΧΑΡΤΗ"
msgid "INFO"
msgstr ""
msgstr "ΠΛΗΡΟΦΟΡΙΕΣ"
msgid ""
"BATTLE\n"
"ONLY"
msgstr ""
"ΜΟΝΟ\n"
"ΜΑΧΗ"
msgid "SETTINGS"
msgstr ""
msgstr "ΡΥΘΜΙΣΕΙΣ"
msgid ""
"STANDARD\n"
"GAME"
msgstr ""
"ΚΑΝΟΝΙΚΟ\n"
"ΠΑΙΧΝΙΔΙ"
msgid ""
"CAMPAIGN\n"
"GAME"
msgstr ""
"ΙΣΤΟΡΙΑ\n"
"ΠΑΙΧΝΙΔΙΟΥ"
msgid ""
"MULTI-\n"
"PLAYER\n"
"GAME"
msgstr ""
"ΠΑΙΧΝΙΔΙ\n"
"ΠΟΛΛΩΝ\n"
"ΠΑΙΚΤΩΝ"
msgid "HOT SEAT"
msgstr ""
msgstr "ΤΟΠΙΚΟ ΠΑΙΧΝΙΔΙ"
msgid "2 PLAYERS"
msgstr ""
msgstr "2 ΠΑΙΚΤΕΣ"
msgid "3 PLAYERS"
msgstr ""
msgstr "3 ΠΑΙΚΤΕΣ"
msgid "4 PLAYERS"
msgstr ""
msgstr "4 ΠΑΙΚΤΕΣ"
msgid "5 PLAYERS"
msgstr ""
msgstr "5 ΠΑΙΚΤΕΣ"
msgid "6 PLAYERS"
msgstr ""
msgstr "6 ΠΑΙΚΤΕΣ"
msgid ""
"ORIGINAL\n"
"CAMPAIGN"
msgstr ""
"ΑΡΧΙΚΗ\n"
"ΙΣΤΟΡΙΑ"
msgid ""
"EXPANSION\n"
"CAMPAIGN"
msgstr ""
"ΙΣΤΟΡΙΑ\n"
"ΕΠΕΚΤΑΣΗΣ"
msgid "editorMainMenu|BACK"
msgstr ""
msgstr "ΕΠΙΣΤΡΟΦΗ"
msgid ""
"newMap|FROM\n"
"SCRATCH"
msgstr ""
"ΑΠΟ\n"
"ΤΗΝ ΑΡΧΗ"
# Η επόμενη οθόνη ξεκαθαρίζει πως μιλάμε για γεννήτρια χαρτών, επομένως επέλεξα «τυχαίος»
msgid "newMap|RANDOM"
msgstr ""
msgstr "ΤΥΧΑΙΟΣ"
msgid "DIFFICULTY"
msgstr ""
msgstr "ΔΥΣΚΟΛΙΑ"
# ΠΡΟΒΟΛΗ ΕΙΣΑΓΩΓΗΣ ήταν σε δύο γραμμές επομένως πρέπει αναγκαστικά να το μειώσουμε
msgid "VIEW INTRO"
msgstr ""
msgstr "ΕΙΣΑΓΩΓΗ"
msgid "RESET"
msgstr ""
msgstr "ΕΠΑΝΑΦΟΡΑ"
msgid "START"
msgstr ""
msgstr "ΕΝΑΡΞΗ"
msgid ""
"P\n"
@@ -271,6 +350,15 @@ msgid ""
"O\n"
"L"
msgstr ""
"Π\n"
"Ε\n"
"Ρ\n"
"Ι\n"
"Π\n"
"Ο\n"
"Λ\n"
"Ι\n"
"Α"
msgid "army|Few"
msgstr ""
@@ -446,10 +534,10 @@ msgid ""
"troops present in it by %{count}."
msgstr ""
msgid "Speed: %{speed}"
msgid "battleAnimation|Speed: %{speed}"
msgstr ""
msgid "Speed"
msgid "battleAnimation|Speed"
msgstr ""
msgid "Interface"
@@ -757,11 +845,15 @@ msgid ""
"AUTO\n"
"COMBAT"
msgstr ""
"ΑΥΤΟΜΑΤΗ\n"
"ΜΑΧΗ"
msgid ""
"QUICK\n"
"COMBAT"
msgstr ""
"ΓΡΗΓΟΡΗ\n"
"ΜΑΧΗ"
msgid "The computer continues the combat for you."
msgstr ""
@@ -2608,6 +2700,9 @@ msgstr ""
msgid "HP"
msgstr ""
msgid "Speed"
msgstr ""
msgid "Growth"
msgstr ""
@@ -2874,6 +2969,12 @@ msgid ""
"Conditions"
msgstr ""
msgid "About"
msgstr ""
msgid "Click to read notes from the map creator."
msgstr ""
msgid "Map Description"
msgstr ""
@@ -3386,10 +3487,10 @@ msgid "doubleLinedRace|Neutral"
msgstr ""
msgid "TOWN"
msgstr ""
msgstr "ΠΟΛΗ"
msgid "CASTLE"
msgstr ""
msgstr "ΚΑΣΤΡΟ"
msgid "Click to start placing the selected castle/town."
msgstr ""
@@ -3706,7 +3807,7 @@ msgid "Random Town Name"
msgstr ""
msgid "BANNED SPELLS"
msgstr ""
msgstr "ΑΠΟΚΛΕΙΣΜΕΝΑ ΞΟΡΚΙΑ"
msgid "Click to accept the changes made."
msgstr ""
@@ -3724,7 +3825,7 @@ msgid "Select spells that will appear in the Mage Guild."
msgstr ""
msgid "SET SPELLS"
msgstr ""
msgstr "ΟΡΙΣΤΕ ΞΟΡΚΙΑ"
msgid "Allow Castle build"
msgstr ""
@@ -3732,8 +3833,9 @@ msgstr ""
msgid "Default Buildings"
msgstr ""
# ΠΕΡΙΟΡΙΣΜΟΣ δεν χωράει ενώ «ΠΕΡΙΟΡΙΣΗ» είναι αρχαία (και αγγράματη!) λέξη
msgid "RESTRICT"
msgstr ""
msgstr "ΑΠΟΚΛΙΣΗ"
msgid "Default Army"
msgstr ""
@@ -4490,16 +4592,13 @@ msgid "Map Difficulty"
msgstr ""
msgid "RUMORS"
msgstr ""
msgstr "ΦΗΜΕΣ"
msgid "EVENTS"
msgstr ""
msgstr "ΣΥΜΒΑΝΤΑ"
msgid "LANGUAGE"
msgstr ""
msgid "ABOUT"
msgstr ""
msgstr "ΓΛΩΣΣΑ"
msgid "Change Map Name"
msgstr ""
@@ -4507,9 +4606,6 @@ msgstr ""
msgid "Change Map Description"
msgstr ""
msgid "About"
msgstr ""
msgid "Click to edit custom rumors."
msgstr ""
@@ -5108,6 +5204,9 @@ msgstr ""
msgid "hotkey|re-configure random map"
msgstr ""
msgid "hotkey|output all text"
msgstr ""
msgid "hotkey|roland campaign"
msgstr ""
@@ -6055,13 +6154,13 @@ msgid "The available values range from %{min} to %{max}."
msgstr ""
msgid "Keyboard|123"
msgstr ""
msgstr "123"
msgid "Keyboard|SPACE"
msgstr ""
msgstr "ΚΕΝΟ"
msgid "Keyboard|ABC"
msgstr ""
msgstr "ΑΒΓ"
msgid "The entered value is invalid."
msgstr ""
+23 -10
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2025-07-06 12:40+0200\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: Spanish <[email protected]>\n"
@@ -22,6 +22,9 @@ msgstr ""
msgid "SELECT"
msgstr "ESCOGER"
msgid "ABOUT"
msgstr ""
msgid "S"
msgstr "S"
@@ -550,11 +553,13 @@ msgstr ""
"El foso reduce la habilidad de defensa de las tropas atrapadas en él en un "
"%{count} y limita su rango de movimiento."
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Velocidad: %{speed}"
msgid "Speed"
msgstr "Velocidad"
#, fuzzy
msgid "battleAnimation|Speed"
msgstr "Anexión"
msgid "Interface"
msgstr "Interfaz"
@@ -2928,6 +2933,9 @@ msgstr "Daño"
msgid "HP"
msgstr "PV"
msgid "Speed"
msgstr "Velocidad"
msgid "Growth"
msgstr "Crecimiento"
@@ -3229,6 +3237,13 @@ msgstr ""
"Condiciones\n"
"de Derrota"
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Haz clic para volver al menú principal."
#, fuzzy
msgid "Map Description"
msgstr "Descripción seleccionada"
@@ -5115,9 +5130,6 @@ msgstr "EVENTOS"
msgid "LANGUAGE"
msgstr "IDIOMA"
msgid "ABOUT"
msgstr ""
msgid "Change Map Name"
msgstr ""
@@ -5125,9 +5137,6 @@ msgstr ""
msgid "Change Map Description"
msgstr "Descripción seleccionada"
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to edit custom rumors."
msgstr "Haz clic para volver al menú principal"
@@ -5808,6 +5817,10 @@ msgstr "Resumen del reino"
msgid "hotkey|re-configure random map"
msgstr "Resumen del reino"
#, fuzzy
msgid "hotkey|output all text"
msgstr "Asiento caliente"
msgid "hotkey|roland campaign"
msgstr ""
+23 -10
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2025-11-08 13:34+0100\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: French <[email protected]>\n"
@@ -21,6 +21,9 @@ msgstr ""
msgid "SELECT"
msgstr "AUTRE"
msgid "ABOUT"
msgstr ""
msgid "S"
msgstr "S"
@@ -540,11 +543,13 @@ msgstr ""
"Le Fossé réduit de -%{count} la caractéristique de défense de n'importe "
"quelle créature et ralentit sa capacité de mouvement."
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Vitesse : %{speed}"
msgid "Speed"
msgstr "Vitesse"
#, fuzzy
msgid "battleAnimation|Speed"
msgstr "Animation"
msgid "Interface"
msgstr "Interface"
@@ -2970,6 +2975,9 @@ msgstr "Dégâts"
msgid "HP"
msgstr "PV"
msgid "Speed"
msgstr "Vitesse"
msgid "Growth"
msgstr "Croissance"
@@ -3276,6 +3284,13 @@ msgstr ""
"Conditions\n"
"de défaite"
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Cliquez pour revenir au menu principal."
#, fuzzy
msgid "Map Description"
msgstr ""
@@ -5095,18 +5110,12 @@ msgstr "ÉVÉNEMENT"
msgid "LANGUAGE"
msgstr "LANGUE"
msgid "ABOUT"
msgstr ""
msgid "Change Map Name"
msgstr "Changer le nom de la carte"
msgid "Change Map Description"
msgstr "Changer la description de la carte"
msgid "About"
msgstr ""
msgid "Click to edit custom rumors."
msgstr "Cliquez pour éditer les rumeurs personnalisées."
@@ -5770,6 +5779,10 @@ msgstr "Nouvelle carte aléatoire"
msgid "hotkey|re-configure random map"
msgstr "Nouvelle carte aléatoire"
#, fuzzy
msgid "hotkey|output all text"
msgstr "Défilement gauche"
msgid "hotkey|roland campaign"
msgstr "Campagne de Roland"
+23 -19
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2026-02-15 23:50+0100\n"
"Last-Translator: Berda Jenő <[email protected]>\n"
"Language-Team: fheroes2 team <[email protected]>\n"
@@ -21,6 +21,9 @@ msgstr ""
msgid "SELECT"
msgstr "VÁLASZT"
msgid "ABOUT"
msgstr "LEÍRÁS"
msgid "S"
msgstr "S"
@@ -540,11 +543,13 @@ msgstr ""
"A várárok megakasztja a keresztülhaladó egységek mozgását és csökkenti a "
"benne álló egységek védelmi képességét %{count} százalékkal."
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Sebesség: %{speed}"
msgid "Speed"
msgstr "Sebesség"
#, fuzzy
msgid "battleAnimation|Speed"
msgstr "Animáció"
msgid "Interface"
msgstr "Kezelőfelület"
@@ -2918,6 +2923,9 @@ msgstr "Sebzés"
msgid "HP"
msgstr "Életerő"
msgid "Speed"
msgstr "Sebesség"
msgid "Growth"
msgstr "Szaporulat"
@@ -3217,6 +3225,13 @@ msgstr ""
"Vesztési\n"
"feltételek"
msgid "About"
msgstr "Leírás"
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Kattints a főmenübe való visszatéréshez."
msgid "Map Description"
msgstr "Térkép leírása"
@@ -4958,18 +4973,12 @@ msgstr "ESEMÉNYEK"
msgid "LANGUAGE"
msgstr "NYELV"
msgid "ABOUT"
msgstr "LEÍRÁS"
msgid "Change Map Name"
msgstr "Térkép nevének megváltoztatása"
msgid "Change Map Description"
msgstr "Térképleírás megváltoztatása"
msgid "About"
msgstr "Leírás"
msgid "Click to edit custom rumors."
msgstr "Kattints egyéni szóbeszéd szerkesztéséhez."
@@ -5606,6 +5615,10 @@ msgstr "véletlenszerű térkép újragenerálása"
msgid "hotkey|re-configure random map"
msgstr "véletlenszerű térkép újrakonfigurálása"
#, fuzzy
msgid "hotkey|output all text"
msgstr "görgetés balra"
msgid "hotkey|roland campaign"
msgstr "roland hadjárata"
@@ -12569,12 +12582,3 @@ msgstr "A férfi üres fecsegésére a nő így válaszolt: bla-bla-bla..."
msgid "An unknown force is being resurrected..."
msgstr "Egy ismeretlen erő kelt új életre ..."
#~ msgid ""
#~ "You are about to change the map's language from %{oldLanguage} to "
#~ "%{newLanguage}. Some texts might not be displayed properly after this. Do "
#~ "you want to proceed?"
#~ msgstr ""
#~ "A térkép nyelvét készülsz megváltoztatni. Régi nyelv: %{oldLanguage}, új "
#~ "nyelv: %{newLanguage}. Néhány szöveg nem biztos, hogy megfelelően jelenik "
#~ "meg ezután. Így is végre akarod hajtani a műveletet?"
+23 -10
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2022-12-03 04:36+0100\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: <[email protected]>\n"
@@ -21,6 +21,9 @@ msgstr ""
msgid "SELECT"
msgstr ""
msgid "ABOUT"
msgstr ""
msgid "S"
msgstr ""
@@ -472,11 +475,13 @@ msgid ""
"troops present in it by %{count}."
msgstr ""
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Velocità: %{speed}"
msgid "Speed"
msgstr "Velocità"
#, fuzzy
msgid "battleAnimation|Speed"
msgstr "Navigazione"
msgid "Interface"
msgstr "Interfaccia"
@@ -2790,6 +2795,9 @@ msgstr "Danni"
msgid "HP"
msgstr "PF"
msgid "Speed"
msgstr "Velocità"
msgid "Growth"
msgstr "Crescita"
@@ -3095,6 +3103,13 @@ msgstr ""
"Condizioni\n"
"Sconfitta"
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Clicca per salvare la partita in corso."
#, fuzzy
msgid "Map Description"
msgstr ""
@@ -4925,9 +4940,6 @@ msgstr ""
msgid "LANGUAGE"
msgstr ""
msgid "ABOUT"
msgstr ""
msgid "Change Map Name"
msgstr ""
@@ -4935,9 +4947,6 @@ msgstr ""
msgid "Change Map Description"
msgstr "Descrizione scelta"
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to edit custom rumors."
msgstr "Clicca per salvare la partita in corso."
@@ -5603,6 +5612,10 @@ msgstr "Sommario Regno"
msgid "hotkey|re-configure random map"
msgstr "Sommario Regno"
#, fuzzy
msgid "hotkey|output all text"
msgstr "Inizia una partita singola o multigiocatore."
msgid "hotkey|roland campaign"
msgstr ""
+21 -10
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2022-09-23 16:14+0200\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: Lithuanian <[email protected]>\n"
@@ -23,6 +23,9 @@ msgstr ""
msgid "SELECT"
msgstr ""
msgid "ABOUT"
msgstr ""
msgid "S"
msgstr ""
@@ -459,11 +462,11 @@ msgid ""
"troops present in it by %{count}."
msgstr ""
msgid "Speed: %{speed}"
msgid "battleAnimation|Speed: %{speed}"
msgstr ""
msgid "Speed"
msgstr "Greitis"
msgid "battleAnimation|Speed"
msgstr ""
msgid "Interface"
msgstr ""
@@ -2759,6 +2762,9 @@ msgstr ""
msgid "HP"
msgstr ""
msgid "Speed"
msgstr "Greitis"
msgid "Growth"
msgstr ""
@@ -3036,6 +3042,13 @@ msgid ""
"Conditions"
msgstr ""
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Rodyti kitą miestą"
msgid "Map Description"
msgstr ""
@@ -4800,18 +4813,12 @@ msgstr ""
msgid "LANGUAGE"
msgstr ""
msgid "ABOUT"
msgstr ""
msgid "Change Map Name"
msgstr ""
msgid "Change Map Description"
msgstr ""
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to edit custom rumors."
msgstr "Rodyti kitą miestą"
@@ -5452,6 +5459,10 @@ msgstr "Rodyti kitą miestą"
msgid "hotkey|re-configure random map"
msgstr "Rodyti kitą miestą"
#, fuzzy
msgid "hotkey|output all text"
msgstr "Rodyti kitą miestą"
msgid "hotkey|roland campaign"
msgstr ""
+23 -10
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2025-03-12 23:47+0100\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: \n"
@@ -20,6 +20,9 @@ msgstr ""
msgid "SELECT"
msgstr "ENDRE"
msgid "ABOUT"
msgstr ""
msgid "S"
msgstr "L"
@@ -519,11 +522,13 @@ msgstr ""
"Vollgraven reduserer forsvarsevnen til krigere som befinner seg i den med "
"%{count} og halverer skrittene deres."
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Hurtighet : %{speed}"
msgid "Speed"
msgstr "Hurtighet"
#, fuzzy
msgid "battleAnimation|Speed"
msgstr "Underleggelse"
msgid "Interface"
msgstr "Grensesnitt"
@@ -3013,6 +3018,9 @@ msgstr "Skade"
msgid "HP"
msgstr "Liv"
msgid "Speed"
msgstr "Hurtighet"
msgid "Growth"
msgstr "Vekst"
@@ -3323,6 +3331,13 @@ msgstr ""
"Taps-\n"
"vilkår"
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Klikk her for å dra tilbake til hovedmenyen."
#, fuzzy
msgid "Map Description"
msgstr ""
@@ -5200,9 +5215,6 @@ msgstr ""
msgid "LANGUAGE"
msgstr ""
msgid "ABOUT"
msgstr ""
msgid "Change Map Name"
msgstr ""
@@ -5210,9 +5222,6 @@ msgstr ""
msgid "Change Map Description"
msgstr "Kartbeskrivelse"
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to edit custom rumors."
msgstr "Klikk for å lagre det nåværende spillet."
@@ -5891,6 +5900,10 @@ msgstr "Nytt automatisk kart"
msgid "hotkey|re-configure random map"
msgstr "Nytt automatisk kart"
#, fuzzy
msgid "hotkey|output all text"
msgstr "Panorer til venstre"
msgid "hotkey|roland campaign"
msgstr "Rolands felttog"
+24 -10
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2022-10-25 08:52+0200\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: Dutch <[email protected]>\n"
@@ -21,6 +21,9 @@ msgstr ""
msgid "SELECT"
msgstr ""
msgid "ABOUT"
msgstr ""
msgid "S"
msgstr ""
@@ -479,11 +482,13 @@ msgstr ""
"De Moat verminderd by -%{count} de verdedgings vaardigheid van een eenheid "
"en versloomt naar de helft van de bewegings snelheid"
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Snelheid: %{speed}"
msgid "Speed"
msgstr "Snelheid"
#, fuzzy
msgid "battleAnimation|Speed"
msgstr "Annexatie"
msgid "Interface"
msgstr ""
@@ -2891,6 +2896,9 @@ msgstr ""
msgid "HP"
msgstr ""
msgid "Speed"
msgstr "Snelheid"
msgid "Growth"
msgstr ""
@@ -3159,6 +3167,14 @@ msgid ""
"Conditions"
msgstr ""
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr ""
"Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?"
msgid "Map Description"
msgstr ""
@@ -4879,18 +4895,12 @@ msgstr ""
msgid "LANGUAGE"
msgstr ""
msgid "ABOUT"
msgstr ""
msgid "Change Map Name"
msgstr ""
msgid "Change Map Description"
msgstr ""
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to edit custom rumors."
msgstr ""
@@ -5524,6 +5534,10 @@ msgstr ""
msgid "hotkey|re-configure random map"
msgstr ""
#, fuzzy
msgid "hotkey|output all text"
msgstr "Systeem instellingen aanpassen"
msgid "hotkey|roland campaign"
msgstr ""
+259 -292
View File
File diff suppressed because it is too large Load Diff
+23 -19
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2026-03-06 18:49-0300\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: Brazilian Portuguese <[email protected]>\n"
@@ -21,6 +21,9 @@ msgstr ""
msgid "SELECT"
msgstr "SELEC."
msgid "ABOUT"
msgstr "SOBRE"
msgid "S"
msgstr "P"
@@ -545,11 +548,13 @@ msgstr ""
"O Fosso interrompe qualquer movimento através dele e reduz a habilidade "
"dedefesa das tropas presentes nele em %{count}."
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Velocidade: %{speed}"
msgid "Speed"
msgstr "Velocidade"
#, fuzzy
msgid "battleAnimation|Speed"
msgstr "Animação"
msgid "Interface"
msgstr "Aparência"
@@ -2935,6 +2940,9 @@ msgstr "Dano"
msgid "HP"
msgstr "PV"
msgid "Speed"
msgstr "Velocidade"
msgid "Growth"
msgstr "Produção"
@@ -3237,6 +3245,13 @@ msgstr ""
"de\n"
"Derrota"
msgid "About"
msgstr "Sobre"
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Clique para retornar ao menu principal."
msgid "Map Description"
msgstr "Descrição do Mapa"
@@ -4991,18 +5006,12 @@ msgstr "EVENTOS"
msgid "LANGUAGE"
msgstr "IDIOMA"
msgid "ABOUT"
msgstr "SOBRE"
msgid "Change Map Name"
msgstr "Alterar o Nome do Mapa"
msgid "Change Map Description"
msgstr "Alterar Descrição do Mapa"
msgid "About"
msgstr "Sobre"
msgid "Click to edit custom rumors."
msgstr "Clique para editar rumores personalizados."
@@ -5642,6 +5651,10 @@ msgstr "gerar novo mapa aleatório"
msgid "hotkey|re-configure random map"
msgstr "reconfigurar mapa aleatório"
#, fuzzy
msgid "hotkey|output all text"
msgstr "rolar para a esquerda"
msgid "hotkey|roland campaign"
msgstr "campanha de Roland"
@@ -12713,12 +12726,3 @@ msgstr ""
msgid "An unknown force is being resurrected..."
msgstr "Uma força misteriosa está ressuscitando..."
#~ msgid ""
#~ "You are about to change the map's language from %{oldLanguage} to "
#~ "%{newLanguage}. Some texts might not be displayed properly after this. Do "
#~ "you want to proceed?"
#~ msgstr ""
#~ "Você está prestes a alterar o idioma do mapa de %{oldLanguage} para "
#~ "%{newLanguage}. Alguns textos podem não ser exibidos corretamente depois "
#~ "disso. Deseja prosseguir?"
+23 -10
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2022-10-25 08:56+0200\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: \n"
@@ -21,6 +21,9 @@ msgstr ""
msgid "SELECT"
msgstr "SELECTEAZĂ"
msgid "ABOUT"
msgstr ""
msgid "S"
msgstr "S"
@@ -535,11 +538,13 @@ msgstr ""
"Șanțul reduce cu -%{count} abilitatea de apărare a oricărei unități și "
"reduce la jumătate viteza de mișcare."
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Viteză: %{speed}"
msgid "Speed"
msgstr "Viteză"
#, fuzzy
msgid "battleAnimation|Speed"
msgstr "Anexare"
msgid "Interface"
msgstr "Interfață"
@@ -2828,6 +2833,9 @@ msgstr ""
msgid "HP"
msgstr ""
msgid "Speed"
msgstr "Viteză"
msgid "Growth"
msgstr ""
@@ -3096,6 +3104,13 @@ msgid ""
"Conditions"
msgstr ""
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Ești sigur că vrei să termini bătălia în modul automat?"
#, fuzzy
msgid "Map Description"
msgstr "Designeri de hărți"
@@ -4811,18 +4826,12 @@ msgstr ""
msgid "LANGUAGE"
msgstr ""
msgid "ABOUT"
msgstr ""
msgid "Change Map Name"
msgstr ""
msgid "Change Map Description"
msgstr ""
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to edit custom rumors."
msgstr "Dați click pentru a reîncepe bătălia în mod manual."
@@ -5448,6 +5457,10 @@ msgstr ""
msgid "hotkey|re-configure random map"
msgstr ""
#, fuzzy
msgid "hotkey|output all text"
msgstr "Personalizează opțiunile sistemului"
msgid "hotkey|roland campaign"
msgstr ""
+23 -10
View File
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2026-02-15 20:44+0300\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: <[email protected]> <>\n"
@@ -24,6 +24,9 @@ msgstr ""
msgid "SELECT"
msgstr "ВЫБОР"
msgid "ABOUT"
msgstr "О КАРТЕ"
msgid "S"
msgstr "М"
@@ -542,11 +545,13 @@ msgstr ""
"Ров прерывает любое передвижение через него и уменьшает на -%{count} навык "
"обороны любого находящегося в нём отряда."
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Скорость: %{speed}"
msgid "Speed"
msgstr "Скорость"
#, fuzzy
msgid "battleAnimation|Speed"
msgstr "Анимация"
msgid "Interface"
msgstr "Интерфейс"
@@ -2940,6 +2945,9 @@ msgstr "Урон"
msgid "HP"
msgstr "Здоровье"
msgid "Speed"
msgstr "Скорость"
msgid "Growth"
msgstr "Прирост"
@@ -3235,6 +3243,13 @@ msgstr ""
"Условия\n"
"поражения"
msgid "About"
msgstr "О карте"
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Нажмите для возврата в главное меню."
msgid "Map Description"
msgstr "Описание карты"
@@ -4991,18 +5006,12 @@ msgstr "СОБЫТИЯ"
msgid "LANGUAGE"
msgstr "ЯЗЫК"
msgid "ABOUT"
msgstr "О КАРТЕ"
msgid "Change Map Name"
msgstr "Изменить название карты"
msgid "Change Map Description"
msgstr "Изменить описание карты"
msgid "About"
msgstr "О карте"
msgid "Click to edit custom rumors."
msgstr "Нажмите, чтобы отредактировать пользовательские слухи."
@@ -5644,6 +5653,10 @@ msgstr "заново генерировать случайную карту"
msgid "hotkey|re-configure random map"
msgstr "изменить параметры случайной карты"
#, fuzzy
msgid "hotkey|output all text"
msgstr "прокрутка влево"
msgid "hotkey|roland campaign"
msgstr "кампания за роланда"
+23 -10
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2025-03-12 23:48+0100\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: \n"
@@ -21,6 +21,9 @@ msgstr ""
msgid "SELECT"
msgstr "ZVOĽ"
msgid "ABOUT"
msgstr ""
msgid "S"
msgstr "S"
@@ -534,11 +537,13 @@ msgid ""
msgstr ""
"Priekopa znižuje obranu každého o -%{count} a spomaľuje pohyb na polovicu."
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Rýchlosť: %{speed}"
msgid "Speed"
msgstr "Rýchlosť"
#, fuzzy
msgid "battleAnimation|Speed"
msgstr "Anexia"
msgid "Interface"
msgstr "Rozhranie"
@@ -2961,6 +2966,9 @@ msgstr "Poškodenie"
msgid "HP"
msgstr "Zdravie"
msgid "Speed"
msgstr "Rýchlosť"
msgid "Growth"
msgstr "Nárast"
@@ -3261,6 +3269,13 @@ msgstr ""
"Podmienky\n"
"prehry"
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Kliknutím sa vrátiš do hlavnej ponuky."
#, fuzzy
msgid "Map Description"
msgstr ""
@@ -5122,9 +5137,6 @@ msgstr ""
msgid "LANGUAGE"
msgstr ""
msgid "ABOUT"
msgstr ""
msgid "Change Map Name"
msgstr ""
@@ -5132,9 +5144,6 @@ msgstr ""
msgid "Change Map Description"
msgstr "Zvolený opis"
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to edit custom rumors."
msgstr "Klikni pre uloženie terajšej hry."
@@ -5806,6 +5815,10 @@ msgstr "nová mapa, náhodná"
msgid "hotkey|re-configure random map"
msgstr "nová mapa, náhodná"
#, fuzzy
msgid "hotkey|output all text"
msgstr "posun naľavo"
msgid "hotkey|roland campaign"
msgstr "kampaň roland"
+23 -19
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2026-02-24 17:38+0100\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: Swedish <[email protected]>\n"
@@ -21,6 +21,9 @@ msgstr ""
msgid "SELECT"
msgstr "VÄLJ"
msgid "ABOUT"
msgstr "OM"
msgid "S"
msgstr "S"
@@ -540,11 +543,13 @@ msgstr ""
"Vallgraven sänker en varelses Försvar med %{count} och avbryter dennes "
"rörelser genom vallgraven."
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Hastighet: %{speed}"
msgid "Speed"
msgstr "Hastighet"
#, fuzzy
msgid "battleAnimation|Speed"
msgstr "Animering"
msgid "Interface"
msgstr "Gränssnitt"
@@ -2923,6 +2928,9 @@ msgstr "Skada"
msgid "HP"
msgstr "HP"
msgid "Speed"
msgstr "Hastighet"
msgid "Growth"
msgstr "Tillväxt"
@@ -3219,6 +3227,13 @@ msgstr ""
"Förlust-\n"
"villkor"
msgid "About"
msgstr "Om"
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Klicka för att gå tillbaka till huvudmenyn."
msgid "Map Description"
msgstr "Kartbeskrivning"
@@ -4947,18 +4962,12 @@ msgstr "HÄNDELSER"
msgid "LANGUAGE"
msgstr "SPRÅK"
msgid "ABOUT"
msgstr "OM"
msgid "Change Map Name"
msgstr "Ändra Kartnamn"
msgid "Change Map Description"
msgstr "Ändra Kartbeskrivning"
msgid "About"
msgstr "Om"
msgid "Click to edit custom rumors."
msgstr "Klicka för att redigera anpassade rykten."
@@ -5597,6 +5606,10 @@ msgstr "Återgenerera slumpad karta"
msgid "hotkey|re-configure random map"
msgstr "Återkonfigurera slumpad karta"
#, fuzzy
msgid "hotkey|output all text"
msgstr "Skrolla vänster"
msgid "hotkey|roland campaign"
msgstr "Rolands kampanj"
@@ -12583,12 +12596,3 @@ msgstr "Han sa till henne: Jag bah... och hon svarade: Du bah..."
msgid "An unknown force is being resurrected..."
msgstr "En okänd kraft återuppstår..."
#~ msgid ""
#~ "You are about to change the map's language from %{oldLanguage} to "
#~ "%{newLanguage}. Some texts might not be displayed properly after this. Do "
#~ "you want to proceed?"
#~ msgstr ""
#~ "Du tänker ändra kartans språk från %{oldLanguage} till %{newLanguage}. En "
#~ "del texter kan eventuellt inte visas korrekt efter detta. Vill du "
#~ "fortfarande ändra språk?"
+22 -10
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2024-12-01 16:37+0300\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: Turkish <[email protected]>\n"
@@ -21,6 +21,9 @@ msgstr ""
msgid "SELECT"
msgstr "SEÇ"
msgid "ABOUT"
msgstr ""
msgid "S"
msgstr "S"
@@ -535,11 +538,12 @@ msgstr ""
"Hendek savunma becerisi herhangi bir birimin savunma becerisi ve hareket "
"hızını %{count} düşürüyor."
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Hız: %{speed}"
msgid "Speed"
msgstr "Hız"
msgid "battleAnimation|Speed"
msgstr ""
msgid "Interface"
msgstr "Arayüz"
@@ -2846,6 +2850,9 @@ msgstr ""
msgid "HP"
msgstr ""
msgid "Speed"
msgstr "Hız"
msgid "Growth"
msgstr ""
@@ -3126,6 +3133,13 @@ msgstr ""
"Yenilgi\n"
"Şartları"
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Savaş sonuçlarından çıkmak için tıklayın."
msgid "Map Description"
msgstr ""
@@ -4828,18 +4842,12 @@ msgstr "ETKİNLİKLER"
msgid "LANGUAGE"
msgstr "DİL"
msgid "ABOUT"
msgstr ""
msgid "Change Map Name"
msgstr ""
msgid "Change Map Description"
msgstr ""
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to edit custom rumors."
msgstr "Savaşı otomatik modda bitirmek istediğinizden emin misiniz?"
@@ -5461,6 +5469,10 @@ msgstr ""
msgid "hotkey|re-configure random map"
msgstr ""
#, fuzzy
msgid "hotkey|output all text"
msgstr "Sistem seçeneklerini özelleştirin"
msgid "hotkey|roland campaign"
msgstr ""
+23 -10
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2026-01-31 15:48+0200\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: \n"
@@ -21,6 +21,9 @@ msgstr ""
msgid "SELECT"
msgstr "ОБРАТИ"
msgid "ABOUT"
msgstr "ПРО МАПУ"
msgid "S"
msgstr "М"
@@ -548,11 +551,13 @@ msgstr ""
"Рів перериває будь-який рух через нього і зменшує навичку захисту військ, що "
"знаходяться в ньому, на %{count}."
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Швидкість: %{speed}"
msgid "Speed"
msgstr "Швидкість"
#, fuzzy
msgid "battleAnimation|Speed"
msgstr "Анімація"
msgid "Interface"
msgstr "Інтерфейс"
@@ -2944,6 +2949,9 @@ msgstr "Шкода"
msgid "HP"
msgstr "Здоров'я"
msgid "Speed"
msgstr "Швидкість"
msgid "Growth"
msgstr "Приріст"
@@ -3233,6 +3241,13 @@ msgid ""
"Conditions"
msgstr "Умови поразки"
msgid "About"
msgstr "Опис"
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Тицьніть для повернення до головного меню."
msgid "Map Description"
msgstr "Опис мапи"
@@ -4973,18 +4988,12 @@ msgstr "ПОДІЇ"
msgid "LANGUAGE"
msgstr "МОВА"
msgid "ABOUT"
msgstr "ПРО МАПУ"
msgid "Change Map Name"
msgstr "Змінити назву мапи"
msgid "Change Map Description"
msgstr "Змінити опис мапи"
msgid "About"
msgstr "Опис"
msgid "Click to edit custom rumors."
msgstr "Тицьніть, щоб редагувати власні чутки."
@@ -5622,6 +5631,10 @@ msgstr "перегенерувати випадкову мапу"
msgid "hotkey|re-configure random map"
msgstr "переналаштувати випадкову мапу"
#, fuzzy
msgid "hotkey|output all text"
msgstr "прокрутити ліворуч"
msgid "hotkey|roland campaign"
msgstr "кампанія Роланда"
+23 -10
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fheroes2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 13:59+0000\n"
"POT-Creation-Date: 2026-04-01 01:29+0000\n"
"PO-Revision-Date: 2024-02-20 08:49+0700\n"
"Last-Translator: fheroes2 team <[email protected]>\n"
"Language-Team: \n"
@@ -20,6 +20,9 @@ msgstr ""
msgid "SELECT"
msgstr "CHỌN"
msgid "ABOUT"
msgstr ""
msgid "S"
msgstr "S"
@@ -533,11 +536,13 @@ msgstr ""
"Hào giảm -%{count} kỹ năng phòng thủ của bất kỳ đơn vị nào và làm chậm một "
"nửa tốc độ di chuyển."
msgid "Speed: %{speed}"
#, fuzzy
msgid "battleAnimation|Speed: %{speed}"
msgstr "Tốc độ: %{speed}"
msgid "Speed"
msgstr "Tốc độ"
#, fuzzy
msgid "battleAnimation|Speed"
msgstr "Thôn tính"
msgid "Interface"
msgstr "Giao diện"
@@ -2965,6 +2970,9 @@ msgstr "Sát thương"
msgid "HP"
msgstr "Máu"
msgid "Speed"
msgstr "Tốc độ"
msgid "Growth"
msgstr "Sinh trưởng"
@@ -3268,6 +3276,13 @@ msgstr ""
"Điều kiện\n"
"Thua"
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to read notes from the map creator."
msgstr "Nhấp để quay lại màn hình chính."
#, fuzzy
msgid "Map Description"
msgstr ""
@@ -5123,9 +5138,6 @@ msgstr ""
msgid "LANGUAGE"
msgstr ""
msgid "ABOUT"
msgstr ""
msgid "Change Map Name"
msgstr ""
@@ -5133,9 +5145,6 @@ msgstr ""
msgid "Change Map Description"
msgstr "Chọn Mô tả"
msgid "About"
msgstr ""
#, fuzzy
msgid "Click to edit custom rumors."
msgstr "Nhấp để lưu trò chơi hiện tại."
@@ -5807,6 +5816,10 @@ msgstr "bản đồ mới ngẫu nhiên"
msgid "hotkey|re-configure random map"
msgstr "bản đồ mới ngẫu nhiên"
#, fuzzy
msgid "hotkey|output all text"
msgstr "cuộn trái"
msgid "hotkey|roland campaign"
msgstr "chiến dịch roland"
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -153,7 +153,7 @@ namespace fheroes2
return false;
}
_fileData[name] = Compression::zipData( data.data(), data.size() );
_fileData[name] = Compression::zipData( data.data(), data.size(), true );
return true;
}
+15 -4
View File
@@ -737,15 +737,26 @@ namespace fheroes2
}
const int32_t outWidth = out.width();
const int32_t inWidth = in.width();
const int32_t inHeight = in.height();
int32_t inWidth = in.width();
if ( outWidth < ( inWidth + outPos.x + std::max<int32_t>( shadowOffset.x, 0 ) ) ) {
inWidth = outWidth - ( outPos.x + std::max<int32_t>( shadowOffset.x, 0 ) );
}
int32_t inHeight = in.height();
if ( out.height() < ( inHeight + outPos.y + std::max<int32_t>( shadowOffset.y, 0 ) ) ) {
inHeight = out.height() - ( outPos.y + std::max<int32_t>( shadowOffset.y, 0 ) );
}
if ( inWidth <= 1 || inHeight <= 1 ) {
return;
}
const int32_t shadowOffsetX = std::min<int32_t>( shadowOffset.x, 0 );
const int32_t shadowOffsetY = std::min<int32_t>( shadowOffset.y, 0 );
const int32_t outStartOffset = outPos.x + shadowOffsetX + in.x() + ( outPos.y + shadowOffsetY + in.y() ) * outWidth;
// The shadow should not be outside of 'out' image.
assert( outStartOffset >= 0 && outWidth >= ( inWidth + outPos.x + std::max<int32_t>( shadowOffset.x, 0 ) )
&& out.height() >= ( inHeight + outPos.y + std::max<int32_t>( shadowOffset.y, 0 ) ) );
assert( outStartOffset >= 0 );
const int32_t absOffsetX = std::abs( shadowOffset.x );
const int32_t absOffsetY = std::abs( shadowOffset.y );
+7 -2
View File
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2019 - 2025 *
* Copyright (C) 2019 - 2026 *
* *
* Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 *
* Copyright (C) 2009 by Andrey Afletdinov <[email protected]> *
@@ -334,7 +334,7 @@ namespace
return pos ? ++pos : str;
}
class MOFile
class MOFile final
{
public:
MOFile() = default;
@@ -621,6 +621,11 @@ const char * Translation::gettext( const char * str )
return current ? current->ngettext( str, 0 ) : stripContext( str );
}
const char * Translation::getNonTranslated( const char * str )
{
return stripContext( str );
}
const char * Translation::ngettext( const char * str, const char * plural, const size_t n )
{
if ( current ) {
+4 -1
View File
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2019 - 2025 *
* Copyright (C) 2019 - 2026 *
* *
* Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 *
* Copyright (C) 2009 by Andrey Afletdinov <[email protected]> *
@@ -52,6 +52,9 @@ namespace Translation
// Converts the given string to lowercase in a locale aware way
std::string StringLower( std::string str );
// Use it only if you need the original English string but with stripped context.
const char * getNonTranslated( const char * str );
}
#define _( str ) Translation::gettext( str )
+4 -4
View File
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2019 - 2024 *
* Copyright (C) 2019 - 2026 *
* *
* Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 *
* Copyright (C) 2009 by Andrey Afletdinov <[email protected]> *
@@ -100,7 +100,7 @@ std::vector<uint8_t> Compression::unzipData( const uint8_t * src, const size_t s
return res;
}
std::vector<uint8_t> Compression::zipData( const uint8_t * src, const size_t srcSize )
std::vector<uint8_t> Compression::zipData( const uint8_t * src, const size_t srcSize, const bool isMaximumCompression )
{
if ( src == nullptr || srcSize == 0 ) {
return {};
@@ -120,7 +120,7 @@ std::vector<uint8_t> Compression::zipData( const uint8_t * src, const size_t src
return {};
}
const int ret = compress( res.data(), &dstSizeULong, src, srcSizeULong );
const int ret = compress2( res.data(), &dstSizeULong, src, srcSizeULong, isMaximumCompression ? Z_BEST_COMPRESSION : Z_DEFAULT_COMPRESSION );
if ( ret != Z_OK ) {
ERROR_LOG( "zlib error: " << ret )
@@ -160,7 +160,7 @@ bool Compression::unzipStream( IStreamBase & inputStream, OStreamBase & outputSt
bool Compression::zipStreamBuf( const IStreamBuf & inputStream, OStreamBase & outputStream )
{
const std::vector<uint8_t> zip = zipData( inputStream.data(), inputStream.size() );
const std::vector<uint8_t> zip = zipData( inputStream.data(), inputStream.size(), false );
if ( zip.empty() ) {
return false;
}
+3 -2
View File
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2019 - 2025 *
* Copyright (C) 2019 - 2026 *
* *
* Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 *
* Copyright (C) 2009 by Andrey Afletdinov <[email protected]> *
@@ -42,7 +42,8 @@ namespace Compression
std::vector<uint8_t> unzipData( const uint8_t * src, const size_t srcSize, size_t realSize = 0 );
// Zips the input data and returns the compressed data or an empty vector in case of an error.
std::vector<uint8_t> zipData( const uint8_t * src, const size_t srcSize );
// Set isMaximumCompression only when compressing data not during the gameplay.
std::vector<uint8_t> zipData( const uint8_t * src, const size_t srcSize, const bool isMaximumCompression );
// Reads & unzips the zipped chunk from the given input stream and writes it to the given output
// stream. Returns true on success or false on error.
+23 -6
View File
@@ -130,6 +130,8 @@ namespace
ICN::BUTTON_5_EVIL,
ICN::BUTTON_MAP_SELECT_GOOD,
ICN::BUTTON_MAP_SELECT_EVIL,
ICN::BUTTON_MAP_ABOUT_GOOD,
ICN::BUTTON_MAP_ABOUT_EVIL,
ICN::BUTTONS_NEW_GAME_MENU_GOOD,
ICN::BUTTONS_NEW_GAME_MENU_EVIL,
ICN::BUTTONS_EDITOR_MENU_GOOD,
@@ -385,10 +387,8 @@ namespace
fheroes2::AGG::GetICN( ICN::FONT, 0 );
fheroes2::AGG::GetICN( ICN::SMALFONT, 0 );
fheroes2::AGG::GetICN( ICN::BUTTON_GOOD_FONT_RELEASED, 0 );
fheroes2::AGG::GetICN( ICN::BUTTON_GOOD_FONT_PRESSED, 0 );
fheroes2::AGG::GetICN( ICN::BUTTON_EVIL_FONT_RELEASED, 0 );
fheroes2::AGG::GetICN( ICN::BUTTON_EVIL_FONT_PRESSED, 0 );
// Do not automatically load resources for button fonts as
// they are not stored in the original game resources.
_normalFont = _icnVsSprite[ICN::FONT];
_smallFont = _icnVsSprite[ICN::SMALFONT];
@@ -749,6 +749,14 @@ namespace
break;
}
case ICN::BUTTON_MAP_ABOUT_GOOD: {
_icnVsSprite[id].resize( 2 );
const char * text = fheroes2::getSupportedText( gettext_noop( "ABOUT" ), fheroes2::FontType::buttonReleasedWhite() );
getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], text, ICN::EMPTY_MAP_SELECT_BUTTON, ICN::UNKNOWN );
break;
}
case ICN::BUTTON_MAPSIZE_SMALL: {
_icnVsSprite[id].resize( 2 );
@@ -1464,6 +1472,7 @@ namespace
case ICN::BUTTON_HSCORES_VERTICAL_STANDARD_EVIL:
case ICN::BUTTON_GIFT_EVIL:
case ICN::BUTTON_MAP_SELECT_EVIL:
case ICN::BUTTON_MAP_ABOUT_EVIL:
case ICN::BUTTON_SMALL_ACCEPT_EVIL:
case ICN::BUTTON_SMALL_DECLINE_EVIL:
case ICN::BUTTON_SMALL_MAX_EVIL:
@@ -1490,6 +1499,9 @@ namespace
else if ( id == ICN::BUTTON_MAP_SELECT_EVIL ) {
goodButtonIcnID = ICN::BUTTON_MAP_SELECT_GOOD;
}
else if ( id == ICN::BUTTON_MAP_ABOUT_EVIL ) {
goodButtonIcnID = ICN::BUTTON_MAP_ABOUT_GOOD;
}
else if ( id == ICN::BUTTON_SMALL_RESTART_EVIL ) {
goodButtonIcnID = ICN::BUTTON_SMALL_RESTART_GOOD;
}
@@ -2538,6 +2550,10 @@ namespace
imageArray[249 - 32] = imageArray[100];
imageArray.erase( imageArray.begin() + 218, imageArray.end() );
}
// Add 32 empty images to the front of the array to have 1:1 correlation between character index and its corresponding image.
const fheroes2::Sprite firstSprite{ imageArray[0] };
imageArray.insert( imageArray.begin(), 32, firstSprite );
break;
}
case ICN::YELLOW_FONT:
@@ -4799,8 +4815,9 @@ namespace
case ICN::BUTTON_GOOD_FONT_PRESSED:
case ICN::BUTTON_EVIL_FONT_RELEASED:
case ICN::BUTTON_EVIL_FONT_PRESSED: {
generateBaseButtonFont( _icnVsSprite[ICN::BUTTON_GOOD_FONT_RELEASED], _icnVsSprite[ICN::BUTTON_GOOD_FONT_PRESSED],
_icnVsSprite[ICN::BUTTON_EVIL_FONT_RELEASED], _icnVsSprite[ICN::BUTTON_EVIL_FONT_PRESSED] );
// These aren't the original game resources and these images are being generated dynamically.
// So, we shouldn't do anything here.
// We could even assert this place as the engine shouldn't even call it.
break;
}
case ICN::HISCORE: {
+3
View File
@@ -1089,6 +1089,9 @@ namespace ICN
BUTTON_MAP_SELECT_GOOD,
BUTTON_MAP_SELECT_EVIL,
BUTTON_MAP_ABOUT_GOOD,
BUTTON_MAP_ABOUT_EVIL,
BUTTON_GUILDWELL_EXIT,
BUTTON_VIEWWORLD_EXIT_GOOD,
BUTTON_VIEWWORLD_EXIT_EVIL,
+13
View File
@@ -390,6 +390,11 @@ namespace
AI::OptimizeTroopsOrder( giverArmy );
BagArtifacts::exchangeArtifacts( taker, giver );
if ( Difficulty::isArtifactSortingAllowedForAI( Game::getDifficulty() ) ) {
left.GetBagArtifacts().sortFromWorstToBest();
right.GetBagArtifacts().sortFromWorstToBest();
}
}
void AIToCastle( Heroes & hero, const int32_t dstIndex )
@@ -486,6 +491,10 @@ namespace
captureCastle();
hero.IncreaseExperience( res.getAttackerExperience() );
if ( Difficulty::isArtifactSortingAllowedForAI( Game::getDifficulty() ) ) {
hero.GetBagArtifacts().sortFromWorstToBest();
}
}
// The defender won
else if ( res.isDefenderWin() && defender ) {
@@ -569,6 +578,10 @@ namespace
// The attacker won
if ( res.isAttackerWin() ) {
hero.IncreaseExperience( res.getAttackerExperience() );
if ( Difficulty::isArtifactSortingAllowedForAI( Game::getDifficulty() ) ) {
hero.GetBagArtifacts().sortFromWorstToBest();
}
}
// The defender won
else if ( res.isDefenderWin() ) {
+3 -3
View File
@@ -227,7 +227,7 @@ namespace
const Settings & conf = Settings::Get();
const int speed = conf.BattleSpeed();
std::string str = _( "Speed: %{speed}" );
std::string str = _( "battleAnimation|Speed: %{speed}" );
StringReplace( str, "%{speed}", speed );
uint32_t speedIcnIndex = 0;
if ( speed >= 8 ) {
@@ -238,7 +238,7 @@ namespace
}
const fheroes2::Sprite & speedIcon = fheroes2::AGG::GetICN( ICN::CSPANEL, speedIcnIndex );
fheroes2::drawOption( optionRoi, speedIcon, _( "Speed" ), std::move( str ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW );
fheroes2::drawOption( optionRoi, speedIcon, _( "battleAnimation|Speed" ), std::move( str ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW );
}
void drawInterfaceSettings( const fheroes2::Rect & optionRoi )
@@ -334,7 +334,7 @@ namespace
}
if ( le.isMouseRightButtonPressedInArea( windowSpeedRoi ) ) {
fheroes2::showStandardTextMessage( _( "Speed" ), _( "Set the speed of combat actions and animations." ), 0 );
fheroes2::showStandardTextMessage( _( "battleAnimation|Speed" ), _( "Set the speed of combat actions and animations." ), 0 );
}
else if ( le.isMouseRightButtonPressedInArea( windowInterfaceRoi ) ) {
fheroes2::showStandardTextMessage( _( "Interface Settings" ), _( "Change the interface settings of the game." ), 0 );
+27 -1
View File
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2019 - 2024 *
* Copyright (C) 2019 - 2026 *
* *
* Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 *
* Copyright (C) 2012 by Andrey Afletdinov <[email protected]> *
@@ -103,6 +103,32 @@ Battle::Unit * Battle::Graveyard::getLastUnit( const int32_t index ) const
return units.back();
}
void Battle::Graveyard::moveToLastIfPresent( Battle::Unit * unit )
{
assert( unit != nullptr && Board::isValidIndex( unit->GetHeadIndex() )
&& ( unit->isWide() ? Board::isValidIndex( unit->GetTailIndex() ) : !Board::isValidIndex( unit->GetTailIndex() ) ) );
Graveyard & graveyard = *this;
auto & headIndexMonsters = graveyard[unit->GetHeadIndex()];
auto iter = std::find( headIndexMonsters.begin(), headIndexMonsters.end(), unit );
if ( iter == headIndexMonsters.end() ) {
// The monster isn't dead. Nothing needs to be done.
return;
}
std::rotate( iter, iter + 1, headIndexMonsters.end() );
if ( unit->isWide() ) {
auto & tailIndexMonsters = graveyard[unit->GetTailIndex()];
iter = std::find( tailIndexMonsters.begin(), tailIndexMonsters.end(), unit );
assert( iter != tailIndexMonsters.end() );
std::rotate( iter, iter + 1, tailIndexMonsters.end() );
}
}
std::vector<Battle::Unit *> Battle::Graveyard::getUnits( const int32_t index ) const
{
const auto iter = find( index );
+5 -2
View File
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2019 - 2024 *
* Copyright (C) 2019 - 2026 *
* *
* Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 *
* Copyright (C) 2012 by Andrey Afletdinov <[email protected]> *
@@ -33,7 +33,7 @@ namespace Battle
{
class Unit;
class Graveyard : public std::map<int32_t, std::vector<Unit *>>
class Graveyard final : public std::map<int32_t, std::vector<Unit *>>
{
public:
Graveyard() = default;
@@ -50,6 +50,9 @@ namespace Battle
Unit * getLastUnit( const int32_t index ) const;
// In case of spells applied on dead monsters we have to put this monster on top of others to have proper animation.
void moveToLastIfPresent( Unit * unit );
std::vector<Unit *> getUnits( const int32_t index ) const;
};
}
+60 -46
View File
@@ -47,6 +47,7 @@
#include "battle_catapult.h"
#include "battle_cell.h"
#include "battle_command.h"
#include "battle_grave.h"
#include "battle_tower.h"
#include "battle_troop.h"
#include "bin_info.h"
@@ -88,30 +89,30 @@ class Kingdom;
namespace
{
const int32_t cellYOffset = -9;
constexpr int32_t cellYOffset = -9;
const int32_t turnOrderMonsterIconSize = 43; // in both directions.
constexpr int32_t turnOrderMonsterIconSize = 43; // in both directions.
// The parameters of castle buildings destruction by a catapult:
// Smoke cloud frame number, after which the building should be drawn as destroyed.
const int32_t castleBuildingDestroyFrame = 5;
constexpr int32_t castleBuildingDestroyFrame = 5;
// Bridge demolition second smoke cloud offset from the first one after the catapult attack.
const fheroes2::Point bridgeDestroySmokeOffset( -45, 65 );
constexpr fheroes2::Point bridgeDestroySmokeOffset( -45, 65 );
// Smoke cloud frame number, after which the bridge should be drawn as destroyed.
const int32_t bridgeDestroyFrame = 6;
constexpr int32_t bridgeDestroyFrame = 6;
// The number of frames the second smoke cloud is delayed by.
const int32_t bridgeDestroySmokeDelay = 2;
constexpr int32_t bridgeDestroySmokeDelay = 2;
const int32_t offsetForTextBar{ 32 };
constexpr int32_t offsetForTextBar{ 32 };
const int32_t maxElementsInBattleLog{ 6 };
constexpr int32_t maxElementsInBattleLog{ 6 };
// This value must be equal to the height of Normal font.
const int32_t battleLogElementHeight{ 17 };
constexpr int32_t battleLogElementHeight{ 17 };
const int32_t battleLogLastElementOffset{ 4 };
constexpr int32_t battleLogLastElementOffset{ 4 };
const int32_t battleLogElementWidth{ fheroes2::Display::DEFAULT_WIDTH - 32 - 16 };
constexpr int32_t battleLogElementWidth{ fheroes2::Display::DEFAULT_WIDTH - 32 - 16 };
struct LightningPoint
{
@@ -1377,7 +1378,6 @@ Battle::Interface::Interface( Arena & battleArena, const int32_t tileIndex )
popup.setBattleUIRect( _interfacePosition );
// cover
const bool trees = !Maps::ScanAroundObject( tileIndex, MP2::OBJ_TREES ).empty();
const Maps::Tile & tile = world.getTile( tileIndex );
const int groundType = tile.GetGround();
@@ -1392,10 +1392,12 @@ Battle::Interface::Interface( Arena & battleArena, const int32_t tileIndex )
_battleGroundIcn = ICN::CBKGDSRT;
_borderObjectsIcn = ICN::FRNG0004;
break;
case Maps::Ground::SNOW:
case Maps::Ground::SNOW: {
const bool trees = Maps::hasNearbyObject( tileIndex, MP2::OBJ_TREES );
_battleGroundIcn = trees ? ICN::CBKGSNTR : ICN::CBKGSNMT;
_borderObjectsIcn = trees ? ICN::FRNG0006 : ICN::FRNG0007;
break;
}
case Maps::Ground::SWAMP:
_battleGroundIcn = ICN::CBKGSWMP;
_borderObjectsIcn = ICN::FRNG0008;
@@ -1412,14 +1414,18 @@ Battle::Interface::Interface( Arena & battleArena, const int32_t tileIndex )
_battleGroundIcn = ICN::CBKGLAVA;
_borderObjectsIcn = ICN::FRNG0005;
break;
case Maps::Ground::DIRT:
case Maps::Ground::DIRT: {
const bool trees = Maps::hasNearbyObject( tileIndex, MP2::OBJ_TREES );
_battleGroundIcn = trees ? ICN::CBKGDITR : ICN::CBKGDIMT;
_borderObjectsIcn = trees ? ICN::FRNG0010 : ICN::FRNG0009;
break;
case Maps::Ground::GRASS:
}
case Maps::Ground::GRASS: {
const bool trees = Maps::hasNearbyObject( tileIndex, MP2::OBJ_TREES );
_battleGroundIcn = trees ? ICN::CBKGGRTR : ICN::CBKGGRMT;
_borderObjectsIcn = trees ? ICN::FRNG0011 : ICN::FRNG0012;
break;
}
case Maps::Ground::WATER:
_battleGroundIcn = ICN::CBKGWATR;
_borderObjectsIcn = ICN::FRNG0013;
@@ -1527,7 +1533,7 @@ void Battle::Interface::setStatus( const std::string & message, const bool top )
status.setMessage( "", false );
}
humanturn_redraw = true;
_needRedraw = true;
}
void Battle::Interface::UpdateContourColor()
@@ -1982,14 +1988,14 @@ void Battle::Interface::RedrawOpponentsFlags()
if ( _attackingOpponent ) {
const int icn = getFlagIcn( arena.getAttackingForce().GetColor() );
const fheroes2::Sprite & flag = fheroes2::AGG::GetICN( icn, ICN::getAnimatedIcnIndex( icn, 0, animation_flags_frame ) );
const fheroes2::Sprite & flag = fheroes2::AGG::GetICN( icn, ICN::getAnimatedIcnIndex( icn, 0, _flagAnimationFrameIndex ) );
fheroes2::Blit( flag, _mainSurface, _attackingOpponent->Offset().x + OpponentSprite::LEFT_HERO_X_OFFSET + flag.x(),
_attackingOpponent->Offset().y + OpponentSprite::LEFT_HERO_Y_OFFSET + flag.y() );
}
if ( _defendingOpponent ) {
const int icn = getFlagIcn( arena.getDefendingForce().GetColor() );
const fheroes2::Sprite & flag = fheroes2::AGG::GetICN( icn, ICN::getAnimatedIcnIndex( icn, 0, animation_flags_frame ) );
const fheroes2::Sprite & flag = fheroes2::AGG::GetICN( icn, ICN::getAnimatedIcnIndex( icn, 0, _flagAnimationFrameIndex ) );
fheroes2::Blit( flag, _mainSurface,
_defendingOpponent->Offset().x + fheroes2::Display::DEFAULT_WIDTH - OpponentSprite::RIGHT_HERO_X_OFFSET - ( flag.x() + flag.width() ),
_defendingOpponent->Offset().y + OpponentSprite::RIGHT_HERO_Y_OFFSET + flag.y(), true );
@@ -3066,7 +3072,7 @@ void Battle::Interface::HumanTurn( const Unit & unit, Actions & actions )
_highlightUnitMovementArea = nullptr;
_currentUnit = &unit;
humanturn_redraw = false;
_needRedraw = false;
humanturn_exit = false;
catapult_frame = 0;
@@ -3082,10 +3088,10 @@ void Battle::Interface::HumanTurn( const Unit & unit, Actions & actions )
Redraw();
std::string msg;
animation_flags_frame = 0;
// TODO: update delay types within the loop to avoid rendering slowdown.
const std::vector<Game::DelayType> delayTypes{ Game::BATTLE_FLAGS_DELAY };
_flagAnimationFrameIndex = 0;
const Board * board = Arena::GetBoard();
LocalEvent & le = LocalEvent::Get();
@@ -3098,7 +3104,7 @@ void Battle::Interface::HumanTurn( const Unit & unit, Actions & actions )
}
if ( _currentCellIndex != indexNew ) {
_currentCellIndex = indexNew;
humanturn_redraw = true;
_needRedraw = true;
}
_highlightUnitMovementArea = nullptr;
@@ -3113,20 +3119,20 @@ void Battle::Interface::HumanTurn( const Unit & unit, Actions & actions )
// update status
if ( msg != status.getMessage() ) {
status.setMessage( msg, false );
humanturn_redraw = true;
_needRedraw = true;
}
// animation troops
if ( IdleTroopsAnimation() ) {
humanturn_redraw = true;
_needRedraw = true;
}
CheckGlobalEvents( le );
// redraw arena
if ( humanturn_redraw ) {
if ( _needRedraw ) {
Redraw();
humanturn_redraw = false;
_needRedraw = false;
}
else if ( listlog && listlog->IsNeedRedraw() ) {
listlog->Redraw();
@@ -3170,7 +3176,7 @@ void Battle::Interface::HumanBattleTurn( const Unit & unit, Actions & actions, s
else if ( Game::HotKeyPressEvent( Game::HotKeyEvent::BATTLE_TOGGLE_TURN_ORDER_DISPLAY ) ) {
conf.setBattleShowTurnOrder( !conf.BattleShowTurnOrder() );
humanturn_redraw = true;
_needRedraw = true;
}
// Switch the auto combat mode on
else if ( Game::HotKeyPressEvent( Game::HotKeyEvent::BATTLE_TOGGLE_AUTO_COMBAT ) ) {
@@ -3244,7 +3250,7 @@ void Battle::Interface::HumanBattleTurn( const Unit & unit, Actions & actions, s
else if ( conf.BattleShowTurnOrder() && le.isMouseCursorPosInArea( _turnOrder.getRenderingRoi() ) ) {
cursor.SetThemes( Cursor::POINTER );
if ( _turnOrder.queueEventProcessing( *this, msg, _interfacePosition.getPosition(), highlightUnitMovementArea ) ) {
humanturn_redraw = true;
_needRedraw = true;
}
}
else if ( le.isMouseCursorPosInArea( _buttonAuto.area() ) ) {
@@ -3268,7 +3274,7 @@ void Battle::Interface::HumanBattleTurn( const Unit & unit, Actions & actions, s
if ( le.MouseClickLeft( _buttonSettings.area() ) ) {
_openBattleSettingsDialog();
humanturn_redraw = true;
_needRedraw = true;
}
else if ( le.isMouseRightButtonPressed() ) {
fheroes2::showStandardTextMessage( _( "System Options" ), _( "Allows you to customize the combat screen." ), Dialog::ZERO );
@@ -3305,7 +3311,7 @@ void Battle::Interface::HumanBattleTurn( const Unit & unit, Actions & actions, s
if ( le.MouseClickLeft( attackingOpponentArea ) ) {
ProcessingHeroDialogResult( arena.DialogBattleHero( *_attackingOpponent->GetHero(), true, status ), actions );
humanturn_redraw = true;
_needRedraw = true;
}
}
else {
@@ -3319,13 +3325,13 @@ void Battle::Interface::HumanBattleTurn( const Unit & unit, Actions & actions, s
if ( le.MouseClickLeft( attackingOpponentArea ) ) {
arena.DialogBattleHero( *_attackingOpponent->GetHero(), true, status );
humanturn_redraw = true;
_needRedraw = true;
}
}
if ( le.isMouseRightButtonPressedInArea( attackingOpponentArea ) ) {
arena.DialogBattleHero( *_attackingOpponent->GetHero(), false, status );
humanturn_redraw = true;
_needRedraw = true;
}
}
else if ( _defendingOpponent && le.isMouseCursorPosInArea( _defendingOpponent->GetArea() + _interfacePosition.getPosition() ) ) {
@@ -3342,7 +3348,7 @@ void Battle::Interface::HumanBattleTurn( const Unit & unit, Actions & actions, s
if ( le.MouseClickLeft( defendingOpponentArea ) ) {
ProcessingHeroDialogResult( arena.DialogBattleHero( *_defendingOpponent->GetHero(), true, status ), actions );
humanturn_redraw = true;
_needRedraw = true;
}
}
else {
@@ -3357,13 +3363,13 @@ void Battle::Interface::HumanBattleTurn( const Unit & unit, Actions & actions, s
if ( le.MouseClickLeft( defendingOpponentArea ) ) {
arena.DialogBattleHero( *_defendingOpponent->GetHero(), true, status );
humanturn_redraw = true;
_needRedraw = true;
}
}
if ( le.isMouseRightButtonPressedInArea( defendingOpponentArea ) ) {
arena.DialogBattleHero( *_defendingOpponent->GetHero(), false, status );
humanturn_redraw = true;
_needRedraw = true;
}
}
else if ( le.isMouseCursorPosInArea( battleFieldRect ) ) {
@@ -3416,7 +3422,7 @@ void Battle::Interface::HumanBattleTurn( const Unit & unit, Actions & actions, s
MouseLeftClickBoardAction( themes, *cell, isConfirmed, actions );
}
else if ( le.isMouseRightButtonPressed() && MousePressRightBoardAction( *cell ) ) {
humanturn_redraw = true;
_needRedraw = true;
}
else if ( le.isMouseLeftButtonPressedInArea( battleFieldRect ) ) {
if ( !le.isDragInProgress() && !_swipeAttack.isValid() ) {
@@ -3571,7 +3577,7 @@ void Battle::Interface::EventShowOptions()
_buttonSettings.drawOnPress();
_openBattleSettingsDialog();
_buttonSettings.drawOnRelease();
humanturn_redraw = true;
_needRedraw = true;
}
void Battle::Interface::_startAutoCombat( const Unit & unit, Actions & actions )
@@ -3581,7 +3587,7 @@ void Battle::Interface::_startAutoCombat( const Unit & unit, Actions & actions )
actions.emplace_back( Command::TOGGLE_AUTO_COMBAT, static_cast<std::underlying_type_t<PlayerColor>>( unit.GetCurrentOrArmyColor() ) );
humanturn_redraw = true;
_needRedraw = true;
humanturn_exit = true;
}
@@ -3589,7 +3595,7 @@ void Battle::Interface::_quickCombat( Actions & actions )
{
actions.emplace_back( Command::QUICK_COMBAT );
humanturn_redraw = true;
_needRedraw = true;
humanturn_exit = true;
}
@@ -3794,7 +3800,7 @@ void Battle::Interface::MouseLeftClickBoardAction( const int themes, const Cell
Dialog::ArmyInfo( *unitOnCell, Dialog::BUTTONS, unitOnCell->isReflect() );
humanturn_redraw = true;
_needRedraw = true;
break;
}
@@ -6036,6 +6042,13 @@ void Battle::Interface::_redrawActionStoneSpell( const Unit & target )
void Battle::Interface::_redrawActionResurrectSpell( Unit & target, const Spell & spell )
{
if ( !target.isValid() ) {
// TODO: the below logic doesn't work properly for cases when a 2-hex unit is being resurrected in relation to another 2-hex unit.
// This will require us to redo rendering sequence as we render from left to right and the right hex always has higher priority
// over left hex.
// Move the current monster to the top of a stack in graveyard if it exists there.
Battle::Arena::GetGraveyard()->moveToLastIfPresent( &target );
// Restore direction of the creature, since it could be killed when it was reflected.
target.UpdateDirection();
@@ -6980,8 +6993,9 @@ void Battle::Interface::RedrawBridgeAnimation( const bool bridgeDownAnimation )
_bridgeAnimation.currentFrameId = bridgeDownAnimation ? BridgeMovementAnimation::UP_POSITION : BridgeMovementAnimation::DOWN_POSITION;
if ( bridgeDownAnimation )
if ( bridgeDownAnimation ) {
AudioManager::PlaySound( M82::DRAWBRG );
}
while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_BRIDGE_DELAY } ) ) ) {
if ( bridgeDownAnimation ) {
@@ -7051,22 +7065,22 @@ void Battle::Interface::CheckGlobalEvents( LocalEvent & le )
// Animation of the currently active unit's contour
if ( Game::validateAnimationDelay( Game::BATTLE_SELECTED_UNIT_DELAY ) ) {
UpdateContourColor();
humanturn_redraw = true;
_needRedraw = true;
}
// Animation of flags and heroes idle.
if ( Game::validateAnimationDelay( Game::BATTLE_FLAGS_DELAY ) ) {
++animation_flags_frame;
humanturn_redraw = true;
++_flagAnimationFrameIndex;
_needRedraw = true;
// Perform heroes idle animation only if heroes are not performing any other animation (e.g. spell casting).
if ( Game::hasEveryDelayPassed( { Game::BATTLE_OPPONENTS_DELAY } ) ) {
if ( _attackingOpponent && _attackingOpponent->updateAnimationState() ) {
humanturn_redraw = true;
_needRedraw = true;
}
if ( _defendingOpponent && _defendingOpponent->updateAnimationState() ) {
humanturn_redraw = true;
_needRedraw = true;
}
}
}
@@ -7145,7 +7159,7 @@ void Battle::Interface::ProcessingHeroDialogResult( const int result, Actions &
if ( spell.isApplyWithoutFocusObject() ) {
actions.emplace_back( Command::SPELLCAST, spell.GetID(), -1 );
humanturn_redraw = true;
_needRedraw = true;
humanturn_exit = true;
}
else {
+5 -5
View File
@@ -128,7 +128,7 @@ namespace Battle
bool isReflectedImage{ false };
};
class OpponentSprite
class OpponentSprite final
{
public:
OpponentSprite( const fheroes2::Rect & area, HeroBase * hero, const bool isReflect );
@@ -269,12 +269,12 @@ namespace Battle
static void _redrawUnit( const fheroes2::Rect & pos, const Battle::Unit & unit, const bool revert, const uint8_t currentUnitColor, fheroes2::Image & output );
std::weak_ptr<const Units> _orderOfUnits;
PlayerColor _opponentColor{ PlayerColor::NONE };
fheroes2::Rect _renderingRoi;
fheroes2::Rect _battleRoi;
std::vector<UnitPos> _rects;
std::unique_ptr<fheroes2::ImageRestorer> _restorer;
PlayerColor _opponentColor{ PlayerColor::NONE };
bool _isInsideBattleField{ false };
};
@@ -314,7 +314,7 @@ namespace Battle
bool _needDelay{ true };
};
class Interface
class Interface final
{
public:
Interface( Arena & battleArena, const int32_t tileIndex );
@@ -500,8 +500,8 @@ namespace Battle
Spell humanturn_spell{ Spell::NONE };
bool humanturn_exit{ true };
bool humanturn_redraw{ true };
uint32_t animation_flags_frame{ 0 };
bool _needRedraw{ true };
uint32_t _flagAnimationFrameIndex{ 0 };
int catapult_frame{ 0 };
PlayerColor _interruptAutoCombatForColor{ PlayerColor::NONE };
+6 -7
View File
@@ -1323,7 +1323,6 @@ bool Castle::BuyBuilding( const uint32_t buildingType )
return true;
}
/* draw image castle to position */
void Castle::DrawImageCastle( const fheroes2::Point & pt ) const
{
fheroes2::Display & display = fheroes2::Display::instance();
@@ -1363,16 +1362,16 @@ void Castle::DrawImageCastle( const fheroes2::Point & pt ) const
return;
}
for ( uint32_t ii = 0; ii < 5; ++ii ) {
const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::OBJNTWBA, index + ii );
dst_pt.x = pt.x + ii * 32 + sprite.x();
for ( uint32_t i = 0; i < 5; ++i ) {
const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::OBJNTWBA, index + i );
dst_pt.x = pt.x + i * 32 + sprite.x();
dst_pt.y = pt.y + 3 * 32 + sprite.y();
fheroes2::Blit( sprite, display, dst_pt.x, dst_pt.y );
}
for ( uint32_t ii = 0; ii < 5; ++ii ) {
const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::OBJNTWBA, index + 5 + ii );
dst_pt.x = pt.x + ii * 32 + sprite.x();
for ( uint32_t i = 0; i < 5; ++i ) {
const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::OBJNTWBA, index + 5 + i );
dst_pt.x = pt.x + i * 32 + sprite.x();
dst_pt.y = pt.y + 4 * 32 + sprite.y();
fheroes2::Blit( sprite, display, dst_pt.x, dst_pt.y );
}
+1
View File
@@ -288,6 +288,7 @@ public:
void ActionPreBattle();
void ActionAfterBattle( const bool attackerWins );
// Draw image castle to position.
void DrawImageCastle( const fheroes2::Point & pt ) const;
CastleDialogReturnValue OpenDialog( const bool openConstructionWindow, const bool openMageGuildWindow, const bool fade, const bool renderBackgroundDialog );
+3 -3
View File
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2019 - 2025 *
* Copyright (C) 2019 - 2026 *
* *
* Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 *
* Copyright (C) 2009 by Andrey Afletdinov <[email protected]> *
@@ -208,12 +208,12 @@ Castle::ConstructionDialogResult Castle::_openConstructionDialog( uint32_t & dwe
// draw castle sprite
dst_pt.x = cur_pt.x + 459;
dst_pt.y = cur_pt.y + 5;
dst_pt.y = cur_pt.y + 6;
DrawImageCastle( dst_pt );
// castle name
const fheroes2::Text castleName( GetName(), fheroes2::FontType::smallWhite() );
castleName.draw( cur_pt.x + 538 - castleName.width() / 2, cur_pt.y + 3, display );
castleName.draw( cur_pt.x + 538 - castleName.width() / 2, cur_pt.y + 2, display );
dst_pt.y = cur_pt.y + 2;
+4 -4
View File
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2019 - 2025 *
* Copyright (C) 2019 - 2026 *
* *
* Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 *
* Copyright (C) 2009 by Andrey Afletdinov <[email protected]> *
@@ -231,9 +231,9 @@ void Castle::_openWell()
Monster( _race, GetActualDwelling( castleDwellings[4] ) ), Monster( _race, GetActualDwelling( castleDwellings[5] ) ) };
std::array<fheroes2::RandomMonsterAnimation, maxNumOfDwellings> monsterAnimInfo
= { fheroes2::RandomMonsterAnimation( castleMonster[0] ), fheroes2::RandomMonsterAnimation( castleMonster[1] ),
fheroes2::RandomMonsterAnimation( castleMonster[2] ), fheroes2::RandomMonsterAnimation( castleMonster[3] ),
fheroes2::RandomMonsterAnimation( castleMonster[4] ), fheroes2::RandomMonsterAnimation( castleMonster[5] ) };
= { fheroes2::RandomMonsterAnimation( castleMonster[0], false ), fheroes2::RandomMonsterAnimation( castleMonster[1], false ),
fheroes2::RandomMonsterAnimation( castleMonster[2], false ), fheroes2::RandomMonsterAnimation( castleMonster[3], false ),
fheroes2::RandomMonsterAnimation( castleMonster[4], false ), fheroes2::RandomMonsterAnimation( castleMonster[5], false ) };
fheroes2::Image background;
background._disableTransformLayer();
+2 -2
View File
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2019 - 2025 *
* Copyright (C) 2019 - 2026 *
* *
* Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 *
* Copyright (C) 2009 by Andrey Afletdinov <[email protected]> *
@@ -563,7 +563,7 @@ int Dialog::ArmyInfo( const Troop & troop, int flags, bool isReflected, const in
DrawMonsterInfo( pos_rt.getPosition(), troop );
const bool isAnimated = ( flags & BUTTONS ) != 0;
fheroes2::RandomMonsterAnimation monsterAnimation( troop );
fheroes2::RandomMonsterAnimation monsterAnimation( troop, true );
const fheroes2::Point monsterOffset( pos_rt.x + 520 / 4 + 16, pos_rt.y + 175 );
if ( !isAnimated ) {
monsterAnimation.reset();
+50 -4
View File
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2019 - 2025 *
* Copyright (C) 2019 - 2026 *
* *
* Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 *
* Copyright (C) 2009 by Andrey Afletdinov <[email protected]> *
@@ -21,6 +21,7 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <cassert>
#include <string>
#include <vector>
@@ -98,11 +99,43 @@ void Dialog::GameInfo()
fheroes2::Blit( window, display, dialogOffset.x, shadowOffset.y );
const fheroes2::Rect scenarioNameRoi{ 37 + shadowOffset.x, 29 + shadowOffset.y, 349, 19 };
const int32_t buttonAboutWidth = fheroes2::AGG::GetICN( ICN::BUTTON_MAP_ABOUT_GOOD, 0 ).width();
fheroes2::Button buttonAbout( dialogOffset.x + 401 - buttonAboutWidth, dialogOffset.y + 36, isEvilInterface ? ICN::BUTTON_MAP_ABOUT_EVIL : ICN::BUTTON_MAP_ABOUT_GOOD,
0, 1 );
const bool isCreatorInfoPresent{ !mapInfo.creatorNotes.empty() };
if ( isCreatorInfoPresent ) {
// Make sure that this is a Resurrection map.
assert( mapInfo.version == GameVersion::RESURRECTION );
buttonAbout.draw();
}
else {
buttonAbout.hide();
}
const int32_t scenarioNameMaxWidth{ 349 };
const fheroes2::Rect scenarioNameRoi{ 37 + shadowOffset.x, 29 + shadowOffset.y, scenarioNameMaxWidth - ( isCreatorInfoPresent ? buttonAboutWidth : 0 ), 19 };
fheroes2::Text text( mapInfo.name, fheroes2::FontType::normalWhite(), mapLanguage );
text.fitToOneRow( scenarioNameRoi.width );
text.draw( scenarioNameRoi.x, shadowOffset.y + 32, scenarioNameRoi.width, display );
// We deduct 2 to have at least 1 pixel space between text and text field borders.
text.fitToOneRow( scenarioNameRoi.width - 2 );
if ( isCreatorInfoPresent ) {
// We need to center the map name according to the center of the frame.
const int32_t noShiftWidth = scenarioNameMaxWidth - buttonAboutWidth * 2 - 2;
if ( text.width() <= noShiftWidth ) {
text.draw( scenarioNameRoi.x, shadowOffset.y + 32, scenarioNameMaxWidth, display );
}
else {
// It seems that we need to shift the scenario name to the left.
const int32_t offsetX = scenarioNameRoi.width - text.width() - 1;
text.draw( scenarioNameRoi.x + offsetX, shadowOffset.y + 32, display );
}
}
else {
text.draw( scenarioNameRoi.x, shadowOffset.y + 32, scenarioNameRoi.width, display );
}
text.set( _( "Map\nDifficulty" ), fheroes2::FontType::smallWhite() );
text.draw( shadowOffset.x + SCENARIO_MAP_DIFFICULTY_OFFSET, shadowOffset.y + 56, SCENARIO_INFO_VALUES_BOX_WIDTH, display );
@@ -174,10 +207,23 @@ void Dialog::GameInfo()
while ( le.HandleEvents() ) {
buttonOk.drawOnState( le.isMouseLeftButtonPressedAndHeldInArea( buttonOk.area() ) );
if ( isCreatorInfoPresent ) {
buttonAbout.drawOnState( le.isMouseLeftButtonPressedAndHeldInArea( buttonAbout.area() ) );
}
if ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyCloseWindow() ) {
break;
}
if ( isCreatorInfoPresent ) {
if ( le.MouseClickLeft( buttonAbout.area() ) ) {
fheroes2::showStandardTextMessage( _( "About" ), mapInfo.creatorNotes, Dialog::OK );
}
else if ( le.isMouseRightButtonPressedInArea( buttonAbout.area() ) ) {
fheroes2::showStandardTextMessage( _( "About" ), _( "Click to read notes from the map creator." ), Dialog::ZERO );
}
}
if ( le.isMouseRightButtonPressedInArea( scenarioDescripionRoi ) ) {
const fheroes2::Text header( _( "Map Description" ), fheroes2::FontType::normalYellow() );
const fheroes2::Text body( mapInfo.description, fheroes2::FontType::normalWhite(), mapLanguage );
+8 -1
View File
@@ -380,11 +380,18 @@ bool Dialog::inputString( const fheroes2::TextBase & title, const fheroes2::Text
}
charInsertPos = newPos;
}
else if ( ( le.getPressedKeyValue() == fheroes2::Key::KEY_DELETE ) || ( le.getPressedKeyValue() == fheroes2::Key::KEY_BACKSPACE ) ) {
// Character deletion shouldn't check any length as we are reducing the existing text.
// This is useful when the text is actually bigger that the text window and it is not possible to enter anything
// but we have to allow to delete characters.
charInsertPos = InsertKeySym( result, charInsertPos, le.getPressedKeyValue(), LocalEvent::getCurrentKeyModifiers() );
}
else {
// We should verify the height of the text before allowing to enter one more line.
std::string tmp = result;
const size_t tempCharInsertPos = InsertKeySym( tmp, charInsertPos, le.getPressedKeyValue(), LocalEvent::getCurrentKeyModifiers() );
if ( textInput.height( tmp ) <= textInputArea.height ) {
if ( !isMultiLine || ( textInput.height( tmp ) <= textInputArea.height ) ) {
result = std::move( tmp );
charInsertPos = tempCharInsertPos;
}
+122
View File
@@ -91,6 +91,12 @@
#include "world.h"
#include "world_object_uid.h"
#if defined( WITH_DEBUG )
#include <sstream>
#include "logging.h"
#endif
namespace fheroes2
{
class Image;
@@ -858,6 +864,119 @@ namespace
return allowedMonsters;
}
#if defined( WITH_DEBUG )
int32_t getObjectIndex( const Maps::Map_Format::MapFormat & mapFormat, const uint32_t uid, const Maps::ObjectGroup group )
{
for ( size_t i = 0; i < mapFormat.tiles.size(); ++i ) {
for ( const auto & objectInfo : mapFormat.tiles[i].objects ) {
if ( objectInfo.id == uid && objectInfo.group == group ) {
return static_cast<int32_t>( i );
}
}
}
// It could be a leftover object kept by the previous version of the Editor.
return -1;
}
std::string getAllMapTexts( const Maps::Map_Format::MapFormat & mapFormat )
{
std::ostringstream os;
os << "******* Map texts *******" << std::endl;
os << "------- Towns -------" << std::endl;
for ( const auto & [uid, castle] : mapFormat.castleMetadata ) {
if ( !castle.customName.empty() ) {
const int32_t index = getObjectIndex( mapFormat, uid, Maps::ObjectGroup::KINGDOM_TOWNS );
if ( index < 0 ) {
os << "!!! [absent object " << uid << "]: " << castle.customName << std::endl;
}
else {
os << "[" << ( index % mapFormat.width ) << ',' << ( index / mapFormat.width ) << "]: " << castle.customName << std::endl;
}
}
}
os << "------- Heroes -------" << std::endl;
for ( const auto & [uid, hero] : mapFormat.heroMetadata ) {
if ( !hero.customName.empty() ) {
int32_t index = getObjectIndex( mapFormat, uid, Maps::ObjectGroup::KINGDOM_HEROES );
if ( index < 0 ) {
// It could be a Jail object.
index = getObjectIndex( mapFormat, uid, Maps::ObjectGroup::ADVENTURE_MISCELLANEOUS );
}
if ( index < 0 ) {
os << "!!! [absent object " << uid << "]: " << hero.customName << std::endl;
}
else {
os << "[" << ( index % mapFormat.width ) << ',' << ( index / mapFormat.width ) << "]: " << hero.customName << std::endl;
}
}
}
os << "------- Sphinxes -------" << std::endl;
for ( const auto & [uid, sphinx] : mapFormat.sphinxMetadata ) {
if ( !sphinx.riddle.empty() ) {
const int32_t index = getObjectIndex( mapFormat, uid, Maps::ObjectGroup::ADVENTURE_MISCELLANEOUS );
if ( index < 0 ) {
os << "!!! [absent object " << uid << "]: " << sphinx.riddle << std::endl;
}
else {
os << "[" << ( index % mapFormat.width ) << ',' << ( index / mapFormat.width ) << "]: " << sphinx.riddle << std::endl;
}
os << " Answers:" << std::endl;
for ( const auto & answer : sphinx.answers ) {
os << " " << answer << std::endl;
}
}
}
os << "------- Events -------" << std::endl;
for ( const auto & [uid, event] : mapFormat.adventureMapEventMetadata ) {
if ( !event.message.empty() ) {
const int32_t index = getObjectIndex( mapFormat, uid, Maps::ObjectGroup::ADVENTURE_MISCELLANEOUS );
if ( index < 0 ) {
os << "!!! [absent object " << uid << "]: " << event.message << std::endl;
}
else {
os << "[" << ( index % mapFormat.width ) << ',' << ( index / mapFormat.width ) << "]: " << event.message << std::endl;
}
}
}
os << "------- Signs -------" << std::endl;
for ( const auto & [uid, sign] : mapFormat.signMetadata ) {
if ( !sign.message.empty() ) {
const int32_t index = getObjectIndex( mapFormat, uid, Maps::ObjectGroup::ADVENTURE_MISCELLANEOUS );
if ( index < 0 ) {
os << "!!! [absent object " << uid << "]: " << sign.message << std::endl;
}
else {
os << "[" << ( index % mapFormat.width ) << ',' << ( index / mapFormat.width ) << "]: " << sign.message << std::endl;
}
}
}
os << "------- Daily events -------" << std::endl;
for ( const auto & event : mapFormat.dailyEvents ) {
if ( !event.message.empty() ) {
os << "Day " << event.firstOccurrenceDay << ": " << event.message << std::endl;
}
}
os << "------- Rumors -------" << std::endl;
for ( const auto & rumor : mapFormat.rumors ) {
os << rumor << std::endl;
}
os << "******* End *******" << std::endl;
return os.str();
}
#endif
}
namespace Interface
@@ -1074,6 +1193,9 @@ namespace Interface
}
}
}
else if ( HotKeyPressEvent( Game::HotKeyEvent::EDITOR_OUTPUT_ALL_TEXT ) ) {
VERBOSE_LOG( getAllMapTexts( _mapFormat ) )
}
#endif
else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_SCROLL_LEFT ) ) {
if ( !_gameArea.isDragScroll() && conf.ScrollSpeed() != SCROLL_SPEED_NONE ) {
+13
View File
@@ -321,3 +321,16 @@ bool Difficulty::isBasicAIBattleLogicApplicable( const int32_t difficulty, const
return !isControlledByHuman;
}
bool Difficulty::isArtifactSortingAllowedForAI( const int32_t difficulty )
{
switch ( difficulty ) {
case Difficulty::EASY:
case Difficulty::NORMAL:
return false;
default:
break;
}
return true;
}
+2
View File
@@ -78,4 +78,6 @@ namespace Difficulty
bool allowAIToBuildCastleBuilding( const int difficulty, const bool isCampaign, const BuildingType building );
bool isBasicAIBattleLogicApplicable( const int32_t difficulty, const bool isControlledByHuman );
bool isArtifactSortingAllowedForAI( const int32_t difficulty );
}
+8 -10
View File
@@ -38,7 +38,6 @@
#include "battle_arena.h"
#include "dialog.h"
#include "game_interface.h"
#include "game_language.h"
#include "interface_gamearea.h"
#include "localevent.h"
#include "logging.h"
@@ -50,7 +49,6 @@
#include "tools.h"
#include "translations.h"
#include "ui_dialog.h"
#include "ui_language.h"
namespace
{
@@ -175,6 +173,8 @@ namespace
= { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|re-generate random map" ), fheroes2::Key::KEY_F5 };
hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::EDITOR_RANDOM_MAP_RECONFIGURE )]
= { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|re-configure random map" ), fheroes2::Key::KEY_F6 };
hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::EDITOR_OUTPUT_ALL_TEXT )]
= { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|output all text" ), fheroes2::Key::KEY_F2 };
#endif
hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::CAMPAIGN_ROLAND )]
@@ -346,22 +346,21 @@ namespace
os << std::endl;
Game::HotKeyCategory currentCategory = hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::NONE ) + 1].category;
os << "# " << getHotKeyCategoryName( currentCategory ) << ':' << std::endl;
os << "# " << Translation::getNonTranslated( getHotKeyCategoryName( currentCategory ) ) << ':' << std::endl;
#if defined( WITH_DEBUG )
std::set<const char *> duplicationStringVerifier;
#endif
const fheroes2::LanguageSwitcher languageSwitcher( fheroes2::SupportedLanguage::English );
for ( int32_t eventId = hotKeyEventToInt( Game::HotKeyEvent::NONE ) + 1; eventId < hotKeyEventToInt( Game::HotKeyEvent::NO_EVENT ); ++eventId ) {
if ( currentCategory != hotKeyEventInfo[eventId].category ) {
currentCategory = hotKeyEventInfo[eventId].category;
os << std::endl;
os << "# " << getHotKeyCategoryName( currentCategory ) << ':' << std::endl;
os << "# " << Translation::getNonTranslated( getHotKeyCategoryName( currentCategory ) ) << ':' << std::endl;
}
const char * eventName = _( hotKeyEventInfo[eventId].name );
// Use the original name without translation to keep the configuration file consistent for all languages.
const char * eventName = Translation::getNonTranslated( hotKeyEventInfo[eventId].name );
assert( strlen( eventName ) > 0 );
#if defined( WITH_DEBUG )
const bool isUnique = duplicationStringVerifier.emplace( eventName ).second;
@@ -445,10 +444,9 @@ void Game::HotKeysLoad( const std::string & filename )
nameToKey.try_emplace( StringUpper( KeySymGetName( key ) ), key );
}
const fheroes2::LanguageSwitcher languageSwitcher( fheroes2::SupportedLanguage::English );
for ( int eventId = hotKeyEventToInt( HotKeyEvent::NONE ) + 1; eventId < hotKeyEventToInt( HotKeyEvent::NO_EVENT ); ++eventId ) {
const char * eventName = _( hotKeyEventInfo[eventId].name );
// Load the original name without using translation.
const char * eventName = Translation::getNonTranslated( hotKeyEventInfo[eventId].name );
std::string value = config.StrParams( eventName );
if ( value.empty() ) {
// TODO: remove this temporary workaround
+1
View File
@@ -86,6 +86,7 @@ namespace Game
// TODO: remove these hotkeys when the time is right.
EDITOR_RANDOM_MAP_REGENERATE,
EDITOR_RANDOM_MAP_RECONFIGURE,
EDITOR_OUTPUT_ALL_TEXT,
#endif
CAMPAIGN_ROLAND,
+4830 -4555
View File
File diff suppressed because it is too large Load Diff
+1 -4
View File
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2022 - 2025 *
* Copyright (C) 2022 - 2026 *
* *
* 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 *
@@ -35,9 +35,6 @@ namespace fheroes2
bool isAlphabetSupported( const SupportedLanguage language );
void generateBaseButtonFont( std::vector<Sprite> & goodReleased, std::vector<Sprite> & goodPressed, std::vector<Sprite> & evilReleased,
std::vector<Sprite> & evilPressed );
void generateButtonAlphabet( const SupportedLanguage language, std::vector<std::vector<Sprite>> & icnVsSprite );
void modifyBaseNormalFont( std::vector<fheroes2::Sprite> & icnVsSprite );
+57
View File
@@ -75,13 +75,19 @@ namespace
// English is a default language so it is not considered as an extra language.
return false;
case fheroes2::SupportedLanguage::Belarusian:
case fheroes2::SupportedLanguage::Bulgarian:
case fheroes2::SupportedLanguage::Czech:
case fheroes2::SupportedLanguage::Danish:
case fheroes2::SupportedLanguage::French:
case fheroes2::SupportedLanguage::German:
case fheroes2::SupportedLanguage::Hungarian:
case fheroes2::SupportedLanguage::Norwegian:
case fheroes2::SupportedLanguage::Polish:
case fheroes2::SupportedLanguage::Portuguese:
case fheroes2::SupportedLanguage::Russian:
case fheroes2::SupportedLanguage::Slovak:
case fheroes2::SupportedLanguage::Spanish:
case fheroes2::SupportedLanguage::Swedish:
case fheroes2::SupportedLanguage::Ukrainian:
return true;
default:
@@ -382,14 +388,21 @@ namespace
// Numeric layout can be used for special letters as well.
switch ( language ) {
case fheroes2::SupportedLanguage::Belarusian:
case fheroes2::SupportedLanguage::Bulgarian:
case fheroes2::SupportedLanguage::Czech:
case fheroes2::SupportedLanguage::Danish:
case fheroes2::SupportedLanguage::English:
case fheroes2::SupportedLanguage::French:
case fheroes2::SupportedLanguage::German:
case fheroes2::SupportedLanguage::Greek:
case fheroes2::SupportedLanguage::Hungarian:
case fheroes2::SupportedLanguage::Norwegian:
case fheroes2::SupportedLanguage::Polish:
case fheroes2::SupportedLanguage::Portuguese:
case fheroes2::SupportedLanguage::Russian:
case fheroes2::SupportedLanguage::Slovak:
case fheroes2::SupportedLanguage::Spanish:
case fheroes2::SupportedLanguage::Swedish:
case fheroes2::SupportedLanguage::Ukrainian:
return { "1234567890", "-:;()_+=", "[].,!'?" };
default:
@@ -411,6 +424,8 @@ namespace
switch ( language ) {
case fheroes2::SupportedLanguage::Belarusian:
return { "\xC9\xD6\xD3\xCA\xC5\xCD\xC3\xD8\xA1\xC7\xD5\x92", "\xD4\xDB\xC2\xC0\xCF\xD0\xCE\xCB\xC4\xC6\xDD", "\xDF\xD7\xD1\xCC\xB2\xD2\xDC\xC1\xDE\xA8" };
case fheroes2::SupportedLanguage::Bulgarian:
return { "\xDB\xD3\xC5\xC8\xD8\xD9\xCA\xD1\xC7\xD6", "\xDC\xDF\xC0\xCE\xC6\xC3\xD2\xCD\xC2\xCC\xD7", "\xDE\xC9\xDA\xDD\xD4\xD5\xCF\xD0\xCB\xC1" };
case fheroes2::SupportedLanguage::Czech:
return { "\xCC\x8A\xC8\xD8\x8E\xDD\xC1\xCD\xC9", "QWERTZUIOP\xDA", "ASDFGHJKL\xD9", "YXCVBNM" };
case fheroes2::SupportedLanguage::Danish:
@@ -421,12 +436,24 @@ namespace
return { "\xC9\xC8\xC7\xC0\xC2\xCA\xCB\xCD\xCE\xCF\xDB\xDC", "AZERTYUIOP\xD4", "QSDFGHJKLM\xD9", "WXCVBN" };
case fheroes2::SupportedLanguage::German:
return { "QWERTZUIOP\xDC", "ASDFGHJKL\xD6\xC4", "YXCVBNM\xDF" };
case fheroes2::SupportedLanguage::Greek:
return { "\xF2\xC5\xC1\xD4\xD5\xC8\xC9\xCF\xD0", "\xC1\xD3\xC4\xD6\xC3\xC7\xCE\xCA\xCB", "\xC6\xD7\xD8\xD9\xC2\xCD\xCC" };
case fheroes2::SupportedLanguage::Hungarian:
return { "QWERTZUIOP\xD5\xDA\xDB", "ASDFGHJKL\xC9\xC1", "YXCVBNM\xD6\xDC\xD3" };
case fheroes2::SupportedLanguage::Norwegian:
return { "QWERTYUIOP\xC5", "ASDFGHJKL\xD8\xC6", "ZXCVBNM" };
case fheroes2::SupportedLanguage::Polish:
return { "\x8C\x8F\xA3\xA5\xAF\xC6\xCA\xD1\xD3", "QWERTYUIOP", "ASDFGHJKL", "ZXCVBNM" };
case fheroes2::SupportedLanguage::Portuguese:
return { "QWERTYUIOP", "ASDFGHJKL\xC7", "ZXCVBNM" };
case fheroes2::SupportedLanguage::Russian:
return { "\xC9\xD6\xD3\xCA\xC5\xCD\xC3\xD8\xD9\xC7\xD5\xDA", "\xD4\xDB\xC2\xC0\xCF\xD0\xCE\xCB\xC4\xC6\xDD", "\xDF\xD7\xD1\xCC\xC8\xD2\xDC\xC1\xDE\xA8" };
case fheroes2::SupportedLanguage::Slovak:
return { "\xCF\xBC\x8A\xC8\x8D\x8E\xDD\xC1\xCD\xC9\xD3", "QWERTZUIOP\xDA", "ASDFGHJKL\xD4\xD2", "\xC4YXCVBNM\xC5\xC0" };
case fheroes2::SupportedLanguage::Spanish:
return { "QWERTYUIOP", "ASDFGHJKL\xD1\xC7", "ZXCVBNM" };
case fheroes2::SupportedLanguage::Swedish:
return { "QWERTYUIOP\xC5", "ASDFGHJKL\xD6\xC4", "ZXCVBNM" };
case fheroes2::SupportedLanguage::Ukrainian:
return { "\xC9\xD6\xD3\xCA\xC5\xCD\xC3\xD8\xD9\xC7\xD5\xAF", "\xD4\xB2\xC2\xC0\xCF\xD0\xCE\xCB\xC4\xC6\xAA", "\xDF\xD7\xD1\xCC\xC8\xD2\xDC\xC1\xDE\xA5" };
default:
@@ -443,6 +470,8 @@ namespace
switch ( language ) {
case fheroes2::SupportedLanguage::Belarusian:
return { "\xE9\xF6\xF3\xEA\xE5\xED\xE3\xF8\xA2\xE7\xF5\x92", "\xF4\xFB\xE2\xE0\xEF\xF0\xEE\xEB\xE4\xE6\xFD", "\xFF\xF7\xF1\xEC\xB3\xF2\xFC\xE1\xFE\xB8" };
case fheroes2::SupportedLanguage::Bulgarian:
return { "\xFB\xF3\xE5\xE8\xF8\xF9\xEA\xF1\xE7\xF6", "\xFC\xFF\xE0\xEE\xE6\xE3\xF2\xED\xE2\xEC\xF7", "\xFE\xE9\xFA\xFD\xF4\xF5\xEF\xF0\xEB\xE1" };
case fheroes2::SupportedLanguage::Czech:
return { "\xEC\x9A\xE8\xF8\xBE\xFD\xE1\xED\xE9", "qwertzuiop\xFA", "asdfghjkl\xF9", "yxcvbnm" };
case fheroes2::SupportedLanguage::Danish:
@@ -453,12 +482,24 @@ namespace
return { "\xE9\xE8\xE7\xE0\xE2\xEA\xEB\xED\xEE\xEF\xFB\xFC", "azertyuiop\xF4", "qsdfghjklm\xF9", "wxcvbn" };
case fheroes2::SupportedLanguage::German:
return { "qwertzuiop\xFC", "asdfghjkl\xF6\xE4", "yxcvbnm\xDF" };
case fheroes2::SupportedLanguage::Greek:
return { "\xF2\xE5\xF1\xF4\xF5\xE8\xE9\xEF\xF0", "\xE1\xF3\xE4\xF6\xE3\xE7\xEE\xEA\xEB", "\xE6\xF7\xF8\xF9\xE2\xED\xEC" };
case fheroes2::SupportedLanguage::Hungarian:
return { "qwertzuiop\xF5\xFA\xFB", "asdfghjkl\xE9\xE1", "yxcvbnm\xF6\xFC\xF3" };
case fheroes2::SupportedLanguage::Norwegian:
return { "qwertyuiop\xE5", "asdfghjkl\xF8\xE6", "zxcvbnm" };
case fheroes2::SupportedLanguage::Polish:
return { "\x9C\x9F\xB3\xB9\xBF\xE6\xEA\xF1\xF3", "qwertyuiop", "asdfghjkl", "zxcvbnm" };
case fheroes2::SupportedLanguage::Portuguese:
return { "qwertyuiop", "asdfghjkl\xE7", "zxcvbnm" };
case fheroes2::SupportedLanguage::Russian:
return { "\xE9\xF6\xF3\xEA\xE5\xED\xE3\xF8\xF9\xE7\xF5\xFA", "\xF4\xFB\xE2\xE0\xEF\xF0\xEE\xEB\xE4\xE6\xFD", "\xFF\xF7\xF1\xEC\xE8\xF2\xFC\xE1\xFE\xB8" };
case fheroes2::SupportedLanguage::Slovak:
return { "\xEF\xBE\x9A\xE8\x9D\x9E\xFD\xE1\xED\xE9\xF3", "qwertzuiop\xFA", "asdfghjkl\xF4\xF2", "\xE4yxcvbnm\xE5\xE0" };
case fheroes2::SupportedLanguage::Spanish:
return { "qwertyuiop", "asdfghjkl\xF1\xE7", "zxcvbnm" };
case fheroes2::SupportedLanguage::Swedish:
return { "qwertyuiop\xE5", "asdfghjkl\xF6\xE4", "zxcvbnm" };
case fheroes2::SupportedLanguage::Ukrainian:
return { "\xE9\xF6\xF3\xEA\xE5\xED\xE3\xF8\xF9\xE7\xF5\xBF", "\xF4\xB3\xE2\xE0\xEF\xF0\xEE\xEB\xE4\xE6\xBA", "\xFF\xF7\xF1\xEC\xE8\xF2\xFC\xE1\xFE\xB4" };
default:
@@ -508,13 +549,21 @@ namespace
case fheroes2::SupportedLanguage::Polish:
return { 30, defaultButtonHeight };
case fheroes2::SupportedLanguage::Belarusian:
case fheroes2::SupportedLanguage::Bulgarian:
case fheroes2::SupportedLanguage::Danish:
case fheroes2::SupportedLanguage::German:
case fheroes2::SupportedLanguage::Greek:
case fheroes2::SupportedLanguage::Norwegian:
case fheroes2::SupportedLanguage::Portuguese:
case fheroes2::SupportedLanguage::Russian:
case fheroes2::SupportedLanguage::French:
case fheroes2::SupportedLanguage::Slovak:
case fheroes2::SupportedLanguage::Spanish:
case fheroes2::SupportedLanguage::Swedish:
case fheroes2::SupportedLanguage::Ukrainian:
return { 24, defaultButtonHeight };
case fheroes2::SupportedLanguage::Hungarian:
return { 21, defaultButtonHeight };
default:
// Did you add a new supported language? Add the value above!
assert( 0 );
@@ -717,18 +766,26 @@ namespace
{
switch ( language ) {
case fheroes2::SupportedLanguage::Belarusian:
case fheroes2::SupportedLanguage::Bulgarian:
case fheroes2::SupportedLanguage::Czech:
case fheroes2::SupportedLanguage::Danish:
case fheroes2::SupportedLanguage::English:
case fheroes2::SupportedLanguage::French:
case fheroes2::SupportedLanguage::German:
case fheroes2::SupportedLanguage::Greek:
case fheroes2::SupportedLanguage::Hungarian:
case fheroes2::SupportedLanguage::Norwegian:
case fheroes2::SupportedLanguage::Polish:
case fheroes2::SupportedLanguage::Portuguese:
case fheroes2::SupportedLanguage::Russian:
case fheroes2::SupportedLanguage::Slovak:
case fheroes2::SupportedLanguage::Spanish:
case fheroes2::SupportedLanguage::Swedish:
case fheroes2::SupportedLanguage::Ukrainian:
addExtraStandardButtons( buttons, layoutType, isEvilInterface, isExtraLanguageSupported );
break;
default:
// Did you add a new supported language? Add the value above!
assert( 0 );
break;
}
+21 -24
View File
@@ -58,19 +58,15 @@ namespace
const fheroes2::Sprite & getChar( const uint8_t character, const fheroes2::FontType & fontType )
{
if ( character < 0x21 ) {
return errorImage;
}
switch ( fontType.size ) {
case fheroes2::FontSize::SMALL:
switch ( fontType.color ) {
case fheroes2::FontColor::WHITE:
return fheroes2::AGG::GetICN( ICN::SMALFONT, character - 0x20 );
return fheroes2::AGG::GetICN( ICN::SMALFONT, character );
case fheroes2::FontColor::GRAY:
return fheroes2::AGG::GetICN( ICN::GRAY_SMALL_FONT, character - 0x20 );
return fheroes2::AGG::GetICN( ICN::GRAY_SMALL_FONT, character );
case fheroes2::FontColor::YELLOW:
return fheroes2::AGG::GetICN( ICN::YELLOW_SMALLFONT, character - 0x20 );
return fheroes2::AGG::GetICN( ICN::YELLOW_SMALLFONT, character );
default:
// Did you add a new font color? Add the corresponding logic for it!
assert( 0 );
@@ -80,15 +76,15 @@ namespace
case fheroes2::FontSize::NORMAL:
switch ( fontType.color ) {
case fheroes2::FontColor::WHITE:
return fheroes2::AGG::GetICN( ICN::FONT, character - 0x20 );
return fheroes2::AGG::GetICN( ICN::FONT, character );
case fheroes2::FontColor::GRAY:
return fheroes2::AGG::GetICN( ICN::GRAY_FONT, character - 0x20 );
return fheroes2::AGG::GetICN( ICN::GRAY_FONT, character );
case fheroes2::FontColor::YELLOW:
return fheroes2::AGG::GetICN( ICN::YELLOW_FONT, character - 0x20 );
return fheroes2::AGG::GetICN( ICN::YELLOW_FONT, character );
case fheroes2::FontColor::GOLDEN_GRADIENT:
return fheroes2::AGG::GetICN( ICN::GOLDEN_GRADIENT_FONT, character - 0x20 );
return fheroes2::AGG::GetICN( ICN::GOLDEN_GRADIENT_FONT, character );
case fheroes2::FontColor::SILVER_GRADIENT:
return fheroes2::AGG::GetICN( ICN::SILVER_GRADIENT_FONT, character - 0x20 );
return fheroes2::AGG::GetICN( ICN::SILVER_GRADIENT_FONT, character );
default:
// Did you add a new font color? Add the corresponding logic for it!
assert( 0 );
@@ -98,11 +94,11 @@ namespace
case fheroes2::FontSize::LARGE:
switch ( fontType.color ) {
case fheroes2::FontColor::WHITE:
return fheroes2::AGG::GetICN( ICN::WHITE_LARGE_FONT, character - 0x20 );
return fheroes2::AGG::GetICN( ICN::WHITE_LARGE_FONT, character );
case fheroes2::FontColor::GOLDEN_GRADIENT:
return fheroes2::AGG::GetICN( ICN::GOLDEN_GRADIENT_LARGE_FONT, character - 0x20 );
return fheroes2::AGG::GetICN( ICN::GOLDEN_GRADIENT_LARGE_FONT, character );
case fheroes2::FontColor::SILVER_GRADIENT:
return fheroes2::AGG::GetICN( ICN::SILVER_GRADIENT_LARGE_FONT, character - 0x20 );
return fheroes2::AGG::GetICN( ICN::SILVER_GRADIENT_LARGE_FONT, character );
default:
// Did you add a new font color? Add the corresponding logic for it!
assert( 0 );
@@ -112,9 +108,9 @@ namespace
case fheroes2::FontSize::BUTTON_RELEASED:
switch ( fontType.color ) {
case fheroes2::FontColor::WHITE:
return fheroes2::AGG::GetICN( ICN::BUTTON_GOOD_FONT_RELEASED, character - 0x20 );
return fheroes2::AGG::GetICN( ICN::BUTTON_GOOD_FONT_RELEASED, character );
case fheroes2::FontColor::GRAY:
return fheroes2::AGG::GetICN( ICN::BUTTON_EVIL_FONT_RELEASED, character - 0x20 );
return fheroes2::AGG::GetICN( ICN::BUTTON_EVIL_FONT_RELEASED, character );
default:
// Did you add a new font color? Add the corresponding logic for it!
assert( 0 );
@@ -124,9 +120,9 @@ namespace
case fheroes2::FontSize::BUTTON_PRESSED:
switch ( fontType.color ) {
case fheroes2::FontColor::WHITE:
return fheroes2::AGG::GetICN( ICN::BUTTON_GOOD_FONT_PRESSED, character - 0x20 );
return fheroes2::AGG::GetICN( ICN::BUTTON_GOOD_FONT_PRESSED, character );
case fheroes2::FontColor::GRAY:
return fheroes2::AGG::GetICN( ICN::BUTTON_EVIL_FONT_PRESSED, character - 0x20 );
return fheroes2::AGG::GetICN( ICN::BUTTON_EVIL_FONT_PRESSED, character );
default:
// Did you add a new font color? Add the corresponding logic for it!
assert( 0 );
@@ -148,13 +144,13 @@ namespace
{
switch ( fontSize ) {
case fheroes2::FontSize::SMALL:
return fheroes2::AGG::GetICNCount( ICN::SMALFONT ) + 0x20 - 1;
return fheroes2::AGG::GetICNCount( ICN::SMALFONT );
case fheroes2::FontSize::NORMAL:
case fheroes2::FontSize::LARGE:
return fheroes2::AGG::GetICNCount( ICN::FONT ) + 0x20 - 1;
return fheroes2::AGG::GetICNCount( ICN::FONT );
case fheroes2::FontSize::BUTTON_RELEASED:
case fheroes2::FontSize::BUTTON_PRESSED:
return fheroes2::AGG::GetICNCount( ICN::BUTTON_GOOD_FONT_RELEASED ) + 0x20 - 1;
return fheroes2::AGG::GetICNCount( ICN::BUTTON_GOOD_FONT_RELEASED );
default:
// Did you add a new font size? Please add implementation.
assert( 0 );
@@ -614,8 +610,9 @@ namespace fheroes2
const int32_t charWidth = charHandler.getWidth( *data );
if ( lineWidth + charWidth > maxWidth ) {
// Current character has exceeded the maximum line width.
if ( ( lineWidth != 0 ) && ( lineWidth + charWidth > maxWidth ) ) {
// Current character has exceeded the maximum line width
// and the character is not bigger than the maximum width.
if ( !_keepLineTrailingSpaces && isSpaceChar( *data ) ) {
// Current character could be a space character then current line is over.
+2 -2
View File
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2021 - 2025 *
* Copyright (C) 2021 - 2026 *
* *
* 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 *
@@ -380,7 +380,7 @@ namespace fheroes2
std::vector<Text> _texts;
};
class FontCharHandler
class FontCharHandler final
{
public:
explicit FontCharHandler( const FontType fontType );
+6
View File
@@ -41,7 +41,9 @@
#include "battle.h"
#include "castle.h"
#include "dialog.h"
#include "difficulty.h"
#include "direction.h"
#include "game.h"
#include "game_io.h"
#include "game_static.h"
#include "ground.h"
@@ -1458,6 +1460,10 @@ bool Heroes::PickupArtifact( const Artifact & art )
}
}
if ( isControlAI() && Difficulty::isArtifactSortingAllowedForAI( Game::getDifficulty() ) ) {
GetBagArtifacts().sortFromWorstToBest();
}
return true;
}
+2 -2
View File
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2019 - 2025 *
* Copyright (C) 2019 - 2026 *
* *
* Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 *
* Copyright (C) 2010 by Andrey Afletdinov <fheroes2@gmail.com> *
@@ -208,7 +208,7 @@ namespace
hero.Scout( dst );
hero.Move2Dest( dst );
hero.SpellCasted( Spell::DIMENSIONDOOR );
hero.GetPath().Reset();
hero.calculatePath( -1 );
// Clear previous hero position on radar.
I.getRadar().SetRenderArea( fromRoi );
+1 -1
View File
@@ -496,7 +496,7 @@ namespace
<< map.adventureMapEventMetadata << map.selectionObjectMetadata << map.capturableObjectsMetadata << map.monsterMetadata << map.artifactMetadata
<< map.resourceMetadata << map.translationInfo;
const std::vector<uint8_t> temp = Compression::zipData( compressed.data(), compressed.size() );
const std::vector<uint8_t> temp = Compression::zipData( compressed.data(), compressed.size(), false );
stream.putRaw( temp.data(), temp.size() );
+8 -2
View File
@@ -565,10 +565,16 @@ int32_t Maps::getFogTileCountToBeRevealed( const int32_t tileIndex, const int32_
Maps::Indexes Maps::ScanAroundObject( const int32_t center, const MP2::MapObjectType objectType, const bool ignoreHeroes )
{
Indexes results = getAroundIndexes( center );
const Indexes results = getAroundIndexes( center );
return MapsIndexesFilteredObject( results, objectType, ignoreHeroes );
}
bool Maps::hasNearbyObject( const int32_t center, const MP2::MapObjectType objectType )
{
const Indexes results = getAroundIndexes( center );
return std::any_of( results.cbegin(), results.cend(), [objectType]( const int32_t index ) { return world.getTile( index ).getMainObjectType() == objectType; } );
}
bool Maps::isValidForDimensionDoor( int32_t targetIndex, bool isWater )
{
const Maps::Tile & tile = world.getTile( targetIndex );
@@ -577,7 +583,7 @@ bool Maps::isValidForDimensionDoor( int32_t targetIndex, bool isWater )
Maps::Indexes Maps::ScanAroundObject( const int32_t center, const MP2::MapObjectType objectType )
{
Indexes results = getAroundIndexes( center );
const Indexes results = getAroundIndexes( center );
return MapsIndexesFilteredObject( results, objectType );
}
+3 -1
View File
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2019 - 2025 *
* Copyright (C) 2019 - 2026 *
* *
* Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 *
* Copyright (C) 2009 by Andrey Afletdinov <fheroes2@gmail.com> *
@@ -83,6 +83,8 @@ namespace Maps
Indexes ScanAroundObjectWithDistance( const int32_t center, const uint32_t dist, const MP2::MapObjectType objectType );
Indexes ScanAroundObject( const int32_t center, const MP2::MapObjectType objectType, const bool ignoreHeroes );
bool hasNearbyObject( const int32_t center, const MP2::MapObjectType objectType );
bool isValidForDimensionDoor( int32_t targetIndex, bool isWater );
// Checks if the tile is guarded by a monster
bool isTileUnderProtection( const int32_t tileIndex );
+13 -1
View File
@@ -194,6 +194,8 @@ void Maps::FileInfo::Reset()
mainLanguage = fheroes2::SupportedLanguage::English;
translations = {};
creatorNotes = {};
}
bool Maps::FileInfo::readMP2Map( std::string filePath, const bool isForEditor )
@@ -541,6 +543,8 @@ bool Maps::FileInfo::loadResurrectionMap( const Map_Format::BaseMapFormat & map,
translations.emplace_back( language );
}
creatorNotes = map.creatorNotes;
return true;
}
@@ -681,7 +685,7 @@ OStreamBase & Maps::operator<<( OStreamBase & stream, const FileInfo & fi )
return stream << fi.kingdomColors << fi.colorsAvailableForHumans << fi.colorsAvailableForComp << fi.colorsOfRandomRaces << fi.victoryConditionType << fi.compAlsoWins
<< fi.allowNormalVictory << fi.victoryConditionParams[0] << fi.victoryConditionParams[1] << fi.lossConditionType << fi.lossConditionParams[0]
<< fi.lossConditionParams[1] << fi.timestamp << fi.startWithHeroInFirstCastle << fi.version << fi.worldDay << fi.worldWeek << fi.worldMonth
<< fi.mainLanguage;
<< fi.mainLanguage << fi.creatorNotes;
}
IStreamBase & Maps::operator>>( IStreamBase & stream, FileInfo & fi )
@@ -721,6 +725,14 @@ IStreamBase & Maps::operator>>( IStreamBase & stream, FileInfo & fi )
stream >> fi.mainLanguage;
}
static_assert( LAST_SUPPORTED_FORMAT_VERSION < FORMAT_VERSION_1150_RELEASE, "Remove the logic below." );
if ( Game::GetVersionOfCurrentSaveFile() < FORMAT_VERSION_1150_RELEASE ) {
fi.creatorNotes = {};
}
else {
stream >> fi.creatorNotes;
}
return stream;
}
+3
View File
@@ -259,6 +259,9 @@ namespace Maps
// It is very unlikely that a player suddenly decides to switch a language in the middle of a playthrough.
std::vector<fheroes2::SupportedLanguage> translations;
// Optional field available only in Resurrection maps.
std::string creatorNotes;
private:
void FillUnions( const PlayerColorsSet side1Colors, const PlayerColorsSet side2Colors );
};
+7 -4
View File
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2021 - 2022 *
* Copyright (C) 2021 - 2026 *
* *
* 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 *
@@ -38,7 +38,7 @@ namespace fheroes2
return monsterAnimationSequence;
}
RandomMonsterAnimation::RandomMonsterAnimation( const Monster & monster )
RandomMonsterAnimation::RandomMonsterAnimation( const Monster & monster, const bool includeDeathAnimation )
: _reference( monster.GetID() )
, _icnID( fheroes2::getMonsterData( monster.GetID() ).icnId )
, _frameId( 0 )
@@ -56,8 +56,11 @@ namespace fheroes2
_addValidMove( Monster_Info::RANG_BOT );
_addValidMove( Monster_Info::MOVING );
_addValidMove( Monster_Info::MOVING );
_addValidMove( Monster_Info::WNCE );
_addValidMove( Monster_Info::KILL );
if ( includeDeathAnimation ) {
// Getting a hit or death animation.
_addValidMove( Monster_Info::WNCE );
_addValidMove( Monster_Info::KILL );
}
increment();
}
+3 -3
View File
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2021 - 2024 *
* Copyright (C) 2021 - 2026 *
* *
* 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 *
@@ -74,10 +74,10 @@ namespace fheroes2
{
const std::array<uint8_t, 15> & getMonsterAnimationSequence();
class RandomMonsterAnimation
class RandomMonsterAnimation final
{
public:
explicit RandomMonsterAnimation( const Monster & monster );
explicit RandomMonsterAnimation( const Monster & monster, const bool includeDeathAnimation );
RandomMonsterAnimation( const RandomMonsterAnimation & ) = delete;
+19 -1
View File
@@ -1399,8 +1399,9 @@ std::set<ArtifactSetData> BagArtifacts::assembleArtifactSetIfPossible()
// At this point, we have confirmed that all the artifact parts are present
// so remove the parts and then add the assembled artifact to BagArtifacts
for ( const int artifactId : setData.second )
for ( const int artifactId : setData.second ) {
RemoveArtifact( artifactId );
}
assembledArtifactSets.insert( setData.first );
PushArtifact( setData.first._assembledArtifactID );
@@ -1410,6 +1411,23 @@ std::set<ArtifactSetData> BagArtifacts::assembleArtifactSetIfPossible()
return assembledArtifactSets;
}
void BagArtifacts::sortFromWorstToBest()
{
if ( size() < 2 ) {
// Nothing to do here.
return;
}
std::sort( begin(), end(), []( const auto & left, const auto & right ) {
// No sorting should be done for Magic Book.
if ( left == Artifact::MAGIC_BOOK || right == Artifact::MAGIC_BOOK ) {
return false;
}
return left.getArtifactValue() < right.getArtifactValue();
} );
}
bool ArtifactSetData::operator<( const ArtifactSetData & other ) const
{
return _assembledArtifactID < other._assembledArtifactID;
+3
View File
@@ -341,6 +341,9 @@ public:
std::set<ArtifactSetData> assembleArtifactSetIfPossible();
// Useful only for AI heroes.
void sortFromWorstToBest();
std::string String() const;
};
+3 -2
View File
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2021 - 2025 *
* Copyright (C) 2021 - 2026 *
* *
* 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 *
@@ -27,6 +27,7 @@ enum SaveFileFormat : uint16_t
// !!! IMPORTANT !!!
// If you're adding a new version you must assign it to CURRENT_FORMAT_VERSION located at the bottom.
// If you're removing an old version you must assign the oldest available to LAST_SUPPORTED_FORMAT_VERSION located at the bottom.
FORMAT_VERSION_1150_RELEASE = 10033,
FORMAT_VERSION_1111_RELEASE = 10032,
FORMAT_VERSION_1109_RELEASE = 10031,
FORMAT_VERSION_1108_RELEASE = 10030,
@@ -53,5 +54,5 @@ enum SaveFileFormat : uint16_t
LAST_SUPPORTED_FORMAT_VERSION = FORMAT_VERSION_1005_RELEASE,
CURRENT_FORMAT_VERSION = FORMAT_VERSION_1111_RELEASE
CURRENT_FORMAT_VERSION = FORMAT_VERSION_1150_RELEASE
};