mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-22 22:13:35 +02:00
Merge remote-tracking branch 'origin/beta' into random_prison_distributor
This commit is contained in:
commit
8a93b1083f
@ -114,6 +114,8 @@
|
||||
"vcmi.systemOptions.enableUiEnhancementsButton.help" : "{Interface Enhancements}\n\nToggle various quality of life interface improvements. Such as a backpack button etc. Disable to have a more classic experience.",
|
||||
"vcmi.systemOptions.enableLargeSpellbookButton.hover" : "Large Spell Book",
|
||||
"vcmi.systemOptions.enableLargeSpellbookButton.help" : "{Large Spell Book}\n\nEnables larger spell book that fits more spells per page. Spell book page change animation does not work with this setting enabled.",
|
||||
"vcmi.systemOptions.audioMuteFocus.hover" : "Mute on inactivity",
|
||||
"vcmi.systemOptions.audioMuteFocus.help" : "{Mute on inactivity}\n\nMute audio on inactive window focus. Exceptions are ingame messages and new turn sound.",
|
||||
|
||||
"vcmi.adventureOptions.infoBarPick.hover" : "Show Messages in Info Panel",
|
||||
"vcmi.adventureOptions.infoBarPick.help" : "{Show Messages in Info Panel}\n\nWhenever possible, game messages from visiting map objects will be shown in the info panel, instead of popping up in a separate window.",
|
||||
@ -129,6 +131,8 @@
|
||||
"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.smoothDragging.hover" : "Smooth Map Dragging",
|
||||
"vcmi.adventureOptions.smoothDragging.help" : "{Smooth Map Dragging}\n\nWhen enabled, map dragging has a modern run out effect.",
|
||||
"vcmi.adventureOptions.mapScrollSpeed1.hover": "",
|
||||
"vcmi.adventureOptions.mapScrollSpeed5.hover": "",
|
||||
"vcmi.adventureOptions.mapScrollSpeed6.hover": "",
|
||||
@ -258,7 +262,7 @@
|
||||
"vcmi.optionsTab.simturnsMin.help" : "Play simultaneously for specified number of days. Contacts between players during this period are blocked",
|
||||
"vcmi.optionsTab.simturnsMax.help" : "Play simultaneously for specified number of days or until contact with another player",
|
||||
"vcmi.optionsTab.simturnsAI.help" : "{Simultaneous AI Turns}\nExperimental option. Allows AI players to act at the same time as human player when simultaneous turns are enabled.",
|
||||
|
||||
|
||||
"vcmi.optionsTab.turnTime.select" : "Select turn timer preset",
|
||||
"vcmi.optionsTab.turnTime.unlimited" : "Unlimited turn time",
|
||||
"vcmi.optionsTab.turnTime.classic.1" : "Classic timer: 1 minute",
|
||||
|
@ -114,6 +114,8 @@
|
||||
"vcmi.systemOptions.enableUiEnhancementsButton.help" : "{Interface Verbesserungen}\n\nSchaltet verschiedene Interface Verbesserungen um. Wie z.B. ein Rucksack-Button, etc. Deaktivieren, um ein klassischeres Erlebnis zu haben.",
|
||||
"vcmi.systemOptions.enableLargeSpellbookButton.hover" : "Großes Zauberbuch",
|
||||
"vcmi.systemOptions.enableLargeSpellbookButton.help" : "{Großes Zauberbuch}\n\nErmöglicht ein größeres Zauberbuch, in das mehr Zaubersprüche pro Seite passen. Die Animation des Seitenwechsels im Zauberbuch funktioniert nicht, wenn diese Einstellung aktiviert ist.",
|
||||
"vcmi.systemOptions.audioMuteFocus.hover" : "Stumm bei Inaktivität",
|
||||
"vcmi.systemOptions.audioMuteFocus.help" : "{Stumm bei Inaktivität}\n\nSchaltet Audio bei inaktiven Fenster-Fokus stumm. Ausnahmen sind Ingame-Nachrichten und der Neuer-Zug-Sound.",
|
||||
|
||||
"vcmi.adventureOptions.infoBarPick.hover" : "Meldungen im Infobereich anzeigen",
|
||||
"vcmi.adventureOptions.infoBarPick.help" : "{Meldungen im Infobereich anzeigen}\n\nWann immer möglich, werden Spielnachrichten von besuchten Kartenobjekten in der Infoleiste angezeigt, anstatt als Popup-Fenster zu erscheinen",
|
||||
@ -129,6 +131,8 @@
|
||||
"vcmi.adventureOptions.infoBarCreatureManagement.help" : "{Info-Panel Kreaturenmanagement}\n\nErmöglicht die Neuanordnung von Kreaturen im Info-Panel, anstatt zwischen den Standardkomponenten zu wechseln",
|
||||
"vcmi.adventureOptions.leftButtonDrag.hover" : "Ziehen der Karte mit Links",
|
||||
"vcmi.adventureOptions.leftButtonDrag.help" : "{Ziehen der Karte mit Links}\n\nWenn aktiviert, wird die Maus bei gedrückter linker Taste in die Kartenansicht gezogen",
|
||||
"vcmi.adventureOptions.smoothDragging.hover" : "Nahtloses Ziehen der Karte",
|
||||
"vcmi.adventureOptions.smoothDragging.help" : "{Nahtloses Ziehen der Karte}\n\nWenn aktiviert hat das Ziehen der Karte einen sanften Auslaufeffekt.",
|
||||
"vcmi.adventureOptions.mapScrollSpeed1.hover": "",
|
||||
"vcmi.adventureOptions.mapScrollSpeed5.hover": "",
|
||||
"vcmi.adventureOptions.mapScrollSpeed6.hover": "",
|
||||
|
@ -98,7 +98,7 @@
|
||||
]
|
||||
},
|
||||
|
||||
"version" : "1.3",
|
||||
"version" : "1.4",
|
||||
"author" : "VCMI Team",
|
||||
"contact" : "http://forum.vcmi.eu/index.php",
|
||||
"modType" : "Graphical",
|
||||
|
@ -10,8 +10,8 @@ android {
|
||||
applicationId "is.xyz.vcmi"
|
||||
minSdk 19
|
||||
targetSdk 33
|
||||
versionCode 1400
|
||||
versionName "1.4.0"
|
||||
versionCode 1410
|
||||
versionName "1.4.1"
|
||||
setProperty("archivesBaseName", "vcmi")
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,7 @@ void InputHandler::preprocessEvent(const SDL_Event & ev)
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
{
|
||||
boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
|
||||
if(settings["general"]["enableUiEnhancements"].Bool()) {
|
||||
if(settings["general"]["audioMuteFocus"].Bool()) {
|
||||
CCS->musich->setVolume(settings["general"]["music"].Integer());
|
||||
CCS->soundh->setVolume(settings["general"]["sound"].Integer());
|
||||
}
|
||||
@ -179,7 +179,7 @@ void InputHandler::preprocessEvent(const SDL_Event & ev)
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
{
|
||||
boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
|
||||
if(settings["general"]["enableUiEnhancements"].Bool()) {
|
||||
if(settings["general"]["audioMuteFocus"].Bool()) {
|
||||
CCS->musich->setVolume(0);
|
||||
CCS->soundh->setVolume(0);
|
||||
}
|
||||
|
@ -122,7 +122,10 @@ void MapView::onMapLevelSwitched()
|
||||
void MapView::onMapScrolled(const Point & distance)
|
||||
{
|
||||
if(!isGesturing())
|
||||
{
|
||||
postSwipeSpeed = 0.0;
|
||||
controller->setViewCenter(model->getMapViewCenter() + distance, model->getLevel());
|
||||
}
|
||||
}
|
||||
|
||||
void MapView::onMapSwiped(const Point & viewPosition)
|
||||
|
@ -156,6 +156,11 @@ void CSlider::clickPressed(const Point & cursorPosition)
|
||||
|
||||
bool CSlider::receiveEvent(const Point &position, int eventType) const
|
||||
{
|
||||
if (eventType == LCLICK)
|
||||
{
|
||||
return pos.isInside(position) && !left->pos.isInside(position) && !right->pos.isInside(position);
|
||||
}
|
||||
|
||||
if(eventType != WHEEL && eventType != GESTURE)
|
||||
{
|
||||
return CIntObject::receiveEvent(position, eventType);
|
||||
|
@ -126,6 +126,10 @@ AdventureOptionsTab::AdventureOptionsTab()
|
||||
{
|
||||
return setBoolSetting("adventure", "leftButtonDrag", value);
|
||||
});
|
||||
addCallback("smoothDraggingChanged", [](bool value)
|
||||
{
|
||||
return setBoolSetting("adventure", "smoothDragging", value);
|
||||
});
|
||||
build(config);
|
||||
|
||||
std::shared_ptr<CToggleGroup> playerHeroSpeedToggle = widget<CToggleGroup>("heroMovementSpeedPicker");
|
||||
@ -164,4 +168,8 @@ AdventureOptionsTab::AdventureOptionsTab()
|
||||
std::shared_ptr<CToggleButton> leftButtonDragCheckbox = widget<CToggleButton>("leftButtonDragCheckbox");
|
||||
if (leftButtonDragCheckbox)
|
||||
leftButtonDragCheckbox->setSelected(settings["adventure"]["leftButtonDrag"].Bool());
|
||||
|
||||
std::shared_ptr<CToggleButton> smoothDraggingCheckbox = widget<CToggleButton>("smoothDraggingCheckbox");
|
||||
if (smoothDraggingCheckbox)
|
||||
smoothDraggingCheckbox->setSelected(settings["adventure"]["smoothDragging"].Bool());
|
||||
}
|
||||
|
@ -167,6 +167,11 @@ GeneralOptionsTab::GeneralOptionsTab()
|
||||
setBoolSetting("gameTweaks", "enableLargeSpellbook", value);
|
||||
});
|
||||
|
||||
addCallback("audioMuteFocusChanged", [](bool value)
|
||||
{
|
||||
setBoolSetting("general", "audioMuteFocus", value);
|
||||
});
|
||||
|
||||
//moved from "other" tab that is disabled for now to avoid excessible tabs with barely any content
|
||||
addCallback("availableCreaturesAsDwellingChanged", [=](int value)
|
||||
{
|
||||
@ -215,6 +220,10 @@ GeneralOptionsTab::GeneralOptionsTab()
|
||||
if (enableLargeSpellbookCheckbox)
|
||||
enableLargeSpellbookCheckbox->setSelected(settings["gameTweaks"]["enableLargeSpellbook"].Bool());
|
||||
|
||||
std::shared_ptr<CToggleButton> audioMuteFocusCheckbox = widget<CToggleButton>("audioMuteFocusCheckbox");
|
||||
if (audioMuteFocusCheckbox)
|
||||
audioMuteFocusCheckbox->setSelected(settings["general"]["audioMuteFocus"].Bool());
|
||||
|
||||
std::shared_ptr<CSlider> musicSlider = widget<CSlider>("musicSlider");
|
||||
musicSlider->scrollTo(CCS->musich->getVolume());
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
set(VCMI_VERSION_MAJOR 1)
|
||||
set(VCMI_VERSION_MINOR 4)
|
||||
set(VCMI_VERSION_PATCH 0)
|
||||
set(VCMI_VERSION_PATCH 1)
|
||||
add_definitions(
|
||||
-DVCMI_VERSION_MAJOR=${VCMI_VERSION_MAJOR}
|
||||
-DVCMI_VERSION_MINOR=${VCMI_VERSION_MINOR}
|
||||
|
@ -39,7 +39,8 @@
|
||||
"useSavePrefix",
|
||||
"savePrefix",
|
||||
"startTurnAutosave",
|
||||
"enableUiEnhancements"
|
||||
"enableUiEnhancements",
|
||||
"audioMuteFocus"
|
||||
],
|
||||
"properties" : {
|
||||
"playerName" : {
|
||||
@ -131,6 +132,10 @@
|
||||
"enableUiEnhancements" : {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"audioMuteFocus" : {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -347,6 +347,9 @@
|
||||
{
|
||||
"text": "vcmi.adventureOptions.leftButtonDrag.hover",
|
||||
"created" : "desktop"
|
||||
},
|
||||
{
|
||||
"text": "vcmi.adventureOptions.smoothDragging.hover"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -391,6 +394,11 @@
|
||||
"help": "vcmi.adventureOptions.leftButtonDrag",
|
||||
"callback": "leftButtonDragChanged",
|
||||
"created" : "desktop"
|
||||
},
|
||||
{
|
||||
"name": "smoothDraggingCheckbox",
|
||||
"help": "vcmi.adventureOptions.smoothDragging",
|
||||
"callback": "smoothDraggingChanged"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -180,6 +180,28 @@
|
||||
"type": "labelCentered",
|
||||
"position": {"x": 565, "y": 158}
|
||||
},
|
||||
{
|
||||
"type" : "verticalLayout",
|
||||
"customType" : "labelDescription",
|
||||
"position" : {"x": 415, "y": 202},
|
||||
"items" : [
|
||||
{
|
||||
"text": "vcmi.systemOptions.audioMuteFocus.hover"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type" : "verticalLayout",
|
||||
"customType" : "checkbox",
|
||||
"position" : {"x": 380, "y": 200},
|
||||
"items" : [
|
||||
{
|
||||
"name": "audioMuteFocusCheckbox",
|
||||
"help": "vcmi.systemOptions.audioMuteFocus",
|
||||
"callback": "audioMuteFocusChanged"
|
||||
}
|
||||
]
|
||||
},
|
||||
/////////////////////////////////////// Bottom section - Towns Settings
|
||||
{
|
||||
"type" : "verticalLayout",
|
||||
|
6
debian/changelog
vendored
6
debian/changelog
vendored
@ -1,3 +1,9 @@
|
||||
vcmi (1.4.1) jammy; urgency=medium
|
||||
|
||||
* New upstream release
|
||||
|
||||
-- Ivan Savenko <saven.ivan@gmail.com> Fri, 22 Dec 2023 16:00:00 +0200
|
||||
|
||||
vcmi (1.4.0) jammy; urgency=medium
|
||||
|
||||
* New upstream release
|
||||
|
@ -4,7 +4,15 @@
|
||||
|
||||
# VCMI Project
|
||||
|
||||
VCMI is work-in-progress attempt to recreate engine for Heroes III, giving it new and extended possibilities.
|
||||
VCMI is an open-source recreation of Heroes of Might & Magic III engine, giving it new and extended possibilities.
|
||||
|
||||
<p>
|
||||
<img src="https://github.com/vcmi/VCMI.eu/blob/master/static/img/screenshots/1.3.0/Castle%20Siege.jpg?raw=true" alt="Vanilla town siege in extended window" style="height:120px;"/>
|
||||
<img src="https://github.com/vcmi/VCMI.eu/blob/master/static/img/screenshots/1.3.0/Town%20Screen%20with%20Radial%20Menu.jpg?raw=true" alt="Vanilla town view with radial menu for touchscreen devices" style="height:120px;"/>
|
||||
<img src="https://github.com/vcmi/VCMI.eu/blob/master/static/img/screenshots/1.4.0/Big%20spellbook.jpg?raw=true" alt="Large Spellbook with German translation" style="height:120px;"/>
|
||||
<img src="https://github.com/vcmi/VCMI.eu/blob/master/static/img/screenshots/1.4.0/Quick%20Hero%20Select%20Bastion.jpg?raw=true" alt="New widget for Hero selection, featuring Pavillon Town" style="height:120px;"/>
|
||||
</p>
|
||||
|
||||
|
||||
## Links
|
||||
|
||||
@ -27,6 +35,13 @@ Please see corresponding installation guide articles for details for your platfo
|
||||
- [Android](players/Installation_Android.md)
|
||||
- [iOS](players/Installation_iOS.md)
|
||||
|
||||
<p>
|
||||
<img src="https://github.com/vcmi/VCMI.eu/blob/master/static/img/screenshots/1.4.0/Antagarich%20Burning%20Battle.jpg?raw=true" alt="Forge Town in battle" style="height:120px;"/>
|
||||
<img src="https://github.com/vcmi/VCMI.eu/blob/master/static/img/screenshots/1.4.0/Town%20and%20Unit.jpg?raw=true" alt="Asylum town with new creature dialog" style="height:120px;"/>
|
||||
<img src="https://github.com/vcmi/VCMI.eu/blob/master/static/img/screenshots/1.4.0/Siege.jpg?raw=true" alt="Ruins town siege" style="height:120px;"/>
|
||||
<img src="https://github.com/vcmi/VCMI.eu/blob/master/static/img/screenshots/1.4.0/Editor.jpg?raw=true" alt="Map editor" style="height:120px;"/>
|
||||
</p>
|
||||
|
||||
## Documentation and guidelines for players
|
||||
|
||||
- [General information about VCMI Project](players/Manual.md)
|
||||
|
@ -68,6 +68,7 @@
|
||||
<category>StrategyGame</category>
|
||||
</categories>
|
||||
<releases>
|
||||
<release version="1.4.1" date="2023-12-22" />
|
||||
<release version="1.4.0" date="2023-12-08" />
|
||||
<release version="1.3.2" date="2023-09-15" />
|
||||
<release version="1.3.1" date="2023-08-18" />
|
||||
|
@ -313,7 +313,7 @@ QString CModListView::genModInfoText(CModEntry & mod)
|
||||
|
||||
result += replaceIfNotEmpty(getModNames(mod.getDependencies()), lineTemplate.arg(tr("Required mods")));
|
||||
result += replaceIfNotEmpty(getModNames(mod.getConflicts()), lineTemplate.arg(tr("Conflicting mods")));
|
||||
result += replaceIfNotEmpty(getModNames(mod.getValue("description").toStringList()), textTemplate.arg(tr("Description")));
|
||||
result += replaceIfNotEmpty(mod.getValue("description"), textTemplate.arg(tr("Description")));
|
||||
|
||||
result += "<p></p>"; // to get some empty space
|
||||
|
||||
|
@ -168,7 +168,10 @@ DLL_LINKAGE std::string MetaString::toString() const
|
||||
boost::replace_first(dst, "%d", std::to_string(numbers[nums++]));
|
||||
break;
|
||||
case EMessage::REPLACE_POSITIVE_NUMBER:
|
||||
boost::replace_first(dst, "%+d", '+' + std::to_string(numbers[nums++]));
|
||||
if (dst.find("%+d") != std::string::npos)
|
||||
boost::replace_first(dst, "%+d", '+' + std::to_string(numbers[nums++]));
|
||||
else
|
||||
boost::replace_first(dst, "%d", std::to_string(numbers[nums++]));
|
||||
break;
|
||||
default:
|
||||
logGlobal->error("MetaString processing error! Received message of type %d", static_cast<int>(elem));
|
||||
|
@ -132,6 +132,9 @@ int DamageCalculator::getActorAttackSlayer() const
|
||||
const std::string cachingStrSlayer = "type_SLAYER";
|
||||
static const auto selectorSlayer = Selector::type()(BonusType::SLAYER);
|
||||
|
||||
if (!info.defender->hasBonusOfType(BonusType::KING))
|
||||
return 0;
|
||||
|
||||
auto slayerEffects = info.attacker->getBonuses(selectorSlayer, cachingStrSlayer);
|
||||
auto slayerAffected = info.defender->unitType()->valOfBonuses(Selector::type()(BonusType::KING));
|
||||
|
||||
|
@ -1444,18 +1444,22 @@ bool CGameState::checkForVictory(const PlayerColor & player, const EventConditio
|
||||
{
|
||||
// list of players that need to control object to fulfull condition
|
||||
// NOTE: cgameinfocallback specified explicitly in order to get const version
|
||||
const auto & team = CGameInfoCallback::getPlayerTeam(player)->players;
|
||||
const auto * team = CGameInfoCallback::getPlayerTeam(player);
|
||||
|
||||
if (condition.objectID != ObjectInstanceID::NONE) // mode A - flag one specific object, like town
|
||||
{
|
||||
return team.count(getObjInstance(condition.objectID)->tempOwner) != 0;
|
||||
const auto * object = getObjInstance(condition.objectID);
|
||||
|
||||
if (!object)
|
||||
return false;
|
||||
return team->players.count(object->getOwner()) != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(const auto & elem : map->objects) // mode B - flag all objects of this type
|
||||
{
|
||||
//check not flagged objs
|
||||
if ( elem && elem->ID == condition.objectType.as<MapObjectID>() && team.count(elem->tempOwner) == 0 )
|
||||
if ( elem && elem->ID == condition.objectType.as<MapObjectID>() && team->players.count(elem->getOwner()) == 0 )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -452,10 +452,12 @@ void CObjectClassesHandler::generateExtraMonolithsForRMG(ObjectClass * container
|
||||
newPortal->type = portal->getIndex();
|
||||
|
||||
newPortal->subtype = portalVec.size(); //indexes must be unique, they are returned as a set
|
||||
newPortal->blockVisit = portal->blockVisit;
|
||||
newPortal->removable = portal->removable;
|
||||
|
||||
portalVec.push_back(newPortal);
|
||||
|
||||
registerObject(ModScope::scopeGame(), container->getJsonKey(), newPortal->subTypeName, newPortal->subtype);
|
||||
registerObject(newPortal->modScope, container->getJsonKey(), newPortal->subTypeName, newPortal->subtype);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,7 @@ void CHeroInstanceConstructor::afterLoadFinalization()
|
||||
{
|
||||
filters[entry.first] = LogicalExpression<HeroTypeID>(entry.second, [](const JsonNode & node)
|
||||
{
|
||||
return HeroTypeID(VLC->identifiers()->getIdentifier("hero", node.Vector()[0]).value());
|
||||
return HeroTypeID(VLC->identifiers()->getIdentifier("hero", node.Vector()[0]).value_or(-1));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -150,6 +150,11 @@ bool CGHeroInstance::isCoastVisitable() const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGHeroInstance::isBlockedVisitable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BattleField CGHeroInstance::getBattlefield() const
|
||||
{
|
||||
return BattleField::NONE;
|
||||
@ -280,7 +285,6 @@ CGHeroInstance::CGHeroInstance():
|
||||
setNodeType(HERO);
|
||||
ID = Obj::HERO;
|
||||
secSkills.emplace_back(SecondarySkill::NONE, -1);
|
||||
blockVisit = true;
|
||||
}
|
||||
|
||||
PlayerColor CGHeroInstance::getOwner() const
|
||||
|
@ -301,6 +301,7 @@ public:
|
||||
void updateFrom(const JsonNode & data) override;
|
||||
|
||||
bool isCoastVisitable() const override;
|
||||
bool isBlockedVisitable() const override;
|
||||
BattleField getBattlefield() const override;
|
||||
protected:
|
||||
void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;//synchr
|
||||
|
@ -1224,12 +1224,21 @@ TerrainId CGTownInstance::getNativeTerrain() const
|
||||
GrowthInfo::Entry::Entry(const std::string &format, int _count)
|
||||
: count(_count)
|
||||
{
|
||||
description = boost::str(boost::format(format) % count);
|
||||
MetaString formatter;
|
||||
formatter.appendRawString(format);
|
||||
formatter.replacePositiveNumber(count);
|
||||
|
||||
description = formatter.toString();
|
||||
}
|
||||
|
||||
GrowthInfo::Entry::Entry(int subID, const BuildingID & building, int _count): count(_count)
|
||||
{
|
||||
description = boost::str(boost::format("%s %+d") % (*VLC->townh)[subID]->town->buildings.at(building)->getNameTranslated() % count);
|
||||
MetaString formatter;
|
||||
formatter.appendRawString("%s %+d");
|
||||
formatter.replaceRawString((*VLC->townh)[subID]->town->buildings.at(building)->getNameTranslated());
|
||||
formatter.replacePositiveNumber(count);
|
||||
|
||||
description = formatter.toString();
|
||||
}
|
||||
|
||||
GrowthInfo::Entry::Entry(int _count, std::string fullDescription):
|
||||
|
@ -59,7 +59,7 @@ std::vector<Component> CRewardableObject::loadComponents(const CGHeroInstance *
|
||||
if (rewardIndices.empty())
|
||||
return result;
|
||||
|
||||
if (configuration.selectMode != Rewardable::SELECT_FIRST)
|
||||
if (configuration.selectMode != Rewardable::SELECT_FIRST && rewardIndices.size() > 1)
|
||||
{
|
||||
for (auto index : rewardIndices)
|
||||
result.push_back(configuration.info.at(index).reward.getDisplayedComponent(contextHero));
|
||||
|
@ -937,7 +937,7 @@ void CGSignBottle::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
auto vector = VLC->generaltexth->findStringsWithPrefix("core.randsign");
|
||||
std::string messageIdentifier = *RandomGeneratorUtil::nextItem(vector, rand);
|
||||
message.appendTextID(TextIdentifier("core", "randsign", messageIdentifier).get());
|
||||
message.appendTextID(messageIdentifier);
|
||||
}
|
||||
|
||||
if(ID == Obj::OCEAN_BOTTLE)
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __UCLIBC__
|
||||
#if defined(__UCLIBC__) || defined(__FreeBSD__)
|
||||
#undef major
|
||||
#undef minor
|
||||
#undef patch
|
||||
|
@ -162,9 +162,6 @@ void CPathfinder::calculatePaths()
|
||||
if(neighbour->locked)
|
||||
continue;
|
||||
|
||||
if (source.node->theNodeBefore && source.node->theNodeBefore->coord == neighbour->coord )
|
||||
continue; // block U-turns
|
||||
|
||||
if(!hlp->isLayerAvailable(neighbour->layer))
|
||||
continue;
|
||||
|
||||
|
@ -30,6 +30,7 @@ Rewardable::Limiter::Limiter()
|
||||
, heroLevel(-1)
|
||||
, manaPercentage(0)
|
||||
, manaPoints(0)
|
||||
, canLearnSkills(false)
|
||||
, primary(GameConstants::PRIMARY_SKILLS, 0)
|
||||
{
|
||||
}
|
||||
@ -45,6 +46,7 @@ bool operator==(const Rewardable::Limiter & l, const Rewardable::Limiter & r)
|
||||
&& l.manaPoints == r.manaPoints
|
||||
&& l.manaPercentage == r.manaPercentage
|
||||
&& l.secondary == r.secondary
|
||||
&& l.canLearnSkills == r.canLearnSkills
|
||||
&& l.creatures == r.creatures
|
||||
&& l.spells == r.spells
|
||||
&& l.artifacts == r.artifacts
|
||||
|
@ -580,7 +580,7 @@ void CMapGenOptions::finalize(CRandomGenerator & rand)
|
||||
}
|
||||
logGlobal->trace("Player %d: %s", player.second.getColor(), playerType);
|
||||
}
|
||||
logGlobal->info("Final player config: %d total, %d cpu-only", players.size(), static_cast<int>(getCompOnlyPlayerCount()));
|
||||
logGlobal->info("Final player config: %d total, %d cpu-only", players.size(), cpuOnlyPlayers);
|
||||
}
|
||||
|
||||
void CMapGenOptions::updatePlayers()
|
||||
@ -730,12 +730,6 @@ std::vector<const CRmgTemplate *> CMapGenOptions::getPossibleTemplates() const
|
||||
return true;
|
||||
}
|
||||
|
||||
if(compOnlyPlayerCount != CMapGenOptions::RANDOM_SIZE)
|
||||
{
|
||||
if (!tmpl->getHumanPlayers().isInRange(compOnlyPlayerCount))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
@ -128,6 +128,16 @@ void Object::Instance::setTemplate(TerrainId terrain, CRandomGenerator & rng)
|
||||
auto terrainName = VLC->terrainTypeHandler->getById(terrain)->getNameTranslated();
|
||||
throw rmgException(boost::str(boost::format("Did not find graphics for object (%d,%d) at %s") % dObject.ID % dObject.getObjTypeIndex() % terrainName));
|
||||
}
|
||||
//Get terrain-specific template if possible
|
||||
int leastTerrains = (*boost::min_element(templates, [](const std::shared_ptr<const ObjectTemplate> & tmp1, const std::shared_ptr<const ObjectTemplate> & tmp2)
|
||||
{
|
||||
return tmp1->getAllowedTerrains().size() < tmp2->getAllowedTerrains().size();
|
||||
}))->getAllowedTerrains().size();
|
||||
|
||||
vstd::erase_if(templates, [leastTerrains](const std::shared_ptr<const ObjectTemplate> & tmp)
|
||||
{
|
||||
return tmp->getAllowedTerrains().size() > leastTerrains;
|
||||
});
|
||||
|
||||
dObject.appearance = *RandomGeneratorUtil::nextItem(templates, rng);
|
||||
dAccessibleAreaCache.clear();
|
||||
|
@ -107,8 +107,8 @@ const CSpell::LevelInfo & CSpell::getLevelInfo(const int32_t level) const
|
||||
{
|
||||
if(level < 0 || level >= GameConstants::SPELL_SCHOOL_LEVELS)
|
||||
{
|
||||
logGlobal->error("CSpell::getLevelInfo: invalid school level %d", level);
|
||||
return levels.at(0);
|
||||
logGlobal->error("CSpell::getLevelInfo: invalid school mastery level %d", level);
|
||||
return levels.at(MasteryLevel::EXPERT);
|
||||
}
|
||||
|
||||
return levels.at(level);
|
||||
|
@ -42,6 +42,12 @@ void Summon::adjustTargetTypes(std::vector<TargetType> & types) const
|
||||
|
||||
bool Summon::applicable(Problem & problem, const Mechanics * m) const
|
||||
{
|
||||
if (creature == CreatureID::NONE)
|
||||
{
|
||||
logMod->error("Attempt to summon non-existing creature!");
|
||||
return m->adaptGenericProblem(problem);
|
||||
}
|
||||
|
||||
if(exclusive)
|
||||
{
|
||||
//check if there are summoned creatures of other type
|
||||
|
@ -1133,7 +1133,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
|
||||
if (guardian && getVisitingHero(guardian) != nullptr)
|
||||
return complainRet("Cannot move hero, destination monster is busy!");
|
||||
|
||||
if (objectToVisit && getVisitingHero(objectToVisit) != nullptr)
|
||||
if (objectToVisit && getVisitingHero(objectToVisit) != nullptr && getVisitingHero(objectToVisit) != h)
|
||||
return complainRet("Cannot move hero, destination object is busy!");
|
||||
|
||||
if (objectToVisit &&
|
||||
|
@ -1032,7 +1032,7 @@ void BattleActionProcessor::makeAttack(const CBattleInfoCallback & battle, const
|
||||
const CStack * actor = item.first;
|
||||
int64_t rawDamage = item.second;
|
||||
|
||||
const CGHeroInstance * actorOwner = battle.battleGetFightingHero(actor->unitOwner());
|
||||
const CGHeroInstance * actorOwner = battle.battleGetFightingHero(actor->unitSide());
|
||||
|
||||
if(actorOwner)
|
||||
{
|
||||
@ -1088,7 +1088,10 @@ void BattleActionProcessor::attackCasting(const CBattleInfoCallback & battle, bo
|
||||
TConstBonusListPtr spells = attacker->getBonuses(Selector::type()(attackMode));
|
||||
for(const auto & sf : *spells)
|
||||
{
|
||||
spellsToCast.insert(sf->subtype.as<SpellID>());
|
||||
if (sf->subtype.as<SpellID>() != SpellID())
|
||||
spellsToCast.insert(sf->subtype.as<SpellID>());
|
||||
else
|
||||
logMod->error("Invalid spell to cast during attack!");
|
||||
}
|
||||
for(SpellID spellID : spellsToCast)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user