mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-28 08:48:48 +02:00
Merge remote-tracking branch 'origin/beta' into fix_pandora_amounts
This commit is contained in:
commit
37f1bf9d78
@ -89,6 +89,7 @@ void BattleWindow::createQueue()
|
||||
|
||||
//create stack queue and adjust our own position
|
||||
bool embedQueue;
|
||||
bool showQueue = settings["battle"]["showQueue"].Bool();
|
||||
std::string queueSize = settings["battle"]["queueSize"].String();
|
||||
|
||||
if(queueSize == "auto")
|
||||
@ -97,13 +98,16 @@ void BattleWindow::createQueue()
|
||||
embedQueue = GH.screenDimensions().y < 700 || queueSize == "small";
|
||||
|
||||
queue = std::make_shared<StackQueue>(embedQueue, owner);
|
||||
if(!embedQueue && settings["battle"]["showQueue"].Bool())
|
||||
if(!embedQueue && showQueue)
|
||||
{
|
||||
//re-center, taking into account stack queue position
|
||||
pos.y -= queue->pos.h;
|
||||
pos.h += queue->pos.h;
|
||||
pos = center();
|
||||
}
|
||||
|
||||
if (!showQueue)
|
||||
queue->disable();
|
||||
}
|
||||
|
||||
BattleWindow::~BattleWindow()
|
||||
@ -143,8 +147,8 @@ void BattleWindow::hideQueue()
|
||||
pos.y += queue->pos.h;
|
||||
pos.h -= queue->pos.h;
|
||||
pos = center();
|
||||
GH.totalRedraw();
|
||||
}
|
||||
GH.totalRedraw();
|
||||
}
|
||||
|
||||
void BattleWindow::showQueue()
|
||||
@ -213,9 +217,12 @@ void BattleWindow::tacticPhaseStarted()
|
||||
auto menuTactics = widget<CIntObject>("menuTactics");
|
||||
auto tacticNext = widget<CIntObject>("tacticNext");
|
||||
auto tacticEnd = widget<CIntObject>("tacticEnd");
|
||||
auto alternativeAction = widget<CIntObject>("alternativeAction");
|
||||
|
||||
menuBattle->disable();
|
||||
console->disable();
|
||||
if (alternativeAction)
|
||||
alternativeAction->disable();
|
||||
|
||||
menuTactics->enable();
|
||||
tacticNext->enable();
|
||||
@ -231,9 +238,12 @@ void BattleWindow::tacticPhaseEnded()
|
||||
auto menuTactics = widget<CIntObject>("menuTactics");
|
||||
auto tacticNext = widget<CIntObject>("tacticNext");
|
||||
auto tacticEnd = widget<CIntObject>("tacticEnd");
|
||||
auto alternativeAction = widget<CIntObject>("alternativeAction");
|
||||
|
||||
menuBattle->enable();
|
||||
console->enable();
|
||||
if (alternativeAction)
|
||||
alternativeAction->enable();
|
||||
|
||||
menuTactics->disable();
|
||||
tacticNext->disable();
|
||||
|
@ -372,7 +372,15 @@ std::shared_ptr<CSlider> InterfaceObjectConfigurable::buildSlider(const JsonNode
|
||||
auto itemsTotal = config["itemsTotal"].Integer();
|
||||
auto value = config["selected"].Integer();
|
||||
bool horizontal = config["orientation"].String() == "horizontal";
|
||||
return std::make_shared<CSlider>(position, length, callbacks.at(config["callback"].String()), itemsVisible, itemsTotal, value, horizontal, style);
|
||||
auto const & result = std::make_shared<CSlider>(position, length, callbacks.at(config["callback"].String()), itemsVisible, itemsTotal, value, horizontal, style);
|
||||
|
||||
if (!config["scrollBounds"].isNull())
|
||||
{
|
||||
Rect bounds = readRect(config["scrollBounds"]);
|
||||
result->setScrollBounds(bounds);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::shared_ptr<CAnimImage> InterfaceObjectConfigurable::buildImage(const JsonNode & config) const
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
#include "../../lib/Point.h"
|
||||
#include "../../lib/TextOperations.h"
|
||||
//
|
||||
|
||||
size_t IFont::getStringWidth(const std::string & data) const
|
||||
{
|
||||
|
@ -70,7 +70,7 @@ CBitmapFont::CBitmapFont(const std::string & filename):
|
||||
|
||||
loadModFont("core", resource);
|
||||
|
||||
for (auto const & modName : VLC->modh->getActiveMods())
|
||||
for(const auto & modName : VLC->modh->getActiveMods())
|
||||
{
|
||||
if (CResourceHandler::get(modName)->existsResource(resource))
|
||||
loadModFont(modName, resource);
|
||||
@ -94,6 +94,24 @@ size_t CBitmapFont::getGlyphWidth(const char * data) const
|
||||
return iter->second.leftOffset + iter->second.width + iter->second.rightOffset;
|
||||
}
|
||||
|
||||
bool CBitmapFont::canRepresentCharacter(const char *data) const
|
||||
{
|
||||
CodePoint localChar = TextOperations::getUnicodeCodepoint(data, 4);
|
||||
|
||||
auto iter = chars.find(localChar);
|
||||
|
||||
return iter != chars.end();
|
||||
}
|
||||
|
||||
bool CBitmapFont::canRepresentString(const std::string & data) const
|
||||
{
|
||||
for(size_t i=0; i<data.size(); i += TextOperations::getUnicodeCharacterSize(data[i]))
|
||||
if (!canRepresentCharacter(data.data() + i))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBitmapFont::renderCharacter(SDL_Surface * surface, const BitmapChar & character, const SDL_Color & color, int &posX, int &posY) const
|
||||
{
|
||||
Rect clipRect;
|
||||
|
@ -41,6 +41,11 @@ public:
|
||||
size_t getLineHeight() const override;
|
||||
size_t getGlyphWidth(const char * data) const override;
|
||||
|
||||
/// returns true if this font contains provided utf-8 character
|
||||
bool canRepresentCharacter(const char * data) const;
|
||||
bool canRepresentString(const std::string & data) const;
|
||||
|
||||
friend class CBitmapHanFont;
|
||||
friend class CTrueTypeFont;
|
||||
};
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include "StdInc.h"
|
||||
#include "CTrueTypeFont.h"
|
||||
|
||||
#include "CBitmapFont.h"
|
||||
|
||||
#include "../render/Colors.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
|
||||
@ -52,30 +54,45 @@ int CTrueTypeFont::getFontStyle(const JsonNode &config)
|
||||
CTrueTypeFont::CTrueTypeFont(const JsonNode & fontConfig):
|
||||
data(loadData(fontConfig)),
|
||||
font(loadFont(fontConfig), TTF_CloseFont),
|
||||
dropShadow(fontConfig["blend"].Bool()),
|
||||
blended(fontConfig["blend"].Bool())
|
||||
{
|
||||
assert(font);
|
||||
|
||||
TTF_SetFontStyle(font.get(), getFontStyle(fontConfig));
|
||||
|
||||
std::string fallbackName = fontConfig["fallback"].String();
|
||||
|
||||
if (!fallbackName.empty())
|
||||
fallbackFont = std::make_unique<CBitmapFont>(fallbackName);
|
||||
}
|
||||
|
||||
CTrueTypeFont::~CTrueTypeFont() = default;
|
||||
|
||||
size_t CTrueTypeFont::getLineHeight() const
|
||||
{
|
||||
if (fallbackFont)
|
||||
fallbackFont->getLineHeight();
|
||||
|
||||
return TTF_FontHeight(font.get());
|
||||
}
|
||||
|
||||
size_t CTrueTypeFont::getGlyphWidth(const char *data) const
|
||||
{
|
||||
if (fallbackFont && fallbackFont->canRepresentCharacter(data))
|
||||
return fallbackFont->getGlyphWidth(data);
|
||||
|
||||
return getStringWidth(std::string(data, TextOperations::getUnicodeCharacterSize(*data)));
|
||||
/*
|
||||
int advance;
|
||||
TTF_GlyphMetrics(font.get(), *data, nullptr, nullptr, nullptr, nullptr, &advance);
|
||||
return advance;
|
||||
*/
|
||||
}
|
||||
|
||||
size_t CTrueTypeFont::getStringWidth(const std::string & data) const
|
||||
{
|
||||
if (fallbackFont && fallbackFont->canRepresentString(data))
|
||||
return fallbackFont->getStringWidth(data);
|
||||
|
||||
int width;
|
||||
TTF_SizeUTF8(font.get(), data.c_str(), &width, nullptr);
|
||||
return width;
|
||||
@ -83,7 +100,13 @@ size_t CTrueTypeFont::getStringWidth(const std::string & data) const
|
||||
|
||||
void CTrueTypeFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
if (color.r != 0 && color.g != 0 && color.b != 0) // not black - add shadow
|
||||
if (fallbackFont && fallbackFont->canRepresentString(data))
|
||||
{
|
||||
fallbackFont->renderText(surface, data, color, pos);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dropShadow && color.r != 0 && color.g != 0 && color.b != 0) // not black - add shadow
|
||||
renderText(surface, data, Colors::BLACK, pos + Point(1,1));
|
||||
|
||||
if (!data.empty())
|
||||
|
@ -15,14 +15,18 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
class JsonNode;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class CBitmapFont;
|
||||
|
||||
typedef struct _TTF_Font TTF_Font;
|
||||
|
||||
class CTrueTypeFont : public IFont
|
||||
{
|
||||
std::unique_ptr<CBitmapFont> fallbackFont;
|
||||
const std::pair<std::unique_ptr<ui8[]>, ui64> data;
|
||||
|
||||
const std::unique_ptr<TTF_Font, void (*)(TTF_Font*)> font;
|
||||
const bool blended;
|
||||
const bool dropShadow;
|
||||
|
||||
std::pair<std::unique_ptr<ui8[]>, ui64> loadData(const JsonNode & config);
|
||||
TTF_Font * loadFont(const JsonNode & config);
|
||||
@ -31,6 +35,7 @@ class CTrueTypeFont : public IFont
|
||||
void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override;
|
||||
public:
|
||||
CTrueTypeFont(const JsonNode & fontConfig);
|
||||
~CTrueTypeFont();
|
||||
|
||||
size_t getLineHeight() const override;
|
||||
size_t getGlyphWidth(const char * data) const override;
|
||||
|
@ -575,7 +575,7 @@ void CSlider::mouseMoved (const Point & cursorPosition)
|
||||
v += 0.5;
|
||||
if(v!=value)
|
||||
{
|
||||
moveTo((int)v);
|
||||
moveTo(static_cast<int>(v));
|
||||
}
|
||||
}
|
||||
|
||||
@ -584,6 +584,16 @@ void CSlider::setScrollStep(int to)
|
||||
scrollStep = to;
|
||||
}
|
||||
|
||||
void CSlider::setScrollBounds(const Rect & bounds )
|
||||
{
|
||||
scrollBounds = bounds;
|
||||
}
|
||||
|
||||
void CSlider::clearScrollBounds()
|
||||
{
|
||||
scrollBounds = boost::none;
|
||||
}
|
||||
|
||||
int CSlider::getAmount() const
|
||||
{
|
||||
return amount;
|
||||
@ -775,7 +785,19 @@ void CSlider::showAll(SDL_Surface * to)
|
||||
|
||||
void CSlider::wheelScrolled(bool down, bool in)
|
||||
{
|
||||
moveTo(value + 3 * (down ? +scrollStep : -scrollStep));
|
||||
if (scrollBounds)
|
||||
{
|
||||
Rect testTarget = *scrollBounds + pos.topLeft();
|
||||
|
||||
if (!testTarget.isInside(GH.getCursorPosition()))
|
||||
return;
|
||||
}
|
||||
|
||||
// vertical slider -> scrolling up move slider upwards
|
||||
// horizontal slider -> scrolling up moves slider towards right
|
||||
bool positive = (down != horizontal);
|
||||
|
||||
moveTo(value + 3 * (positive ? +scrollStep : -scrollStep));
|
||||
}
|
||||
|
||||
void CSlider::keyPressed(const SDL_Keycode & key)
|
||||
|
@ -229,6 +229,8 @@ class CSlider : public CIntObject
|
||||
std::shared_ptr<CButton> right;
|
||||
std::shared_ptr<CButton> slider;
|
||||
|
||||
boost::optional<Rect> scrollBounds;
|
||||
|
||||
int capacity;//how many elements can be active at same time (e.g. hero list = 5)
|
||||
int positions; //number of highest position (0 if there is only one)
|
||||
bool horizontal;
|
||||
@ -252,6 +254,10 @@ public:
|
||||
/// Controls how many items wil be scrolled via one click
|
||||
void setScrollStep(int to);
|
||||
|
||||
/// If set, mouse scroll will only scroll slider when inside of this area
|
||||
void setScrollBounds(const Rect & bounds );
|
||||
void clearScrollBounds();
|
||||
|
||||
/// Value modifiers
|
||||
void moveLeft();
|
||||
void moveRight();
|
||||
|
@ -405,31 +405,7 @@ void CHeroGSlot::clickLeft(tribool down, bool previousState)
|
||||
}
|
||||
else if(other->hero && other->isSelected())
|
||||
{
|
||||
bool allow = true;
|
||||
if(upg) //moving hero out of town - check if it is allowed
|
||||
{
|
||||
if(!hero && LOCPLINT->cb->howManyHeroes(false) >= CGI->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))
|
||||
{
|
||||
std::string tmp = CGI->generaltexth->allTexts[18]; //You already have %d adventuring heroes under your command.
|
||||
boost::algorithm::replace_first(tmp,"%d",std::to_string(LOCPLINT->cb->howManyHeroes(false)));
|
||||
LOCPLINT->showInfoDialog(tmp, std::vector<std::shared_ptr<CComponent>>(), soundBase::sound_todo);
|
||||
allow = false;
|
||||
}
|
||||
else if(!other->hero->stacksCount()) //hero has no creatures - strange, but if we have appropriate error message...
|
||||
{
|
||||
LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[19], std::vector<std::shared_ptr<CComponent>>(), soundBase::sound_todo); //This hero has no creatures. A hero must have creatures before he can brave the dangers of the countryside.
|
||||
allow = false;
|
||||
}
|
||||
}
|
||||
|
||||
setHighlight(false);
|
||||
other->setHighlight(false);
|
||||
|
||||
if(allow)
|
||||
{
|
||||
owner->swapArmies();
|
||||
hero = other->hero;
|
||||
}
|
||||
owner->swapArmies();
|
||||
}
|
||||
else if(hero)
|
||||
{
|
||||
@ -524,17 +500,42 @@ void HeroSlots::splitClicked()
|
||||
|
||||
void HeroSlots::swapArmies()
|
||||
{
|
||||
bool allow = true;
|
||||
|
||||
//moving hero out of town - check if it is allowed
|
||||
if (town->garrisonHero)
|
||||
{
|
||||
if (!town->visitingHero && LOCPLINT->cb->howManyHeroes(false) >= CGI->settings()->getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))
|
||||
{
|
||||
std::string text = CGI->generaltexth->translate("core.genrltxt.18"); //You already have %d adventuring heroes under your command.
|
||||
boost::algorithm::replace_first(text,"%d",std::to_string(LOCPLINT->cb->howManyHeroes(false)));
|
||||
|
||||
LOCPLINT->showInfoDialog(text, std::vector<std::shared_ptr<CComponent>>(), soundBase::sound_todo);
|
||||
allow = false;
|
||||
}
|
||||
else if (town->garrisonHero->stacksCount() == 0)
|
||||
{
|
||||
//This hero has no creatures. A hero must have creatures before he can brave the dangers of the countryside.
|
||||
LOCPLINT->showInfoDialog(CGI->generaltexth->translate("core.genrltxt.19"), {}, soundBase::sound_todo);
|
||||
allow = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!town->garrisonHero && town->visitingHero) //visiting => garrison, merge armies: town army => hero army
|
||||
{
|
||||
if(!town->visitingHero->canBeMergedWith(*town))
|
||||
{
|
||||
LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[275], std::vector<std::shared_ptr<CComponent>>(), soundBase::sound_todo);
|
||||
return;
|
||||
allow = false;
|
||||
}
|
||||
}
|
||||
LOCPLINT->cb->swapGarrisonHero(town);
|
||||
}
|
||||
|
||||
garrisonedHero->setHighlight(false);
|
||||
visitingHero->setHighlight(false);
|
||||
|
||||
if (allow)
|
||||
LOCPLINT->cb->swapGarrisonHero(town);
|
||||
}
|
||||
|
||||
class SORTHELP
|
||||
{
|
||||
|
@ -84,14 +84,19 @@ int BattleOptionsTab::getAnimSpeed() const
|
||||
|
||||
int BattleOptionsTab::getQueueSizeId() const
|
||||
{
|
||||
std::string text = settings["battle"]["queueSize"].String();
|
||||
if(text == "none")
|
||||
std::string sizeText = settings["battle"]["queueSize"].String();
|
||||
bool visible = settings["battle"]["showQueue"].Bool();
|
||||
|
||||
if(!visible)
|
||||
return -1;
|
||||
if(text == "auto")
|
||||
|
||||
if(sizeText == "none")
|
||||
return -1;
|
||||
if(sizeText == "auto")
|
||||
return 0;
|
||||
if(text == "small")
|
||||
if(sizeText == "small")
|
||||
return 1;
|
||||
if(text == "big")
|
||||
if(sizeText == "big")
|
||||
return 2;
|
||||
|
||||
return 0;
|
||||
|
@ -147,7 +147,7 @@ GeneralOptionsTab::GeneralOptionsTab()
|
||||
musicVolumeLabel->setText(std::to_string(CCS->musich->getVolume()) + "%");
|
||||
|
||||
std::shared_ptr<CLabel> soundVolumeLabel = widget<CLabel>("soundValueLabel");
|
||||
musicVolumeLabel->setText(std::to_string(CCS->soundh->getVolume()) + "%");
|
||||
soundVolumeLabel->setText(std::to_string(CCS->soundh->getVolume()) + "%");
|
||||
|
||||
}
|
||||
|
||||
|
@ -138,6 +138,7 @@
|
||||
"name": "musicSlider",
|
||||
"type": "slider",
|
||||
"position": {"x": 385, "y": 115},
|
||||
"scrollBounds" : { "x" : -4, "y" : -34, "w" : 208, "h" : 52 },
|
||||
"size": 200,
|
||||
"style": "brown",
|
||||
"orientation": "horizontal",
|
||||
@ -165,6 +166,7 @@
|
||||
"name": "soundVolumeSlider",
|
||||
"type": "slider",
|
||||
"position": {"x": 385, "y": 175},
|
||||
"scrollBounds" : { "x" : -4, "y" : -34, "w" : 208, "h" : 52 },
|
||||
"size": 200,
|
||||
"style": "brown",
|
||||
"orientation": "horizontal",
|
||||
|
@ -35,7 +35,10 @@ The following platforms are supported and known to work, others might require ch
|
||||
if you want x86, otherwise pick **vcmi-deps-windows-conan.tgz**
|
||||
- [Android](https://github.com/vcmi/vcmi-dependencies/releases)
|
||||
|
||||
3. Only if you have Apple Silicon Mac and trying to build for macOS or iOS: follow [instructions how to build Qt host tools for Apple Silicon](https://github.com/vcmi/vcmi-ios-deps#note-for-arm-macs), on step 3 copy them to `~/.conan/data/qt/5.15.x/_/_/package/SOME_HASH/bin` (`5.15.x` and `SOME_HASH` are placeholders).
|
||||
3. Only if you have Apple Silicon Mac and trying to build for macOS or iOS:
|
||||
|
||||
1. Open file `~/.conan/data/qt/5.15.x/_/_/export/conanfile.py` (`5.15.x` is a placeholder), search for string `Designer` (there should be only one match), comment this line and the one above it by inserting `#` in the beginning, and save the file.
|
||||
2. (optional) If you don't want to use Rosetta, follow [instructions how to build Qt host tools for Apple Silicon](https://github.com/vcmi/vcmi-ios-deps#note-for-arm-macs), on step 3 copy them to `~/.conan/data/qt/5.15.x/_/_/package/SOME_HASH/bin` (`5.15.x` and `SOME_HASH` are placeholders). Make sure **not** to copy `qt.conf`!
|
||||
|
||||
## Generate CMake integration
|
||||
|
||||
|
@ -335,6 +335,7 @@ void FirstLaunchView::modPresetUpdate()
|
||||
bool translationExists = !findTranslationModName().isEmpty();
|
||||
|
||||
ui->labelPresetLanguage->setVisible(translationExists);
|
||||
ui->labelPresetLanguageDescr->setVisible(translationExists);
|
||||
ui->checkBoxPresetLanguage->setVisible(translationExists);
|
||||
|
||||
ui->checkBoxPresetLanguage->setEnabled(checkCanInstallTranslation());
|
||||
|
@ -372,7 +372,7 @@ void CSettingsView::loadTranslation()
|
||||
ui->labelTranslationStatus->setVisible(showTranslation);
|
||||
ui->pushButtonTranslation->setVisible(showTranslation);
|
||||
|
||||
if (!translationExists)
|
||||
if (!translationExists || !translationNeeded)
|
||||
return;
|
||||
|
||||
bool translationAvailable = mainWindow->getModView()->isModAvailable(modName);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -432,8 +432,11 @@ const CCreature * CCreatureHandler::getCreature(const std::string & scope, const
|
||||
|
||||
void CCreatureHandler::loadCommanders()
|
||||
{
|
||||
JsonNode data(ResourceID("config/commanders.json"));
|
||||
data.setMeta(CModHandler::scopeBuiltin()); // assume that commanders are in core mod (for proper bonuses resolution)
|
||||
ResourceID configResource("config/commanders.json");
|
||||
|
||||
std::string modSource = VLC->modh->findResourceOrigin(configResource);
|
||||
JsonNode data(configResource);
|
||||
data.setMeta(modSource);
|
||||
|
||||
const JsonNode & config = data; // switch to const data accessors
|
||||
|
||||
@ -960,9 +963,6 @@ void CCreatureHandler::loadStackExperience(CCreature * creature, const JsonNode
|
||||
{
|
||||
for (const JsonNode &exp : input.Vector())
|
||||
{
|
||||
auto bonus = JsonUtils::parseBonus (exp["bonus"]);
|
||||
bonus->source = Bonus::STACK_EXPERIENCE;
|
||||
bonus->duration = Bonus::PERMANENT;
|
||||
const JsonVector &values = exp["values"].Vector();
|
||||
int lowerLimit = 1;//, upperLimit = 255;
|
||||
if (values[0].getType() == JsonNode::JsonType::DATA_BOOL)
|
||||
@ -971,8 +971,14 @@ void CCreatureHandler::loadStackExperience(CCreature * creature, const JsonNode
|
||||
{
|
||||
if(val.Bool())
|
||||
{
|
||||
// parse each bonus separately
|
||||
// we can not create copies since identifiers resolution does not tracks copies
|
||||
// leading to unset identifier values in copies
|
||||
auto bonus = JsonUtils::parseBonus (exp["bonus"]);
|
||||
bonus->source = Bonus::STACK_EXPERIENCE;
|
||||
bonus->duration = Bonus::PERMANENT;
|
||||
bonus->limiter = std::make_shared<RankRangeLimiter>(RankRangeLimiter(lowerLimit));
|
||||
creature->addNewBonus (std::make_shared<Bonus>(*bonus)); //bonuses must be unique objects
|
||||
creature->addNewBonus (bonus);
|
||||
break; //TODO: allow bonuses to turn off?
|
||||
}
|
||||
++lowerLimit;
|
||||
@ -985,9 +991,14 @@ void CCreatureHandler::loadStackExperience(CCreature * creature, const JsonNode
|
||||
{
|
||||
if (val.Float() != lastVal)
|
||||
{
|
||||
bonus->val = static_cast<int>(val.Float()) - lastVal;
|
||||
JsonNode bonusInput = exp["bonus"];
|
||||
bonusInput["val"].Float() = static_cast<int>(val.Float()) - lastVal;
|
||||
|
||||
auto bonus = JsonUtils::parseBonus (bonusInput);
|
||||
bonus->source = Bonus::STACK_EXPERIENCE;
|
||||
bonus->duration = Bonus::PERMANENT;
|
||||
bonus->limiter.reset (new RankRangeLimiter(lowerLimit));
|
||||
creature->addNewBonus (std::make_shared<Bonus>(*bonus));
|
||||
creature->addNewBonus (bonus);
|
||||
}
|
||||
lastVal = static_cast<int>(val.Float());
|
||||
++lowerLimit;
|
||||
|
@ -355,17 +355,17 @@ bool CGeneralTextHandler::validateTranslation(const std::string & language, cons
|
||||
|
||||
bool allFound = true;
|
||||
|
||||
for(const auto & string : config.Struct())
|
||||
{
|
||||
if (stringsLocalizations.count(string.first) > 0)
|
||||
continue;
|
||||
|
||||
if (allFound)
|
||||
logMod->warn("Translation into language '%s' in mod '%s' has unused lines:", language, modContext);
|
||||
|
||||
logMod->warn(R"( "%s" : "%s",)", string.first, TextOperations::escapeString(string.second.String()));
|
||||
allFound = false;
|
||||
}
|
||||
// for(const auto & string : config.Struct())
|
||||
// {
|
||||
// if (stringsLocalizations.count(string.first) > 0)
|
||||
// continue;
|
||||
//
|
||||
// if (allFound)
|
||||
// logMod->warn("Translation into language '%s' in mod '%s' has unused lines:", language, modContext);
|
||||
//
|
||||
// logMod->warn(R"( "%s" : "%s",)", string.first, TextOperations::escapeString(string.second.String()));
|
||||
// allFound = false;
|
||||
// }
|
||||
|
||||
return allPresent && allFound;
|
||||
}
|
||||
|
@ -367,7 +367,12 @@ class IVCMIDirsUNIX : public IVCMIDirs
|
||||
bool IVCMIDirsUNIX::developmentMode() const
|
||||
{
|
||||
// We want to be able to run VCMI from single directory. E.g to run from build output directory
|
||||
return bfs::exists("AI") && bfs::exists("config") && bfs::exists("Mods") && bfs::exists("vcmiserver") && bfs::exists("vcmiclient");
|
||||
const bool result = bfs::exists("AI") && bfs::exists("config") && bfs::exists("Mods") && bfs::exists("vcmiclient");
|
||||
#if SINGLE_PROCESS_APP
|
||||
return result;
|
||||
#else
|
||||
return result && bfs::exists("vcmiserver");
|
||||
#endif
|
||||
}
|
||||
|
||||
bfs::path IVCMIDirsUNIX::clientPath() const { return binaryPath() / "vcmiclient"; }
|
||||
|
@ -160,7 +160,7 @@ std::string CMapGenerator::getMapDescription() const
|
||||
std::stringstream ss;
|
||||
ss << boost::str(boost::format(std::string("Map created by the Random Map Generator.\nTemplate was %s, Random seed was %d, size %dx%d") +
|
||||
", levels %d, players %d, computers %d, water %s, monster %s, VCMI map") % mapTemplate->getName() %
|
||||
randomSeed % map->map().width % map->map().height % map->map().levels() % static_cast<int>(mapGenOptions.getPlayerCount()) %
|
||||
randomSeed % map->map().width % map->map().height % static_cast<int>(map->map().levels()) % static_cast<int>(mapGenOptions.getPlayerCount()) %
|
||||
static_cast<int>(mapGenOptions.getCompOnlyPlayerCount()) % waterContentStr[mapGenOptions.getWaterContent()] %
|
||||
monsterStrengthStr[monsterStrengthIndex]);
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
const ui32 SERIALIZATION_VERSION = 820;
|
||||
const ui32 SERIALIZATION_VERSION = 821;
|
||||
const ui32 MINIMAL_SERIALIZATION_VERSION = 820;
|
||||
const std::string SAVEGAME_MAGIC = "VCMISVG";
|
||||
|
||||
|
@ -272,6 +272,8 @@ public:
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & identifier;
|
||||
if (version > 820)
|
||||
h & modScope;
|
||||
h & id;
|
||||
h & level;
|
||||
h & power;
|
||||
|
@ -4922,8 +4922,9 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
{
|
||||
const CSpell * spell = SpellID(healerAbility->subtype).toSpell();
|
||||
spells::BattleCast parameters(gs->curB, healer, spells::Mode::SPELL_LIKE_ATTACK, spell); //We can heal infinitely by first aid tent
|
||||
auto dest = battle::Destination(destStack, target.at(0).hexValue);
|
||||
parameters.setSpellLevel(0);
|
||||
parameters.cast(spellEnv, target);
|
||||
parameters.cast(spellEnv, {dest});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user