1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Merge remote-tracking branch 'origin/develop' into ban_stuff_on_water_maps

This commit is contained in:
Tomasz Zieliński 2023-07-19 12:05:30 +02:00
commit ad5081f9fe
41 changed files with 588 additions and 72 deletions

View File

@ -87,6 +87,10 @@
"vcmi.adventureOptions.showGrid.help" : "{Show Grid}\n\nShow the grid overlay, highlighting the borders between adventure map tiles.",
"vcmi.adventureOptions.borderScroll.hover" : "Border Scrolling",
"vcmi.adventureOptions.borderScroll.help" : "{Border Scrolling}\n\nScroll adventure map when cursor is adjacent to window edge. Can be disabled by holding down CTRL key.",
"vcmi.adventureOptions.infoBarCreatureManagement.hover" : "Info Panel Creature Management",
"vcmi.adventureOptions.infoBarCreatureManagement.help" : "{Info Panel Creature Management}\n\nAllows rearranging creatures in info panel instead of cycling between default components",
"vcmi.adventureOptions.leftButtonDrag.hover" : "Left Click Drag Map",
"vcmi.adventureOptions.leftButtonDrag.help" : "{Left Click Drag Map}\n\nWhen enabled, moving mouse with left button pressed will drag adventure map view",
"vcmi.adventureOptions.mapScrollSpeed1.hover": "",
"vcmi.adventureOptions.mapScrollSpeed5.hover": "",
"vcmi.adventureOptions.mapScrollSpeed6.hover": "",

View File

@ -68,6 +68,8 @@
"vcmi.adventureOptions.showGrid.help" : "{Показувати сітку}\n\n Відображає сітку, що показує межі між клітинками на мапі пригод.",
"vcmi.adventureOptions.borderScroll.hover" : "Прокрутка по краю",
"vcmi.adventureOptions.borderScroll.help" : "{{Прокрутка по краю}\n\nПрокручувати мапу пригод, коли курсор знаходиться біля краю вікна. Цю функцію можна вимкнути, утримуючи клавішу CTRL.",
"vcmi.adventureOptions.leftButtonDrag.hover" : "Переміщення мапи лівою кнопкою",
"vcmi.adventureOptions.leftButtonDrag.help" : "{Переміщення мапи лівою кнопкою}\n\nЯкщо увімкнено, переміщення миші з натиснутою лівою кнопкою буде перетягувати мапу пригод",
"vcmi.adventureOptions.mapScrollSpeed1.hover": "",
"vcmi.adventureOptions.mapScrollSpeed5.hover": "",
"vcmi.adventureOptions.mapScrollSpeed6.hover": "",

View File

@ -15,13 +15,20 @@ public class LanguageSettingDialog extends LauncherSettingDialog<String>
static
{
AVAILABLE_LANGUAGES.add("english");
AVAILABLE_LANGUAGES.add("czech");
AVAILABLE_LANGUAGES.add("chinese");
AVAILABLE_LANGUAGES.add("finnish");
AVAILABLE_LANGUAGES.add("french");
AVAILABLE_LANGUAGES.add("german");
AVAILABLE_LANGUAGES.add("hungarian");
AVAILABLE_LANGUAGES.add("italian");
AVAILABLE_LANGUAGES.add("korean");
AVAILABLE_LANGUAGES.add("polish");
AVAILABLE_LANGUAGES.add("portuguese");
AVAILABLE_LANGUAGES.add("russian");
AVAILABLE_LANGUAGES.add("spanish");
AVAILABLE_LANGUAGES.add("swedish");
AVAILABLE_LANGUAGES.add("turkish");
AVAILABLE_LANGUAGES.add("ukrainian");
AVAILABLE_LANGUAGES.add("other_cp1250");
AVAILABLE_LANGUAGES.add("other_cp1251");

View File

@ -572,7 +572,14 @@ void CPlayerInterface::garrisonsChanged(std::vector<const CGObjectInstance *> ob
auto * town = dynamic_cast<const CGTownInstance*>(object);
if (hero)
{
adventureInt->onHeroChanged(hero);
if(hero->inTownGarrison)
{
adventureInt->onTownChanged(hero->visitedTown);
}
}
if (town)
adventureInt->onTownChanged(town);
}

View File

@ -394,8 +394,9 @@ void AdventureMapInterface::onPlayerTurnStarted(PlayerColor playerID)
LOCPLINT->localState->setSelection(LOCPLINT->localState->getWanderingHero(0));
}
//show new day animation and sound on infobar
widget->getInfoBar()->showDate();
//show new day animation and sound on infobar, except for 1st day of the game
if (LOCPLINT->cb->getDate(Date::DAY) != 1)
widget->getInfoBar()->showDate();
onHeroChanged(nullptr);
Canvas canvas = Canvas::createFromSurface(screen);

View File

@ -27,6 +27,7 @@
#include "../gui/WindowHandler.h"
#include "../../CCallback.h"
#include "../../lib/CConfigHandler.h"
#include "../../lib/CGeneralTextHandler.h"
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/mapObjects/CGTownInstance.h"
@ -51,14 +52,22 @@ CInfoBar::VisibleHeroInfo::VisibleHeroInfo(const CGHeroInstance * hero)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
background = std::make_shared<CPicture>("ADSTATHR");
heroTooltip = std::make_shared<CHeroTooltip>(Point(0,0), hero);
if(settings["gameTweaks"]["infoBarCreatureManagement"].Bool())
heroTooltip = std::make_shared<CInteractableHeroTooltip>(Point(0,0), hero);
else
heroTooltip = std::make_shared<CHeroTooltip>(Point(0,0), hero);
}
CInfoBar::VisibleTownInfo::VisibleTownInfo(const CGTownInstance * town)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
background = std::make_shared<CPicture>("ADSTATCS");
townTooltip = std::make_shared<CTownTooltip>(Point(0,0), town);
if(settings["gameTweaks"]["infoBarCreatureManagement"].Bool())
townTooltip = std::make_shared<CInteractableTownTooltip>(Point(0,0), town);
else
townTooltip = std::make_shared<CTownTooltip>(Point(0,0), town);
}
CInfoBar::VisibleDateInfo::VisibleDateInfo()
@ -273,8 +282,16 @@ void CInfoBar::tick(uint32_t msPassed)
void CInfoBar::clickReleased(const Point & cursorPosition)
{
timerCounter = 0;
removeUsedEvents(TIME); //expiration trigger from just clicked element is not valid anymore
if(state == HERO || state == TOWN)
{
if(settings["gameTweaks"]["infoBarCreatureManagement"].Bool())
return;
showGameStatus();
}
else if(state == GAME)
showDate();
else
@ -297,11 +314,13 @@ void CInfoBar::hover(bool on)
CInfoBar::CInfoBar(const Rect & position)
: CIntObject(LCLICK | SHOW_POPUP | HOVER, position.topLeft()),
timerCounter(0),
state(EMPTY)
state(EMPTY),
listener(settings.listen["gameTweaks"]["infoBarCreatureManagement"])
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
pos.w = position.w;
pos.h = position.h;
listener(std::bind(&CInfoBar::OnInfoBarCreatureManagementChanged, this));
reset();
}
@ -309,6 +328,10 @@ CInfoBar::CInfoBar(const Point & position): CInfoBar(Rect(position.x, position.y
{
}
void CInfoBar::OnInfoBarCreatureManagementChanged()
{
showSelection();
}
void CInfoBar::setTimer(uint32_t msToTrigger)
{

View File

@ -10,6 +10,7 @@
#pragma once
#include "../gui/CIntObject.h"
#include "CConfigHandler.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -25,7 +26,9 @@ class CShowableAnim;
class CComponent;
class CComponentBox;
class CHeroTooltip;
class CInteractableHeroTooltip;
class CTownTooltip;
class CInteractableTownTooltip;
class CLabel;
class CMultiLineLabel;
@ -66,14 +69,14 @@ private:
class VisibleHeroInfo : public CVisibleInfo
{
std::shared_ptr<CHeroTooltip> heroTooltip;
std::shared_ptr<CIntObject> heroTooltip; //should have CHeroTooltip or CInteractableHeroTooltip;
public:
VisibleHeroInfo(const CGHeroInstance * hero);
};
class VisibleTownInfo : public CVisibleInfo
{
std::shared_ptr<CTownTooltip> townTooltip;
std::shared_ptr<CIntObject> townTooltip; //should have CTownTooltip or CInteractableTownTooltip;
public:
VisibleTownInfo(const CGTownInstance * town);
};
@ -140,6 +143,7 @@ private:
EState state;
uint32_t timerCounter;
bool shouldPopAll = false;
SettingsListener listener;
std::queue<std::pair<VisibleComponentInfo::Cache, int>> componentsQueue;
@ -191,5 +195,8 @@ public:
/// check if infobar is showed something about pickups
bool showingComponents();
/// event handler for custom listening on game setting change
void OnInfoBarCreatureManagementChanged();
};

View File

@ -287,8 +287,28 @@ void CHeroList::updateElement(const CGHeroInstance * hero)
void CHeroList::updateWidget()
{
listBox->resize(LOCPLINT->localState->getWanderingHeroes().size());
listBox->reset();
auto & heroes = LOCPLINT->localState->getWanderingHeroes();
listBox->resize(heroes.size());
for (size_t i = 0; i < heroes.size(); ++i)
{
auto item = std::dynamic_pointer_cast<CHeroItem>(listBox->getItem(i));
if (!item)
continue;
if (item->hero == heroes[i])
{
item->update();
}
else
{
listBox->reset();
break;
}
}
if (LOCPLINT->localState->getCurrentHero())
select(LOCPLINT->localState->getCurrentHero());
@ -364,8 +384,28 @@ void CTownList::updateElement(const CGTownInstance * town)
void CTownList::updateWidget()
{
listBox->resize(LOCPLINT->localState->getOwnedTowns().size());
listBox->reset();
auto & towns = LOCPLINT->localState->getOwnedTowns();
listBox->resize(towns.size());
for (size_t i = 0; i < towns.size(); ++i)
{
auto item = std::dynamic_pointer_cast<CTownItem>(listBox->getItem(i));
if (!item)
continue;
if (item->town == towns[i])
{
item->update();
}
else
{
listBox->reset();
break;
}
}
if (LOCPLINT->localState->getCurrentTown())
select(LOCPLINT->localState->getCurrentTown());

View File

@ -86,7 +86,7 @@ BattleWindow::BattleWindow(BattleInterface & owner):
else
tacticPhaseEnded();
addUsedEvents(KEYBOARD);
addUsedEvents(LCLICK | KEYBOARD);
}
void BattleWindow::createQueue()
@ -204,6 +204,16 @@ void BattleWindow::keyPressed(EShortcut key)
InterfaceObjectConfigurable::keyPressed(key);
}
void BattleWindow::clickPressed(const Point & cursorPosition)
{
if (owner.openingPlaying())
{
owner.openingEnd();
return;
}
InterfaceObjectConfigurable::clickPressed(cursorPosition);
}
void BattleWindow::tacticPhaseStarted()
{
auto menuBattle = widget<CIntObject>("menuBattle");

View File

@ -86,6 +86,7 @@ public:
void deactivate() override;
void keyPressed(EShortcut key) override;
bool captureThisKey(EShortcut key) override;
void clickPressed(const Point & cursorPosition) override;
void show(Canvas & to) override;
void showAll(Canvas & to) override;

View File

@ -172,6 +172,15 @@ void EventDispatcher::dispatchClosePopup(const Point & position)
void EventDispatcher::handleLeftButtonClick(const Point & position, bool isPressed)
{
// WARNING: this approach is NOT SAFE
// 1) We allow (un)registering elements when list itself is being processed/iterated
// 2) To avoid iterator invalidation we create a copy of this list for processing
// HOWEVER it is completely possible (as in, actually happen, no just theory) to:
// 1) element gets unregistered and deleted from lclickable
// 2) element is completely deleted, as in - destructor called, memory freed
// 3) new element is created *with exactly same address(!)
// 4) new element is registered and code will incorrectly assume that this element is still registered
// POSSIBLE SOLUTION: make EventReceivers inherit from create_shared_from this and store weak_ptr's in lists
auto hlp = lclickable;
for(auto & i : hlp)
{

View File

@ -29,11 +29,12 @@ MapViewActions::MapViewActions(MapView & owner, const std::shared_ptr<MapViewMod
: model(model)
, owner(owner)
, pinchZoomFactor(1.0)
, dragActive(false)
{
pos.w = model->getPixelsVisibleDimensions().x;
pos.h = model->getPixelsVisibleDimensions().y;
addUsedEvents(LCLICK | SHOW_POPUP | GESTURE | HOVER | MOVE | WHEEL);
addUsedEvents(LCLICK | SHOW_POPUP | DRAG | GESTURE | HOVER | MOVE | WHEEL);
}
void MapViewActions::setContext(const std::shared_ptr<IMapRendererContext> & context)
@ -43,10 +44,32 @@ void MapViewActions::setContext(const std::shared_ptr<IMapRendererContext> & con
void MapViewActions::clickPressed(const Point & cursorPosition)
{
int3 tile = model->getTileAtPoint(cursorPosition - pos.topLeft());
if (!settings["adventure"]["leftButtonDrag"].Bool())
{
int3 tile = model->getTileAtPoint(cursorPosition - pos.topLeft());
if(context->isInMap(tile))
adventureInt->onTileLeftClicked(tile);
if(context->isInMap(tile))
adventureInt->onTileLeftClicked(tile);
}
}
void MapViewActions::clickReleased(const Point & cursorPosition)
{
if (!dragActive && settings["adventure"]["leftButtonDrag"].Bool())
{
int3 tile = model->getTileAtPoint(cursorPosition - pos.topLeft());
if(context->isInMap(tile))
adventureInt->onTileLeftClicked(tile);
}
dragActive = false;
dragDistance = Point(0,0);
}
void MapViewActions::clickCancel(const Point & cursorPosition)
{
dragActive = false;
dragDistance = Point(0,0);
}
void MapViewActions::showPopupWindow(const Point & cursorPosition)
@ -67,6 +90,17 @@ void MapViewActions::wheelScrolled(int distance)
adventureInt->hotkeyZoom(distance * 4);
}
void MapViewActions::mouseDragged(const Point & cursorPosition, const Point & lastUpdateDistance)
{
dragDistance += lastUpdateDistance;
if (dragDistance.length() > 16)
dragActive = true;
if (dragActive && settings["adventure"]["leftButtonDrag"].Bool())
owner.onMapSwiped(lastUpdateDistance);
}
void MapViewActions::gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance)
{
owner.onMapSwiped(lastUpdateDistance);

View File

@ -22,7 +22,9 @@ class MapViewActions : public CIntObject
std::shared_ptr<MapViewModel> model;
std::shared_ptr<IMapRendererContext> context;
Point dragDistance;
double pinchZoomFactor;
bool dragActive;
void handleHover(const Point & cursorPosition);
@ -32,11 +34,14 @@ public:
void setContext(const std::shared_ptr<IMapRendererContext> & context);
void clickPressed(const Point & cursorPosition) override;
void clickReleased(const Point & cursorPosition) override;
void clickCancel(const Point & cursorPosition) override;
void showPopupWindow(const Point & cursorPosition) override;
void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;
void gesturePinch(const Point & centerPosition, double lastUpdateFactor) override;
void hover(bool on) override;
void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;
void mouseMoved(const Point & cursorPosition, const Point & lastUpdateDistance) override;
void mouseDragged(const Point & cursorPosition, const Point & lastUpdateDistance) override;
void wheelScrolled(int distance) override;
};

View File

@ -410,7 +410,19 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt * Owner, int x, int y, SlotID IID, CGa
pos.h = 64;
}
stackCount = std::make_shared<CLabel>(pos.w, pos.h, owner->smallIcons ? FONT_TINY : FONT_MEDIUM, ETextAlignment::BOTTOMRIGHT, Colors::WHITE);
int labelPosW = pos.w;
int labelPosH = pos.h;
if(Owner->layout == CGarrisonInt::ESlotsLayout::REVERSED_TWO_ROWS) //labels under icon
{
labelPosW = pos.w / 2 + 1;
labelPosH += 7;
}
ETextAlignment labelAlignment = Owner->layout == CGarrisonInt::ESlotsLayout::REVERSED_TWO_ROWS
? ETextAlignment::CENTER
: ETextAlignment::BOTTOMRIGHT;
stackCount = std::make_shared<CLabel>(labelPosW, labelPosH, owner->smallIcons ? FONT_TINY : FONT_MEDIUM, labelAlignment, Colors::WHITE);
update();
}
@ -488,7 +500,7 @@ void CGarrisonInt::addSplitBtn(std::shared_ptr<CButton> button)
void CGarrisonInt::createSlots()
{
int distance = interx + (smallIcons ? 32 : 58);
for(int i=0; i<2; i++)
for(int i = 0; i < 2; i++)
{
std::vector<std::shared_ptr<CGarrisonSlot>> garrisonSlots;
garrisonSlots.resize(7);
@ -499,14 +511,26 @@ void CGarrisonInt::createSlots()
garrisonSlots[elem.first.getNum()] = std::make_shared<CGarrisonSlot>(this, i*garOffset.x + (elem.first.getNum()*distance), i*garOffset.y, elem.first, static_cast<CGarrisonSlot::EGarrisonType>(i), elem.second);
}
}
for(int j=0; j<7; j++)
for(int j = 0; j < 7; j++)
{
if(!garrisonSlots[j])
garrisonSlots[j] = std::make_shared<CGarrisonSlot>(this, i*garOffset.x + (j*distance), i*garOffset.y, SlotID(j), static_cast<CGarrisonSlot::EGarrisonType>(i), nullptr);
if(twoRows && j>=4)
if(layout == ESlotsLayout::TWO_ROWS && j >= 4)
{
garrisonSlots[j]->moveBy(Point(-126, 37));
}
else if(layout == ESlotsLayout::REVERSED_TWO_ROWS)
{
if(j >= 3)
{
garrisonSlots[j]->moveBy(Point(-90, 49));
}
else
{
garrisonSlots[j]->moveBy(Point(36, 0));
}
}
}
vstd::concatenate(availableSlots, garrisonSlots);
}
@ -646,16 +670,16 @@ void CGarrisonInt::bulkSmartSplitStack(const CGarrisonSlot * selected)
}
CGarrisonInt::CGarrisonInt(int x, int y, int inx, const Point & garsOffset,
const CArmedInstance * s1, const CArmedInstance * s2,
bool _removableUnits, bool smallImgs, bool _twoRows)
: highlighted(nullptr),
inSplittingMode(false),
interx(inx),
garOffset(garsOffset),
pb(false),
smallIcons(smallImgs),
removableUnits(_removableUnits),
twoRows(_twoRows)
const CArmedInstance * s1, const CArmedInstance * s2,
bool _removableUnits, bool smallImgs, ESlotsLayout _layout)
: highlighted(nullptr),
inSplittingMode(false),
interx(inx),
garOffset(garsOffset),
pb(false),
smallIcons(smallImgs),
removableUnits(_removableUnits),
layout(_layout)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);

View File

@ -81,6 +81,13 @@ class CGarrisonInt :public CIntObject
bool checkSelected(const CGarrisonSlot * selected, TQuantity min = 0) const;
public:
enum class ESlotsLayout
{
ONE_ROW,
TWO_ROWS,
REVERSED_TWO_ROWS
};
int interx; ///< Space between slots
Point garOffset; ///< Offset between garrisons (not used if only one hero)
std::vector<std::shared_ptr<CButton>> splitButtons; ///< May be empty if no buttons
@ -89,9 +96,10 @@ public:
bool pb,
smallIcons, ///< true - 32x32 imgs, false - 58x64
removableUnits, ///< player Can remove units from up
twoRows, ///< slots Will be placed in 2 rows
owned[2]; ///< player Owns up or down army ([0] upper, [1] lower)
ESlotsLayout layout;
void selectSlot(CGarrisonSlot * slot); ///< @param slot null = deselect
const CGarrisonSlot * getSelection() const;
@ -123,13 +131,13 @@ public:
/// @param s1, s2 Top and bottom armies
/// @param _removableUnits You can take units from top
/// @param smallImgs Units images size 64x58 or 32x32
/// @param _twoRows Display slots in 2 row (1st row = 4 slots, 2nd = 3 slots)
/// @param _layout - when TWO_ROWS - Display slots in 2 rows (1st row = 4 slots, 2nd = 3 slots), REVERSED_TWO_ROWS = 3 slots in 1st row
CGarrisonInt(int x, int y, int inx,
const Point & garsOffset,
const CArmedInstance * s1, const CArmedInstance * s2 = nullptr,
bool _removableUnits = true,
bool smallImgs = false,
bool _twoRows = false);
const Point & garsOffset,
const CArmedInstance * s1, const CArmedInstance * s2 = nullptr,
bool _removableUnits = true,
bool smallImgs = false,
ESlotsLayout _layout = ESlotsLayout::ONE_ROW);
};
class CGarrisonHolder

View File

@ -303,6 +303,31 @@ CHeroTooltip::CHeroTooltip(Point pos, const CGHeroInstance * hero):
init(InfoAboutHero(hero, InfoAboutHero::EInfoLevel::DETAILED));
}
CInteractableHeroTooltip::CInteractableHeroTooltip(Point pos, const CGHeroInstance * hero):
CGarrisonInt(pos.x, pos.y+73, 4, Point(0, 0), hero, nullptr, true, true, CGarrisonInt::ESlotsLayout::REVERSED_TWO_ROWS)
{
init(InfoAboutHero(hero, InfoAboutHero::EInfoLevel::DETAILED));
}
void CInteractableHeroTooltip::init(const InfoAboutHero & hero)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
portrait = std::make_shared<CAnimImage>("PortraitsLarge", hero.portrait, 0, 3, 2-73);
title = std::make_shared<CLabel>(66, 2-73, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, hero.name);
if(hero.details)
{
for(size_t i = 0; i < hero.details->primskills.size(); i++)
labels.push_back(std::make_shared<CLabel>(75 + 28 * (int)i, 58-73, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE,
std::to_string(hero.details->primskills[i])));
labels.push_back(std::make_shared<CLabel>(158, 98-73, FONT_TINY, ETextAlignment::CENTER, Colors::WHITE, std::to_string(hero.details->mana)));
morale = std::make_shared<CAnimImage>("IMRL22", hero.details->morale + 3, 0, 5, 74-73);
luck = std::make_shared<CAnimImage>("ILCK22", hero.details->luck + 3, 0, 5, 91-73);
}
}
void CTownTooltip::init(const InfoAboutTown & town)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
@ -357,6 +382,55 @@ CTownTooltip::CTownTooltip(Point pos, const CGTownInstance * town)
init(InfoAboutTown(town, true));
}
CInteractableTownTooltip::CInteractableTownTooltip(Point pos, const CGTownInstance * town)
: CGarrisonInt(pos.x, pos.y+73, 4, Point(0, 0), town->getUpperArmy(), nullptr, true, true, CGarrisonInt::ESlotsLayout::REVERSED_TWO_ROWS)
{
init(InfoAboutTown(town, true));
}
void CInteractableTownTooltip::init(const InfoAboutTown & town)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
//order of icons in def: fort, citadel, castle, no fort
size_t fortIndex = town.fortLevel ? town.fortLevel - 1 : 3;
fort = std::make_shared<CAnimImage>("ITMCLS", fortIndex, 0, 105, 31-73);
assert(town.tType);
size_t iconIndex = town.tType->clientInfo.icons[town.fortLevel > 0][town.built >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
build = std::make_shared<CAnimImage>("itpt", iconIndex, 0, 3, 2-73);
title = std::make_shared<CLabel>(66, 2-73, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, town.name);
if(town.details)
{
hall = std::make_shared<CAnimImage>("ITMTLS", town.details->hallLevel, 0, 67, 31-73);
if(town.details->goldIncome)
{
income = std::make_shared<CLabel>(157, 58-73, FONT_TINY, ETextAlignment::CENTER, Colors::WHITE,
std::to_string(town.details->goldIncome));
}
if(town.details->garrisonedHero) //garrisoned hero icon
garrisonedHero = std::make_shared<CPicture>("TOWNQKGH", 149, 76-73);
if(town.details->customRes)//silo is built
{
if(town.tType->primaryRes == EGameResID::WOOD_AND_ORE )// wood & ore
{
res1 = std::make_shared<CAnimImage>("SMALRES", GameResID(EGameResID::WOOD), 0, 7, 75-73);
res2 = std::make_shared<CAnimImage>("SMALRES", GameResID(EGameResID::ORE), 0, 7, 88-73);
}
else
{
res1 = std::make_shared<CAnimImage>("SMALRES", town.tType->primaryRes, 0, 7, 81-73);
}
}
}
}
void MoraleLuckBox::set(const AFactionMember * node)
{
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);

View File

@ -10,6 +10,7 @@
#pragma once
#include "../gui/CIntObject.h"
#include "CGarrisonInt.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -80,6 +81,20 @@ public:
CHeroTooltip(Point pos, const CGHeroInstance * hero);
};
/// Class for HD mod-like interactable infobox tooltip. Does not have any background!
class CInteractableHeroTooltip : public CGarrisonInt
{
std::shared_ptr<CLabel> title;
std::shared_ptr<CAnimImage> portrait;
std::vector<std::shared_ptr<CLabel>> labels;
std::shared_ptr<CAnimImage> morale;
std::shared_ptr<CAnimImage> luck;
void init(const InfoAboutHero & hero);
public:
CInteractableHeroTooltip(Point pos, const CGHeroInstance * hero);
};
/// Class for town tooltip. Does not have any background!
/// background for infoBox: ADSTATCS
/// background for tooltip: TOWNQVBK
@ -99,6 +114,23 @@ public:
CTownTooltip(Point pos, const CGTownInstance * town);
};
/// Class for HD mod-like interactable infobox tooltip. Does not have any background!
class CInteractableTownTooltip : public CGarrisonInt
{
std::shared_ptr<CLabel> title;
std::shared_ptr<CAnimImage> fort;
std::shared_ptr<CAnimImage> hall;
std::shared_ptr<CAnimImage> build;
std::shared_ptr<CLabel> income;
std::shared_ptr<CPicture> garrisonedHero;
std::shared_ptr<CAnimImage> res1;
std::shared_ptr<CAnimImage> res2;
void init(const InfoAboutTown & town);
public:
CInteractableTownTooltip(Point pos, const CGTownInstance * town);
};
/// draws picture with creature on background, use Animated=true to get animation
class CCreaturePic : public CIntObject
{

View File

@ -772,7 +772,7 @@ CTownItem::CTownItem(const CGTownInstance * Town)
hall = std::make_shared<CTownInfo>( 69, 31, town, true);
fort = std::make_shared<CTownInfo>(111, 31, town, false);
garr = std::make_shared<CGarrisonInt>(313, 3, 4, Point(232,0), town->getUpperArmy(), town->visitingHero, true, true, true);
garr = std::make_shared<CGarrisonInt>(313, 3, 4, Point(232,0), town->getUpperArmy(), town->visitingHero, true, true, CGarrisonInt::ESlotsLayout::TWO_ROWS);
heroes = std::make_shared<HeroSlots>(town, Point(244,6), Point(475,6), garr, false);
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];

View File

@ -36,6 +36,14 @@ AdventureOptionsTab::AdventureOptionsTab()
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
setRedrawParent(true);
#ifdef VCMI_MOBILE
addConditional("mobile", true);
addConditional("desktop", false);
#else
addConditional("mobile", false);
addConditional("desktop", true);
#endif
const JsonNode config(ResourceID("config/widgets/settings/adventureOptionsTab.json"));
addCallback("playerHeroSpeedChanged", [this](int value)
{
@ -110,6 +118,14 @@ AdventureOptionsTab::AdventureOptionsTab()
{
return setBoolSetting("adventure", "borderScroll", value);
});
addCallback("infoBarCreatureManagementChanged", [](bool value)
{
return setBoolSetting("gameTweaks", "infoBarCreatureManagement", value);
});
addCallback("leftButtonDragChanged", [](bool value)
{
return setBoolSetting("adventure", "leftButtonDrag", value);
});
build(config);
std::shared_ptr<CToggleGroup> playerHeroSpeedToggle = widget<CToggleGroup>("heroMovementSpeedPicker");
@ -141,4 +157,11 @@ AdventureOptionsTab::AdventureOptionsTab()
std::shared_ptr<CToggleButton> borderScrollCheckbox = widget<CToggleButton>("borderScrollCheckbox");
borderScrollCheckbox->setSelected(settings["adventure"]["borderScroll"].Bool());
std::shared_ptr<CToggleButton> infoBarCreatureManagementCheckbox = widget<CToggleButton>("infoBarCreatureManagementCheckbox");
infoBarCreatureManagementCheckbox->setSelected(settings["gameTweaks"]["infoBarCreatureManagement"].Bool());
std::shared_ptr<CToggleButton> leftButtonDragCheckbox = widget<CToggleButton>("leftButtonDragCheckbox");
if (leftButtonDragCheckbox)
leftButtonDragCheckbox->setSelected(settings["adventure"]["leftButtonDrag"].Bool());
}

View File

@ -153,7 +153,7 @@
"language" : {
"type" : "string",
"description" : "Base language of the mod, before applying localizations. By default vcmi assumes English",
"enum" : [ "czech", "chinese", "english", "french", "german", "hungarian", "italian", "korean", "polish", "russian", "spanish", "ukrainian" ]
"enum" : [ "czech", "chinese", "english", "finnish", "french", "german", "hungarian", "italian", "korean", "polish", "portuguese", "russian", "spanish", "swedish", "turkish", "ukrainian" ]
},
"czech" : {
"$ref" : "#/definitions/localizable"
@ -164,6 +164,9 @@
"english" : {
"$ref" : "#/definitions/localizable"
},
"finnish" : {
"$ref" : "#/definitions/localizable"
},
"french" : {
"$ref" : "#/definitions/localizable"
},
@ -182,12 +185,21 @@
"polish" : {
"$ref" : "#/definitions/localizable"
},
"portuguese" : {
"$ref" : "#/definitions/localizable"
},
"russian" : {
"$ref" : "#/definitions/localizable"
},
"spanish" : {
"$ref" : "#/definitions/localizable"
},
"swedish" : {
"$ref" : "#/definitions/localizable"
},
"turkish" : {
"$ref" : "#/definitions/localizable"
},
"ukrainian" : {
"$ref" : "#/definitions/localizable"
},

View File

@ -59,12 +59,12 @@
},
"language" : {
"type" : "string",
"enum" : [ "english", "czech", "chinese", "french", "german", "hungarian", "italian", "korean", "polish", "russian", "spanish", "ukrainian" ],
"enum" : [ "english", "czech", "chinese", "finnish", "french", "german", "hungarian", "italian", "korean", "polish", "portuguese", "russian", "spanish", "swedish", "turkish", "ukrainian" ],
"default" : "english"
},
"gameDataLanguage" : {
"type" : "string",
"enum" : [ "auto", "english", "czech", "chinese", "french", "german", "hungarian", "italian", "korean", "polish", "russian", "spanish", "ukrainian", "other_cp1250", "other_cp1251", "other_cp1252" ],
"enum" : [ "auto", "english", "czech", "chinese", "finnish", "french", "german", "hungarian", "italian", "korean", "polish", "portuguese", "russian", "spanish", "swedish", "turkish", "ukrainian", "other_cp1250", "other_cp1251", "other_cp1252" ],
"default" : "auto"
},
"lastSave" : {
@ -191,7 +191,7 @@
"type" : "object",
"additionalProperties" : false,
"default" : {},
"required" : [ "heroMoveTime", "enemyMoveTime", "scrollSpeedPixels", "heroReminder", "quickCombat", "objectAnimation", "terrainAnimation", "alwaysSkipCombat", "borderScroll" ],
"required" : [ "heroMoveTime", "enemyMoveTime", "scrollSpeedPixels", "heroReminder", "quickCombat", "objectAnimation", "terrainAnimation", "alwaysSkipCombat", "borderScroll", "leftButtonDrag" ],
"properties" : {
"heroMoveTime" : {
"type" : "number",
@ -231,6 +231,10 @@
"defaultIOS" : false,
"defaultAndroid" : false,
"default" : true
},
"leftButtonDrag" : {
"type" : "boolean",
"default" : false
}
}
},
@ -499,7 +503,8 @@
"availableCreaturesAsDwellingLabel",
"compactTownCreatureInfo",
"infoBarPick",
"skipBattleIntroMusic"
"skipBattleIntroMusic",
"infoBarCreatureManagement"
],
"properties" : {
"showGrid" : {
@ -529,6 +534,10 @@
"skipBattleIntroMusic" : {
"type" : "boolean",
"default" : false
},
"infoBarCreatureManagement": {
"type" : "boolean",
"default" : false
}
}
}

View File

@ -340,6 +340,10 @@
},
{
"text": "vcmi.adventureOptions.borderScroll.hover"
},
{
"text": "vcmi.adventureOptions.leftButtonDrag.hover",
"created" : "desktop"
}
]
},
@ -373,6 +377,17 @@
"name": "borderScrollCheckbox",
"help": "vcmi.adventureOptions.borderScroll",
"callback": "borderScrollChanged"
},
{
"name": "infoBarCreatureManagementCheckbox",
"help": "vcmi.adventureOptions.infoBarCreatureManagement",
"callback": "infoBarCreatureManagementChanged"
},
{
"name": "leftButtonDragCheckbox",
"help": "vcmi.adventureOptions.leftButtonDrag",
"callback": "leftButtonDragChanged",
"created" : "desktop"
}
]
}

View File

@ -29,6 +29,14 @@ AboutProjectView::AboutProjectView(QWidget * parent)
ui->lineEditOperatingSystem->setText(QSysInfo::prettyProductName());
}
void AboutProjectView::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
ui->retranslateUi(this);
QWidget::changeEvent(event);
}
void AboutProjectView::on_updatesButton_clicked()
{
UpdateDialog::showUpdateDialog(true);

View File

@ -21,6 +21,7 @@ class AboutProjectView : public QWidget
{
Q_OBJECT
void changeEvent(QEvent *event) override;
public:
explicit AboutProjectView(QWidget * parent = 0);

View File

@ -127,7 +127,7 @@ QSize CSettingsView::getPreferredRenderingResolution()
return QSize(resX, resY);
}
#endif
return QApplication::primaryScreen()->geometry().size();
return QApplication::primaryScreen()->geometry().size() * QApplication::primaryScreen()->devicePixelRatio();
}
void CSettingsView::fillValidScalingRange()

View File

@ -198,6 +198,118 @@
<translation>Version</translation>
</message>
</context>
<context>
<name>CModListModel</name>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="42"/>
<source>Translation</source>
<translation>Traduction</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="43"/>
<source>Town</source>
<translation>Ville</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="44"/>
<source>Test</source>
<translation>Test</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="45"/>
<source>Templates</source>
<translation>Modèles</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="46"/>
<source>Spells</source>
<translation>Sorts</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="47"/>
<source>Music</source>
<translation>Musique</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="48"/>
<source>Sounds</source>
<translation>Sons</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="49"/>
<source>Skills</source>
<translation>Compétences</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="50"/>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="67"/>
<source>Other</source>
<translation>Autre</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="51"/>
<source>Objects</source>
<translation>Objets</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="52"/>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="53"/>
<source>Mechanics</source>
<translation>Mécanique</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="54"/>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="55"/>
<source>Interface</source>
<translation>Interface</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="56"/>
<source>Heroes</source>
<translation>Héros</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="57"/>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="58"/>
<source>Graphical</source>
<translation>Graphique</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="59"/>
<source>Expansion</source>
<translation>Extension</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="60"/>
<source>Creatures</source>
<translation>Créatures</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="61"/>
<source>Artifacts</source>
<translation>Artefacts</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="62"/>
<source>AI</source>
<translation>IA</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="170"/>
<source>Name</source>
<translation>Nom</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="173"/>
<source>Type</source>
<translation>Type</translation>
</message>
<message>
<location filename="../modManager/cmodlistmodel_moc.cpp" line="174"/>
<source>Version</source>
<translation>Version</translation>
</message>
</context>
<context>
<name>CModListView</name>
<message>
@ -920,7 +1032,7 @@ Heroes® of Might and Magic® III HD n&quot;est actuellement pas pris en charge
<message>
<location filename="../firstLaunch/firstlaunch_moc.ui" line="702"/>
<source>Interface Improvements</source>
<translation type="unfinished"></translation>
<translation>Améliorations de l'interface</translation>
</message>
<message>
<source>High Definition Support</source>
@ -939,7 +1051,7 @@ Heroes® of Might and Magic® III HD n&quot;est actuellement pas pris en charge
<message>
<location filename="../firstLaunch/firstlaunch_moc.ui" line="772"/>
<source>Install mod that provides various interface improvements, such as better interface for random maps and selectable actions in battles</source>
<translation type="unfinished"></translation>
<translation>Installer le mod qui fournit diverses améliorations d'interface, telles qu'une meilleure interface pour les cartes aléatoires et des actions sélectionnables dans les batailles</translation>
</message>
<message>
<location filename="../firstLaunch/firstlaunch_moc.ui" line="788"/>

View File

@ -136,7 +136,7 @@ MapFormatFeaturesH3M MapFormatFeaturesH3M::getFeaturesHOTA(uint32_t hotaVersion)
{
result.artifactsCount = 163; // + HotA artifacts
result.heroesCount = 178; // + Cove
result.heroesPortraitsCount = 185; // + Cove
result.heroesPortraitsCount = 186; // + Cove
}
if(hotaVersion == 3)
{

View File

@ -1737,7 +1737,7 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec
if(!object->spells.empty())
{
object->clear();
logGlobal->warn("Hero %s subID=%d has spells set twice (in map properties and on adventure map instance). Using the latter set...", object->getNameTextID(), object->subID);
logGlobal->debug("Hero %s subID=%d has spells set twice (in map properties and on adventure map instance). Using the latter set...", object->getNameTextID(), object->subID);
}
object->spells.insert(SpellID::PRESET); //placeholder "preset spells"

View File

@ -29,7 +29,7 @@ void MapIdentifiersH3M::loadMapping(std::map<IdentifierID, IdentifierID> & resul
for (auto entry : mapping.Struct())
{
IdentifierID sourceID (entry.second.Integer());
IdentifierID targetID (*VLC->modh->identifiers.getIdentifier(VLC->modh->scopeGame(), identifierName, entry.first));
IdentifierID targetID (*VLC->modh->identifiers.getIdentifier(entry.second.meta, identifierName, entry.first));
result[sourceID] = targetID;
}
@ -39,13 +39,13 @@ void MapIdentifiersH3M::loadMapping(const JsonNode & mapping)
{
for (auto entryFaction : mapping["buildings"].Struct())
{
FactionID factionID (*VLC->modh->identifiers.getIdentifier(VLC->modh->scopeGame(), "faction", entryFaction.first));
FactionID factionID (*VLC->modh->identifiers.getIdentifier(entryFaction.second.meta, "faction", entryFaction.first));
auto buildingMap = entryFaction.second;
for (auto entryBuilding : buildingMap.Struct())
{
BuildingID sourceID (entryBuilding.second.Integer());
BuildingID targetID (*VLC->modh->identifiers.getIdentifier(VLC->modh->scopeGame(), "building." + VLC->factions()->getById(factionID)->getJsonKey(), entryBuilding.first));
BuildingID targetID (*VLC->modh->identifiers.getIdentifier(entryBuilding.second.meta, "building." + VLC->factions()->getById(factionID)->getJsonKey(), entryBuilding.first));
mappingFactionBuilding[factionID][sourceID] = targetID;
}
@ -68,7 +68,7 @@ void MapIdentifiersH3M::loadMapping(const JsonNode & mapping)
{
for (auto entryInner : entryOuter.second.Struct())
{
auto handler = VLC->objtypeh->getHandlerFor( VLC->modh->scopeGame(), entryOuter.first, entryInner.first);
auto handler = VLC->objtypeh->getHandlerFor( entryInner.second.meta, entryOuter.first, entryInner.first);
auto entryValues = entryInner.second.Vector();
ObjectTypeIdentifier h3mID{Obj(entryValues[0].Integer()), int32_t(entryValues[1].Integer())};
@ -78,7 +78,7 @@ void MapIdentifiersH3M::loadMapping(const JsonNode & mapping)
}
else
{
auto handler = VLC->objtypeh->getHandlerFor( VLC->modh->scopeGame(), entryOuter.first, entryOuter.first);
auto handler = VLC->objtypeh->getHandlerFor( entryOuter.second.meta, entryOuter.first, entryOuter.first);
auto entryValues = entryOuter.second.Vector();
ObjectTypeIdentifier h3mID{Obj(entryValues[0].Integer()), int32_t(entryValues[1].Integer())};
@ -90,7 +90,7 @@ void MapIdentifiersH3M::loadMapping(const JsonNode & mapping)
for (auto entry : mapping["portraits"].Struct())
{
int32_t sourceID = entry.second.Integer();
int32_t targetID = *VLC->modh->identifiers.getIdentifier(VLC->modh->scopeGame(), "hero", entry.first);
int32_t targetID = *VLC->modh->identifiers.getIdentifier(entry.second.meta, "hero", entry.first);
int32_t iconID = VLC->heroTypes()->getByIndex(targetID)->getIconIndex();
mappingHeroPortrait[sourceID] = iconID;

View File

@ -344,6 +344,16 @@ void Object::Instance::finalize(RmgMap & map)
setTemplate(terrainType->getId());
}
}
if (dObject.ID == Obj::MONSTER)
{
//Make up for extra offset in HotA creature templates
auto visitableOffset = dObject.getVisitableOffset();
auto fixedPos = getPosition(true) + visitableOffset;
vstd::abetween(fixedPos.x, visitableOffset.x, map.width() - 1);
vstd::abetween(fixedPos.y, visitableOffset.y, map.height() - 1);
int3 parentPos = getPosition(true) - getPosition(false);
setPosition(fixedPos - parentPos);
}
if (dObject.isVisitable() && !map.isOnMap(dObject.visitablePos()))
throw rmgException(boost::to_string(boost::format("Visitable tile %s of object %d at %s is outside the map") % dObject.visitablePos().toString() % dObject.id % dObject.pos.toString()));

View File

@ -334,7 +334,17 @@ void ConnectionsPlacer::selfSideIndirectConnection(const rmg::ZoneConnection & c
if(dist < minDist || otherDist < minDist)
return -1.f;
//This could fail is accessibleArea is below the map
rmg::Area toPlace(rmgGate1.getArea() + rmgGate1.getAccessibleArea());
auto inTheMap = toPlace.getTilesVector();
toPlace.clear();
for (const int3& tile : inTheMap)
{
if (map.isOnMap(tile))
{
toPlace.add(tile);
}
}
toPlace.translate(-zShift);
path2 = managerOther.placeAndConnectObject(toPlace, rmgGate2, minDist, guarded2, true, ObjectManager::OptimizeType::NONE);

View File

@ -606,8 +606,6 @@ bool ObjectManager::addGuard(rmg::Object & object, si32 strength, bool zoneGuard
auto & instance = object.addInstance(*guard);
instance.setPosition(guardPos - object.getPosition());
instance.setAnyTemplate(); //terrain is irrelevant for monsters, but monsters need some template now
//Make up for extra offset in HotA creature templates
instance.setPosition(instance.getPosition() + instance.object().getVisitableOffset());
return true;
}

View File

@ -919,7 +919,7 @@
</action>
<action name="actionSave_as">
<property name="text">
<string>Save as</string>
<string>Save as...</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+S</string>
@ -1231,7 +1231,7 @@
</action>
<action name="actionExport">
<property name="text">
<string>Export as</string>
<string>Export as...</string>
</property>
</action>
</widget>

View File

@ -136,7 +136,7 @@
</message>
<message>
<location filename="../mainwindow.ui" line="921"/>
<source>Save as</source>
<source>Save as...</source>
<translation type="unfinished"></translation>
</message>
<message>
@ -281,6 +281,11 @@
<source>Player 8</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="1233"/>
<source>Export as...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="346"/>
<source>Open map</source>

View File

@ -138,7 +138,7 @@
</message>
<message>
<location filename="../mainwindow.ui" line="921"/>
<source>Save as</source>
<source>Save as...</source>
<translation>Enregistrer sous...</translation>
</message>
<message>
@ -278,16 +278,16 @@
<source>Player 7</source>
<translation>Joueur 7</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="1233"/>
<source>Export as</source>
<translation>Exporter sous...</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="1225"/>
<source>Player 8</source>
<translation>Joueur 8</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="1233"/>
<source>Export as...</source>
<translation>Exporter sous...</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="346"/>
<source>Open map</source>

View File

@ -136,7 +136,7 @@
</message>
<message>
<location filename="../mainwindow.ui" line="921"/>
<source>Save as</source>
<source>Save as...</source>
<translation>Speichern unter</translation>
</message>
<message>
@ -281,6 +281,11 @@
<source>Player 8</source>
<translation>Spieler 8</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="1233"/>
<source>Export as...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="346"/>
<source>Open map</source>

View File

@ -136,7 +136,7 @@
</message>
<message>
<location filename="../mainwindow.ui" line="921"/>
<source>Save as</source>
<source>Save as...</source>
<translation>Zapisz jako</translation>
</message>
<message>
@ -281,6 +281,11 @@
<source>Player 8</source>
<translation>Gracz 8</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="1233"/>
<source>Export as...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="346"/>
<source>Open map</source>

View File

@ -136,7 +136,7 @@
</message>
<message>
<location filename="../mainwindow.ui" line="921"/>
<source>Save as</source>
<source>Save as...</source>
<translation>Сохранить как</translation>
</message>
<message>
@ -281,6 +281,11 @@
<source>Player 8</source>
<translation>Игрок 8</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="1233"/>
<source>Export as...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="346"/>
<source>Open map</source>

View File

@ -138,8 +138,8 @@
</message>
<message>
<location filename="../mainwindow.ui" line="921"/>
<source>Save as</source>
<translation>Guardar como</translation>
<source>Save as...</source>
<translation>Guardar como...</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="924"/>
@ -283,6 +283,11 @@
<source>Player 8</source>
<translation>Jugador 8</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="1233"/>
<source>Export as...</source>
<translation>Exportar como...</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="346"/>
<source>Open map</source>

View File

@ -136,7 +136,7 @@
</message>
<message>
<location filename="../mainwindow.ui" line="921"/>
<source>Save as</source>
<source>Save as...</source>
<translation>Зберегти як</translation>
</message>
<message>
@ -281,6 +281,11 @@
<source>Player 8</source>
<translation>Гравець 8</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="1233"/>
<source>Export as...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="346"/>
<source>Open map</source>

View File

@ -299,7 +299,7 @@ void PlayerMessageProcessor::cheatResources(PlayerColor player, std::vector<std:
}
TResources resources;
resources[EGameResID::GOLD] = baseResourceAmount * 100;
resources[EGameResID::GOLD] = baseResourceAmount * 1000;
for (GameResID i = EGameResID::WOOD; i < EGameResID::GOLD; ++i)
resources[i] = baseResourceAmount;