mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-12 02:28:11 +02:00
Merge remote-tracking branch 'upstream/develop' into lobby
This commit is contained in:
commit
e7a8466e2b
@ -774,8 +774,10 @@ void AIGateway::makeTurn()
|
||||
retrieveVisitableObjs();
|
||||
}
|
||||
|
||||
#if NKAI_TRACE_LEVEL == 0
|
||||
try
|
||||
{
|
||||
#endif
|
||||
nullkiller->makeTurn();
|
||||
|
||||
//for debug purpose
|
||||
@ -784,6 +786,7 @@ void AIGateway::makeTurn()
|
||||
if (h->movement)
|
||||
logAi->warn("Hero %s has %d MP left", h->name, h->movement);
|
||||
}
|
||||
#if NKAI_TRACE_LEVEL == 0
|
||||
}
|
||||
catch (boost::thread_interrupted & e)
|
||||
{
|
||||
@ -795,6 +798,7 @@ void AIGateway::makeTurn()
|
||||
{
|
||||
logAi->debug("Making turn thread has caught an exception: %s", e.what());
|
||||
}
|
||||
#endif
|
||||
|
||||
endTurn();
|
||||
}
|
||||
|
@ -334,7 +334,7 @@ BuildingInfo::BuildingInfo()
|
||||
buildCost = 0;
|
||||
buildCostWithPrerequisits = 0;
|
||||
prerequisitesCount = 0;
|
||||
name = "";
|
||||
name.clear();
|
||||
armyStrength = 0;
|
||||
}
|
||||
|
||||
|
@ -57,8 +57,7 @@ Goals::TGoalVec BuyArmyBehavior::decompose() const
|
||||
continue;
|
||||
}
|
||||
|
||||
if(ai->nullkiller->heroManager->getHeroRole(targetHero) == HeroRole::MAIN
|
||||
&& targetHero->getArmyStrength() >= 300)
|
||||
if(ai->nullkiller->heroManager->getHeroRole(targetHero) == HeroRole::MAIN)
|
||||
{
|
||||
auto reinforcement = ai->nullkiller->armyManager->howManyReinforcementsCanGet(
|
||||
targetHero,
|
||||
|
@ -307,7 +307,7 @@ void Nullkiller::executeTask(Goals::TTask task)
|
||||
{
|
||||
logAi->trace("Task %s completed", task->toString());
|
||||
}
|
||||
catch(std::exception & e)
|
||||
catch(cannotFulfillGoalException & e)
|
||||
{
|
||||
logAi->debug("Failed to realize subgoal of type %s, I will stop.", taskDescr);
|
||||
logAi->debug("The error message was: %s", e.what());
|
||||
|
@ -1086,7 +1086,7 @@ void AINodeStorage::calculateTownPortal(
|
||||
for(const CGTownInstance * targetTown : towns)
|
||||
{
|
||||
// TODO: allow to hide visiting hero in garrison
|
||||
if(targetTown->visitingHero)
|
||||
if(targetTown->visitingHero && maskMap.find(targetTown->visitingHero.get()) != maskMap.end())
|
||||
{
|
||||
auto basicMask = maskMap.at(targetTown->visitingHero.get());
|
||||
bool heroIsInChain = (actor->chainMask & basicMask) != 0;
|
||||
|
@ -181,6 +181,12 @@ bool CCallback::assembleArtifacts (const CGHeroInstance * hero, ArtifactPosition
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCallback::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap)
|
||||
{
|
||||
BulkExchangeArtifacts bma(srcHero, dstHero, swap);
|
||||
sendRequest(&bma);
|
||||
}
|
||||
|
||||
bool CCallback::buildBuilding(const CGTownInstance *town, BuildingID buildingID)
|
||||
{
|
||||
if(town->tempOwner!=player)
|
||||
|
@ -94,6 +94,10 @@ public:
|
||||
virtual int bulkSplitStack(ObjectInstanceID armyId, SlotID srcSlot, int howMany = 1) = 0;
|
||||
virtual int bulkSmartSplitStack(ObjectInstanceID armyId, SlotID srcSlot) = 0;
|
||||
virtual int bulkMergeStacks(ObjectInstanceID armyId, SlotID srcSlot) = 0;
|
||||
|
||||
|
||||
// Moves all artifacts from one hero to another
|
||||
virtual void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) = 0;
|
||||
};
|
||||
|
||||
class CBattleCallback : public IBattleCallback, public CPlayerBattleCallback
|
||||
@ -151,6 +155,7 @@ public:
|
||||
bool dismissHero(const CGHeroInstance * hero) override;
|
||||
bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2) override;
|
||||
bool assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) override;
|
||||
void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) override;
|
||||
bool buildBuilding(const CGTownInstance *town, BuildingID buildingID) override;
|
||||
void recruitCreatures(const CGDwelling * obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1) override;
|
||||
bool dismissCreature(const CArmedInstance *obj, SlotID stackPos) override;
|
||||
|
@ -1,6 +1,7 @@
|
||||
[![GitHub](https://github.com/vcmi/vcmi/actions/workflows/github.yml/badge.svg)](https://github.com/vcmi/vcmi/actions/workflows/github.yml)
|
||||
[![AppVeyor Build status](https://ci.appveyor.com/api/projects/status/github/vcmi/vcmi?branch=develop&svg=true)](https://ci.appveyor.com/project/vcmi/vcmi)
|
||||
[![Coverity Scan Build Status](https://scan.coverity.com/projects/vcmi/badge.svg)](https://scan.coverity.com/projects/vcmi)
|
||||
[![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/1.0.0/total)](https://github.com/vcmi/vcmi/releases/tag/1.0.0)
|
||||
# VCMI Project
|
||||
VCMI is work-in-progress attempt to recreate engine for Heroes III, giving it new and extended possibilities.
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include <SDL_mixer.h>
|
||||
#include <SDL.h>
|
||||
|
||||
#include "CMusicHandler.h"
|
||||
#include "CGameInfo.h"
|
||||
@ -410,15 +411,15 @@ void CMusicHandler::release()
|
||||
CAudioBase::release();
|
||||
}
|
||||
|
||||
void CMusicHandler::playMusic(const std::string & musicURI, bool loop)
|
||||
void CMusicHandler::playMusic(const std::string & musicURI, bool loop, bool fromStart)
|
||||
{
|
||||
if (current && current->isTrack(musicURI))
|
||||
return;
|
||||
|
||||
queueNext(this, "", musicURI, loop);
|
||||
queueNext(this, "", musicURI, loop, fromStart);
|
||||
}
|
||||
|
||||
void CMusicHandler::playMusicFromSet(const std::string & whichSet, bool loop)
|
||||
void CMusicHandler::playMusicFromSet(const std::string & whichSet, bool loop, bool fromStart)
|
||||
{
|
||||
auto selectedSet = musicsSet.find(whichSet);
|
||||
if (selectedSet == musicsSet.end())
|
||||
@ -431,10 +432,10 @@ void CMusicHandler::playMusicFromSet(const std::string & whichSet, bool loop)
|
||||
return;
|
||||
|
||||
// in this mode - play random track from set
|
||||
queueNext(this, whichSet, "", loop);
|
||||
queueNext(this, whichSet, "", loop, fromStart);
|
||||
}
|
||||
|
||||
void CMusicHandler::playMusicFromSet(const std::string & whichSet, const std::string & entryID, bool loop)
|
||||
void CMusicHandler::playMusicFromSet(const std::string & whichSet, const std::string & entryID, bool loop, bool fromStart)
|
||||
{
|
||||
auto selectedSet = musicsSet.find(whichSet);
|
||||
if (selectedSet == musicsSet.end())
|
||||
@ -454,7 +455,7 @@ void CMusicHandler::playMusicFromSet(const std::string & whichSet, const std::st
|
||||
return;
|
||||
|
||||
// in this mode - play specific track from set
|
||||
queueNext(this, "", selectedEntry->second, loop);
|
||||
queueNext(this, "", selectedEntry->second, loop, fromStart);
|
||||
}
|
||||
|
||||
void CMusicHandler::queueNext(std::unique_ptr<MusicEntry> queued)
|
||||
@ -473,11 +474,11 @@ void CMusicHandler::queueNext(std::unique_ptr<MusicEntry> queued)
|
||||
}
|
||||
}
|
||||
|
||||
void CMusicHandler::queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped)
|
||||
void CMusicHandler::queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped, bool fromStart)
|
||||
{
|
||||
try
|
||||
{
|
||||
queueNext(make_unique<MusicEntry>(owner, setName, musicURI, looped));
|
||||
queueNext(make_unique<MusicEntry>(owner, setName, musicURI, looped, fromStart));
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
@ -526,10 +527,13 @@ void CMusicHandler::musicFinishedCallback()
|
||||
}
|
||||
}
|
||||
|
||||
MusicEntry::MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped):
|
||||
MusicEntry::MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped, bool fromStart):
|
||||
owner(owner),
|
||||
music(nullptr),
|
||||
startTime(uint32_t(-1)),
|
||||
startPosition(0),
|
||||
loop(looped ? -1 : 1),
|
||||
fromStart(fromStart),
|
||||
setName(std::move(setName))
|
||||
{
|
||||
if (!musicURI.empty())
|
||||
@ -578,11 +582,25 @@ bool MusicEntry::play()
|
||||
}
|
||||
|
||||
logGlobal->trace("Playing music file %s", currentName);
|
||||
if(Mix_PlayMusic(music, 1) == -1)
|
||||
|
||||
if ( !fromStart && owner->trackPositions.count(currentName) > 0 && owner->trackPositions[currentName] > 0)
|
||||
{
|
||||
float timeToStart = owner->trackPositions[currentName];
|
||||
startPosition = std::round(timeToStart * 1000);
|
||||
|
||||
if (Mix_FadeInMusicPos(music, 1, 1000, timeToStart) == -1)
|
||||
{
|
||||
logGlobal->error("Unable to play music (%s)", Mix_GetError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(Mix_PlayMusic(music, 1) == -1)
|
||||
{
|
||||
logGlobal->error("Unable to play music (%s)", Mix_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
startTime = SDL_GetTicks();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -590,8 +608,13 @@ bool MusicEntry::stop(int fade_ms)
|
||||
{
|
||||
if (Mix_PlayingMusic())
|
||||
{
|
||||
logGlobal->trace("Stopping music file %s", currentName);
|
||||
loop = 0;
|
||||
uint32_t endTime = SDL_GetTicks();
|
||||
assert(startTime != uint32_t(-1));
|
||||
float playDuration = (endTime - startTime + startPosition) / 1000.f;
|
||||
owner->trackPositions[currentName] = playDuration;
|
||||
logGlobal->info("Stopping music file %s at %f", currentName, playDuration);
|
||||
|
||||
Mix_FadeOutMusic(fade_ms);
|
||||
return true;
|
||||
}
|
||||
|
@ -99,6 +99,9 @@ class MusicEntry
|
||||
Mix_Music *music;
|
||||
|
||||
int loop; // -1 = indefinite
|
||||
bool fromStart;
|
||||
uint32_t startTime;
|
||||
uint32_t startPosition;
|
||||
//if not null - set from which music will be randomly selected
|
||||
std::string setName;
|
||||
std::string currentName;
|
||||
@ -110,7 +113,7 @@ public:
|
||||
bool isSet(std::string setName);
|
||||
bool isTrack(std::string trackName);
|
||||
|
||||
MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped);
|
||||
MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped, bool fromStart);
|
||||
~MusicEntry();
|
||||
|
||||
bool play();
|
||||
@ -128,10 +131,11 @@ private:
|
||||
std::unique_ptr<MusicEntry> current;
|
||||
std::unique_ptr<MusicEntry> next;
|
||||
|
||||
void queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped);
|
||||
void queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped, bool fromStart);
|
||||
void queueNext(std::unique_ptr<MusicEntry> queued);
|
||||
|
||||
std::map<std::string, std::map<std::string, std::string>> musicsSet;
|
||||
std::map<std::string, float> trackPositions;
|
||||
public:
|
||||
|
||||
CMusicHandler();
|
||||
@ -145,11 +149,11 @@ public:
|
||||
void setVolume(ui32 percent) override;
|
||||
|
||||
/// play track by URI, if loop = true music will be looped
|
||||
void playMusic(const std::string & musicURI, bool loop);
|
||||
void playMusic(const std::string & musicURI, bool loop, bool fromStart);
|
||||
/// play random track from this set
|
||||
void playMusicFromSet(const std::string & musicSet, bool loop);
|
||||
void playMusicFromSet(const std::string & musicSet, bool loop, bool fromStart);
|
||||
/// play specific track from set
|
||||
void playMusicFromSet(const std::string & musicSet, const std::string & entryID, bool loop);
|
||||
void playMusicFromSet(const std::string & musicSet, const std::string & entryID, bool loop, bool fromStart);
|
||||
void stopMusic(int fade_ms=1000);
|
||||
void musicFinishedCallback();
|
||||
|
||||
|
@ -276,7 +276,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
|
||||
{
|
||||
updateAmbientSounds();
|
||||
//We may need to change music - select new track, music handler will change it if needed
|
||||
CCS->musich->playMusicFromSet("terrain", LOCPLINT->cb->getTile(hero->visitablePos())->terType->name, true);
|
||||
CCS->musich->playMusicFromSet("terrain", LOCPLINT->cb->getTile(hero->visitablePos())->terType->name, true, false);
|
||||
|
||||
if(details.result == TryMoveHero::TELEPORTATION)
|
||||
{
|
||||
@ -2338,10 +2338,13 @@ void CPlayerInterface::acceptTurn()
|
||||
while(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt().get()))
|
||||
iw->close();
|
||||
}
|
||||
waitWhileDialog();
|
||||
|
||||
if(CSH->howManyPlayerInterfaces() > 1)
|
||||
{
|
||||
waitWhileDialog(); // wait for player to accept turn in hot-seat mode
|
||||
|
||||
adventureInt->startTurn();
|
||||
}
|
||||
|
||||
adventureInt->heroList.update();
|
||||
adventureInt->townList.update();
|
||||
@ -2591,6 +2594,12 @@ void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const Artifact
|
||||
if (artWin)
|
||||
artWin->artifactMoved(src, dst);
|
||||
}
|
||||
if(!GH.objsToBlit.empty())
|
||||
GH.objsToBlit.back()->redraw();
|
||||
}
|
||||
|
||||
void CPlayerInterface::artifactPossibleAssembling(const ArtifactLocation & dst)
|
||||
{
|
||||
askToAssembleArtifact(dst);
|
||||
}
|
||||
|
||||
|
@ -133,6 +133,7 @@ public:
|
||||
void artifactRemoved(const ArtifactLocation &al) override;
|
||||
void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst) override;
|
||||
void artifactAssembled(const ArtifactLocation &al) override;
|
||||
void artifactPossibleAssembling(const ArtifactLocation & dst) override;
|
||||
void artifactDisassembled(const ArtifactLocation &al) override;
|
||||
|
||||
void heroVisit(const CGHeroInstance * visitor, const CGObjectInstance * visitedObj, bool start) override;
|
||||
|
@ -519,7 +519,7 @@ void CServerHandler::sendMessage(const std::string & txt) const
|
||||
std::string connectedId, playerColorId;
|
||||
readed >> connectedId;
|
||||
readed >> playerColorId;
|
||||
if(connectedId.length(), playerColorId.length()) // BUG https://bugs.vcmi.eu/view.php?id=3144
|
||||
if(connectedId.length() && playerColorId.length())
|
||||
{
|
||||
ui8 connected = boost::lexical_cast<int>(connectedId);
|
||||
auto color = PlayerColor(boost::lexical_cast<int>(playerColorId));
|
||||
|
@ -381,7 +381,7 @@ void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool forceRedraw, boo
|
||||
|
||||
void CVideoPlayer::close()
|
||||
{
|
||||
fname = "";
|
||||
fname.clear();
|
||||
if (sws)
|
||||
{
|
||||
sws_freeContext(sws);
|
||||
|
@ -275,8 +275,31 @@ void EraseArtifact::applyCl(CClient *cl)
|
||||
void MoveArtifact::applyCl(CClient *cl)
|
||||
{
|
||||
callInterfaceIfPresent(cl, src.owningPlayer(), &IGameEventsReceiver::artifactMoved, src, dst);
|
||||
callInterfaceIfPresent(cl, src.owningPlayer(), &IGameEventsReceiver::artifactPossibleAssembling, dst);
|
||||
if(src.owningPlayer() != dst.owningPlayer())
|
||||
{
|
||||
callInterfaceIfPresent(cl, dst.owningPlayer(), &IGameEventsReceiver::artifactMoved, src, dst);
|
||||
callInterfaceIfPresent(cl, dst.owningPlayer(), &IGameEventsReceiver::artifactPossibleAssembling, dst);
|
||||
}
|
||||
}
|
||||
|
||||
void BulkMoveArtifacts::applyCl(CClient * cl)
|
||||
{
|
||||
auto applyMove = [this, cl](std::vector<LinkedSlots> & artsPack) -> void
|
||||
{
|
||||
for(auto & slotToMove : artsPack)
|
||||
{
|
||||
auto srcLoc = ArtifactLocation(srcArtHolder, slotToMove.srcPos);
|
||||
auto dstLoc = ArtifactLocation(dstArtHolder, slotToMove.dstPos);
|
||||
callInterfaceIfPresent(cl, srcLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc);
|
||||
if(srcLoc.owningPlayer() != dstLoc.owningPlayer())
|
||||
callInterfaceIfPresent(cl, dstLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc);
|
||||
}
|
||||
};
|
||||
|
||||
applyMove(artsPack0);
|
||||
if(swap)
|
||||
applyMove(artsPack1);
|
||||
}
|
||||
|
||||
void AssembledArtifact::applyCl(CClient *cl)
|
||||
|
@ -411,7 +411,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
|
||||
{
|
||||
if(LOCPLINT->battleInt)
|
||||
{
|
||||
CCS->musich->playMusicFromSet("battle", true);
|
||||
CCS->musich->playMusicFromSet("battle", true, true);
|
||||
battleActionsStarted = true;
|
||||
blockUI(settings["session"]["spectate"].Bool());
|
||||
battleIntroSoundChannel = -1;
|
||||
@ -457,7 +457,7 @@ CBattleInterface::~CBattleInterface()
|
||||
if (adventureInt && adventureInt->selection)
|
||||
{
|
||||
const auto & terrain = *(LOCPLINT->cb->getTile(adventureInt->selection->visitablePos())->terType);
|
||||
CCS->musich->playMusicFromSet("terrain", terrain.name, true);
|
||||
CCS->musich->playMusicFromSet("terrain", terrain.name, true, false);
|
||||
}
|
||||
animsAreDisplayed.setn(false);
|
||||
}
|
||||
@ -859,17 +859,17 @@ void CBattleInterface::reallySurrender()
|
||||
|
||||
void CBattleInterface::bAutofightf()
|
||||
{
|
||||
if (spellDestSelectMode) //we are casting a spell
|
||||
if(spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
//Stop auto-fight mode
|
||||
if (curInt->isAutoFightOn)
|
||||
if(curInt->isAutoFightOn)
|
||||
{
|
||||
assert(curInt->autofightingAI);
|
||||
curInt->isAutoFightOn = false;
|
||||
logGlobal->trace("Stopping the autofight...");
|
||||
}
|
||||
else
|
||||
else if(!curInt->autofightingAI)
|
||||
{
|
||||
curInt->isAutoFightOn = true;
|
||||
blockUI(true);
|
||||
@ -1619,7 +1619,9 @@ void CBattleInterface::activateStack()
|
||||
|
||||
setActiveStack(stackToActivate);
|
||||
stackToActivate = nullptr;
|
||||
const CStack *s = activeStack;
|
||||
const CStack * s = activeStack;
|
||||
if(!s)
|
||||
return;
|
||||
|
||||
queue->update();
|
||||
redrawBackgroundWithHexes(activeStack);
|
||||
|
@ -506,7 +506,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult & br, CPlayerInterfa
|
||||
break;
|
||||
}
|
||||
|
||||
CCS->musich->playMusic("Music/Win Battle", false);
|
||||
CCS->musich->playMusic("Music/Win Battle", false, true);
|
||||
CCS->videoh->open("WIN3.BIK");
|
||||
std::string str = CGI->generaltexth->allTexts[text];
|
||||
|
||||
@ -543,7 +543,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult & br, CPlayerInterfa
|
||||
logGlobal->error("Invalid battle result code %d. Assumed normal.", static_cast<int>(br.result));
|
||||
break;
|
||||
}
|
||||
CCS->musich->playMusic(musicName, false);
|
||||
CCS->musich->playMusic(musicName, false, true);
|
||||
CCS->videoh->open(videoName);
|
||||
|
||||
labels.push_back(std::make_shared<CLabel>(235, 235, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[text]));
|
||||
|
@ -115,7 +115,7 @@ void CMenuScreen::show(SDL_Surface * to)
|
||||
|
||||
void CMenuScreen::activate()
|
||||
{
|
||||
CCS->musich->playMusic("Music/MainMenu", true);
|
||||
CCS->musich->playMusic("Music/MainMenu", true, true);
|
||||
if(!config["video"].isNull())
|
||||
CCS->videoh->open(config["video"]["name"].String());
|
||||
CIntObject::activate();
|
||||
|
@ -29,7 +29,7 @@ CPrologEpilogVideo::CPrologEpilogVideo(CCampaignScenario::SScenarioPrologEpilog
|
||||
updateShadow();
|
||||
|
||||
CCS->videoh->open(CCampaignHandler::prologVideoName(spe.prologVideo));
|
||||
CCS->musich->playMusic("Music/" + CCampaignHandler::prologMusicName(spe.prologMusic), true);
|
||||
CCS->musich->playMusic("Music/" + CCampaignHandler::prologMusicName(spe.prologMusic), true, true);
|
||||
// MPTODO: Custom campaign crashing on this?
|
||||
// voiceSoundHandle = CCS->soundh->playSound(CCampaignHandler::prologVoiceName(spe.prologVideo));
|
||||
|
||||
|
@ -536,6 +536,8 @@ void CMapHandler::CMapWorldViewBlitter::drawTileOverlay(SDL_Surface * targetSurf
|
||||
for(auto & object : objects)
|
||||
{
|
||||
const CGObjectInstance * obj = object.obj;
|
||||
if(!obj)
|
||||
continue;
|
||||
|
||||
const bool sameLevel = obj->pos.z == pos.z;
|
||||
|
||||
|
@ -1158,7 +1158,7 @@ void CInGameConsole::endEnteringText(bool printEnteredText)
|
||||
previouslyEntered.push_back(txt);
|
||||
//print(txt);
|
||||
}
|
||||
enteredText = "";
|
||||
enteredText.clear();
|
||||
if(GH.topInt() == adventureInt)
|
||||
{
|
||||
GH.statusbar->alignment = CENTER;
|
||||
|
@ -367,7 +367,7 @@ void CHeroArtPlace::setArtifact(const CArtifactInstance *art)
|
||||
if(!art)
|
||||
{
|
||||
image->disable();
|
||||
text = std::string();
|
||||
text.clear();
|
||||
hoverText = CGI->generaltexth->allTexts[507];
|
||||
return;
|
||||
}
|
||||
@ -1034,7 +1034,7 @@ void CCommanderArtPlace::setArtifact(const CArtifactInstance * art)
|
||||
if (!art)
|
||||
{
|
||||
image->disable();
|
||||
text = std::string();
|
||||
text.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -577,7 +577,7 @@ void CTextInput::textInputed(const SDL_TextInputEvent & event)
|
||||
redraw();
|
||||
cb(text);
|
||||
}
|
||||
newText = "";
|
||||
newText.clear();
|
||||
|
||||
#ifdef VCMI_ANDROID
|
||||
notifyAndroidTextInputChanged(text);
|
||||
|
@ -573,7 +573,7 @@ CAdvMapInt::CAdvMapInt():
|
||||
strongInterest = true; // handle all mouse move events to prevent dead mouse move space in fullscreen mode
|
||||
townList.onSelect = std::bind(&CAdvMapInt::selectionChanged,this);
|
||||
bg = BitmapHandler::loadBitmap(ADVOPT.mainGraphic);
|
||||
if (ADVOPT.worldViewGraphic != "")
|
||||
if(!ADVOPT.worldViewGraphic.empty())
|
||||
{
|
||||
bgWorldView = BitmapHandler::loadBitmap(ADVOPT.worldViewGraphic);
|
||||
}
|
||||
@ -1413,7 +1413,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView)
|
||||
auto pos = sel->visitablePos();
|
||||
auto tile = LOCPLINT->cb->getTile(pos);
|
||||
if(tile)
|
||||
CCS->musich->playMusicFromSet("terrain", tile->terType->name, true);
|
||||
CCS->musich->playMusicFromSet("terrain", tile->terType->name, true, false);
|
||||
}
|
||||
if(centerView)
|
||||
centerOn(sel);
|
||||
@ -1863,7 +1863,7 @@ void CAdvMapInt::aiTurnStarted()
|
||||
return;
|
||||
|
||||
adjustActiveness(true);
|
||||
CCS->musich->playMusicFromSet("enemy-turn", true);
|
||||
CCS->musich->playMusicFromSet("enemy-turn", true, false);
|
||||
adventureInt->minimap.setAIRadar(true);
|
||||
adventureInt->infoBar.startEnemyTurn(LOCPLINT->cb->getCurrentPlayer());
|
||||
adventureInt->infoBar.showAll(screen);//force refresh on inactive object
|
||||
|
@ -1171,7 +1171,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst
|
||||
townlist->onSelect = std::bind(&CCastleInterface::townChange, this);
|
||||
|
||||
recreateIcons();
|
||||
CCS->musich->playMusic(town->town->clientInfo.musicTheme, true);
|
||||
CCS->musich->playMusic(town->town->clientInfo.musicTheme, true, false);
|
||||
}
|
||||
|
||||
CCastleInterface::~CCastleInterface()
|
||||
|
@ -593,7 +593,7 @@ void CSpellWindow::SpellArea::clickRight(tribool down, bool previousState)
|
||||
std::string dmgInfo;
|
||||
auto causedDmg = owner->myInt->cb->estimateSpellDamage(mySpell, owner->myHero);
|
||||
if(causedDmg == 0 || mySpell->id == SpellID::TITANS_LIGHTNING_BOLT) //Titan's Lightning Bolt already has damage info included
|
||||
dmgInfo = "";
|
||||
dmgInfo.clear();
|
||||
else
|
||||
{
|
||||
dmgInfo = CGI->generaltexth->allTexts[343];
|
||||
|
@ -192,7 +192,7 @@ void CTradeWindow::CTradeableItem::clickLeft(tribool down, bool previousState)
|
||||
|
||||
aw->arts->artifactsOnAltar.erase(art);
|
||||
setID(-1);
|
||||
subtitle = "";
|
||||
subtitle.clear();
|
||||
aw->deal->block(!aw->arts->artifactsOnAltar.size());
|
||||
}
|
||||
|
||||
|
@ -872,41 +872,6 @@ std::function<void()> CExchangeController::onMoveArmyToRight()
|
||||
return [&]() { moveArmy(true); };
|
||||
}
|
||||
|
||||
void CExchangeController::swapArtifacts(ArtifactPosition slot)
|
||||
{
|
||||
bool leftHasArt = !left->isPositionFree(slot);
|
||||
bool rightHasArt = !right->isPositionFree(slot);
|
||||
|
||||
if(!leftHasArt && !rightHasArt)
|
||||
return;
|
||||
|
||||
ArtifactLocation leftLocation = ArtifactLocation(left, slot);
|
||||
ArtifactLocation rightLocation = ArtifactLocation(right, slot);
|
||||
|
||||
if(leftHasArt && !left->artifactsWorn.at(slot).artifact->canBePutAt(rightLocation, true))
|
||||
return;
|
||||
|
||||
if(rightHasArt && !right->artifactsWorn.at(slot).artifact->canBePutAt(leftLocation, true))
|
||||
return;
|
||||
|
||||
if(leftHasArt)
|
||||
{
|
||||
if(rightHasArt)
|
||||
{
|
||||
auto art = right->getArt(slot);
|
||||
|
||||
cb->swapArtifacts(leftLocation, rightLocation);
|
||||
cb->swapArtifacts(ArtifactLocation(right, right->getArtPos(art)), leftLocation);
|
||||
}
|
||||
else
|
||||
cb->swapArtifacts(leftLocation, rightLocation);
|
||||
}
|
||||
else
|
||||
{
|
||||
cb->swapArtifacts(rightLocation, leftLocation);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<CArtifactInstance *> getBackpackArts(const CGHeroInstance * hero)
|
||||
{
|
||||
std::vector<CArtifactInstance *> result;
|
||||
@ -919,92 +884,13 @@ std::vector<CArtifactInstance *> getBackpackArts(const CGHeroInstance * hero)
|
||||
return result;
|
||||
}
|
||||
|
||||
const std::vector<ArtifactPosition> unmovablePositions = {ArtifactPosition::SPELLBOOK, ArtifactPosition::MACH4};
|
||||
|
||||
bool isArtRemovable(const std::pair<ArtifactPosition, ArtSlotInfo> & slot)
|
||||
{
|
||||
return slot.second.artifact
|
||||
&& !slot.second.locked
|
||||
&& !vstd::contains(unmovablePositions, slot.first);
|
||||
}
|
||||
|
||||
// Puts all composite arts to backpack and returns their previous location
|
||||
std::vector<HeroArtifact> CExchangeController::moveCompositeArtsToBackpack()
|
||||
{
|
||||
std::vector<const CGHeroInstance *> sides = {left, right};
|
||||
std::vector<HeroArtifact> artPositions;
|
||||
|
||||
for(auto hero : sides)
|
||||
{
|
||||
for(int i = ArtifactPosition::HEAD; i < ArtifactPosition::AFTER_LAST; i++)
|
||||
{
|
||||
auto artPosition = ArtifactPosition(i);
|
||||
auto art = hero->getArt(artPosition);
|
||||
|
||||
if(art && art->canBeDisassembled())
|
||||
{
|
||||
cb->swapArtifacts(
|
||||
ArtifactLocation(hero, artPosition),
|
||||
ArtifactLocation(hero, ArtifactPosition(GameConstants::BACKPACK_START)));
|
||||
|
||||
artPositions.push_back(HeroArtifact(hero, art, artPosition));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return artPositions;
|
||||
}
|
||||
|
||||
void CExchangeController::swapArtifacts()
|
||||
{
|
||||
for(int i = ArtifactPosition::HEAD; i < ArtifactPosition::AFTER_LAST; i++)
|
||||
{
|
||||
if(vstd::contains(unmovablePositions, i))
|
||||
continue;
|
||||
|
||||
swapArtifacts(ArtifactPosition(i));
|
||||
}
|
||||
|
||||
auto leftHeroBackpack = getBackpackArts(left);
|
||||
auto rightHeroBackpack = getBackpackArts(right);
|
||||
|
||||
for(auto leftArt : leftHeroBackpack)
|
||||
{
|
||||
cb->swapArtifacts(
|
||||
ArtifactLocation(left, left->getArtPos(leftArt)),
|
||||
ArtifactLocation(right, ArtifactPosition(GameConstants::BACKPACK_START)));
|
||||
}
|
||||
|
||||
for(auto rightArt : rightHeroBackpack)
|
||||
{
|
||||
cb->swapArtifacts(
|
||||
ArtifactLocation(right, right->getArtPos(rightArt)),
|
||||
ArtifactLocation(left, ArtifactPosition(GameConstants::BACKPACK_START)));
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void()> CExchangeController::onSwapArtifacts()
|
||||
{
|
||||
return [&]()
|
||||
{
|
||||
GsThread::run([=]
|
||||
{
|
||||
// it is not possible directly exchange composite artifacts like Angelic Alliance and Armor of Damned
|
||||
auto compositeArtLocations = moveCompositeArtsToBackpack();
|
||||
|
||||
swapArtifacts();
|
||||
|
||||
for(HeroArtifact artLocation : compositeArtLocations)
|
||||
{
|
||||
auto target = artLocation.hero == left ? right : left;
|
||||
auto currentPos = target->getArtPos(artLocation.artifact);
|
||||
|
||||
cb->swapArtifacts(
|
||||
ArtifactLocation(target, currentPos),
|
||||
ArtifactLocation(target, artLocation.artPosition));
|
||||
}
|
||||
|
||||
view->redraw();
|
||||
cb->bulkMoveArtifacts(left->id, right->id, true);
|
||||
});
|
||||
};
|
||||
}
|
||||
@ -1160,20 +1046,8 @@ void CExchangeController::moveArtifacts(bool leftToRight)
|
||||
}
|
||||
|
||||
GsThread::run([=]
|
||||
{
|
||||
while(vstd::contains_if(source->artifactsWorn, isArtRemovable))
|
||||
{
|
||||
auto art = std::find_if(source->artifactsWorn.begin(), source->artifactsWorn.end(), isArtRemovable);
|
||||
|
||||
moveArtifact(source, target, art->first);
|
||||
}
|
||||
|
||||
while(!source->artifactsInBackpack.empty())
|
||||
{
|
||||
moveArtifact(source, target, source->getArtPos(source->artifactsInBackpack.begin()->artifact));
|
||||
}
|
||||
|
||||
view->redraw();
|
||||
{
|
||||
cb->bulkMoveArtifacts(source->id, target->id, false);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1182,26 +1056,11 @@ void CExchangeController::moveArtifact(
|
||||
const CGHeroInstance * target,
|
||||
ArtifactPosition srcPosition)
|
||||
{
|
||||
auto artifact = source->getArt(srcPosition);
|
||||
auto srcLocation = ArtifactLocation(source, srcPosition);
|
||||
auto dstLocation = ArtifactLocation(target,
|
||||
ArtifactUtils::getArtifactDstPosition(source->getArt(srcPosition), target, target->bearerType()));
|
||||
|
||||
for(auto slot : artifact->artType->possibleSlots.at(target->bearerType()))
|
||||
{
|
||||
auto existingArtifact = target->getArt(slot);
|
||||
auto existingArtInfo = target->getSlot(slot);
|
||||
ArtifactLocation destLocation(target, slot);
|
||||
|
||||
if(!existingArtifact
|
||||
&& (!existingArtInfo || !existingArtInfo->locked)
|
||||
&& artifact->canBePutAt(destLocation))
|
||||
{
|
||||
cb->swapArtifacts(srcLocation, ArtifactLocation(target, slot));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cb->swapArtifacts(srcLocation, ArtifactLocation(target, ArtifactPosition(GameConstants::BACKPACK_START)));
|
||||
cb->swapArtifacts(srcLocation, dstLocation);
|
||||
}
|
||||
|
||||
CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID queryID)
|
||||
@ -1700,9 +1559,7 @@ int CUniversityWindow::CItem::state()
|
||||
{
|
||||
if(parent->hero->getSecSkillLevel(SecondarySkill(ID)))//hero know this skill
|
||||
return 1;
|
||||
if(!parent->hero->canLearnSkill())//can't learn more skills
|
||||
return 0;
|
||||
if(parent->hero->type->heroClass->secSkillProbability[ID]==0)//can't learn this skill (like necromancy for most of non-necros)
|
||||
if(!parent->hero->canLearnSkill(SecondarySkill(ID)))//can't learn more skills
|
||||
return 0;
|
||||
return 2;
|
||||
}
|
||||
|
@ -324,9 +324,6 @@ private:
|
||||
void moveArtifacts(bool leftToRight);
|
||||
void moveArtifact(const CGHeroInstance * source, const CGHeroInstance * target, ArtifactPosition srcPosition);
|
||||
void moveStack(const CGHeroInstance * source, const CGHeroInstance * target, SlotID sourceSlot);
|
||||
void swapArtifacts(ArtifactPosition artPosition);
|
||||
std::vector<HeroArtifact> moveCompositeArtsToBackpack();
|
||||
void swapArtifacts();
|
||||
};
|
||||
|
||||
class CExchangeWindow : public CStatusbarWindow, public CGarrisonHolder, public CWindowWithArtifacts
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -15,7 +15,7 @@
|
||||
"specialBattlefields": {
|
||||
"type": "array",
|
||||
"description": "Obstacles can be placed on specified specified battlefields",
|
||||
"items": { "$ref" : "battlefield.json" }
|
||||
"items": { "type" : "string" }
|
||||
},
|
||||
"width": {
|
||||
"type": "number",
|
||||
|
@ -352,7 +352,7 @@ CArtifact * CArtHandler::loadFromJson(const std::string & scope, const JsonNode
|
||||
}
|
||||
|
||||
const JsonNode & warMachine = node["warMachine"];
|
||||
if(warMachine.getType() == JsonNode::JsonType::DATA_STRING && warMachine.String() != "")
|
||||
if(warMachine.getType() == JsonNode::JsonType::DATA_STRING && !warMachine.String().empty())
|
||||
{
|
||||
VLC->modh->identifiers.requestIdentifier("creature", warMachine, [=](si32 id)
|
||||
{
|
||||
@ -729,7 +729,7 @@ CArtifactInstance::CArtifactInstance( CArtifact *Art)
|
||||
void CArtifactInstance::setType( CArtifact *Art )
|
||||
{
|
||||
artType = Art;
|
||||
attachTo(Art);
|
||||
attachTo(*Art);
|
||||
}
|
||||
|
||||
std::string CArtifactInstance::nodeName() const
|
||||
@ -852,7 +852,7 @@ void CArtifactInstance::putAt(ArtifactLocation al)
|
||||
|
||||
al.getHolderArtSet()->setNewArtSlot(al.slot, this, false);
|
||||
if(al.slot < GameConstants::BACKPACK_START)
|
||||
al.getHolderNode()->attachTo(this);
|
||||
al.getHolderNode()->attachTo(*this);
|
||||
}
|
||||
|
||||
void CArtifactInstance::removeFrom(ArtifactLocation al)
|
||||
@ -860,7 +860,7 @@ void CArtifactInstance::removeFrom(ArtifactLocation al)
|
||||
assert(al.getHolderArtSet()->getArt(al.slot) == this);
|
||||
al.getHolderArtSet()->eraseArtSlot(al.slot);
|
||||
if(al.slot < GameConstants::BACKPACK_START)
|
||||
al.getHolderNode()->detachFrom(this);
|
||||
al.getHolderNode()->detachFrom(*this);
|
||||
|
||||
//TODO delete me?
|
||||
}
|
||||
@ -1054,7 +1054,7 @@ void CCombinedArtifactInstance::addAsConstituent(CArtifactInstance *art, Artifac
|
||||
assert(vstd::contains(*artType->constituents, art->artType.get()));
|
||||
assert(art->getParentNodes().size() == 1 && art->getParentNodes().front() == art->artType);
|
||||
constituentsInfo.push_back(ConstituentInfo(art, slot));
|
||||
attachTo(art);
|
||||
attachTo(*art);
|
||||
}
|
||||
|
||||
void CCombinedArtifactInstance::putAt(ArtifactLocation al)
|
||||
@ -1143,7 +1143,7 @@ CArtifactInstance * CCombinedArtifactInstance::figureMainConstituent(const Artif
|
||||
void CCombinedArtifactInstance::deserializationFix()
|
||||
{
|
||||
for(ConstituentInfo &ci : constituentsInfo)
|
||||
attachTo(ci.art);
|
||||
attachTo(*ci.art);
|
||||
}
|
||||
|
||||
bool CCombinedArtifactInstance::isPart(const CArtifactInstance *supposedPart) const
|
||||
@ -1350,7 +1350,7 @@ void CArtifactSet::artDeserializationFix(CBonusSystemNode *node)
|
||||
{
|
||||
for(auto & elem : artifactsWorn)
|
||||
if(elem.second.artifact && !elem.second.locked)
|
||||
node->attachTo(elem.second.artifact);
|
||||
node->attachTo(*elem.second.artifact);
|
||||
}
|
||||
|
||||
void CArtifactSet::serializeJsonArtifacts(JsonSerializeFormat & handler, const std::string & fieldName, CMap * map)
|
||||
@ -1457,4 +1457,83 @@ void CArtifactSet::serializeJsonSlot(JsonSerializeFormat & handler, const Artifa
|
||||
}
|
||||
}
|
||||
|
||||
CArtifactFittingSet::CArtifactFittingSet(ArtBearer::ArtBearer Bearer)
|
||||
{
|
||||
this->Bearer = Bearer;
|
||||
}
|
||||
|
||||
void CArtifactFittingSet::setNewArtSlot(ArtifactPosition slot, CArtifactInstance * art, bool locked)
|
||||
{
|
||||
ArtSlotInfo & asi = retrieveNewArtSlot(slot);
|
||||
asi.artifact = art;
|
||||
asi.locked = locked;
|
||||
}
|
||||
|
||||
void CArtifactFittingSet::putArtifact(ArtifactPosition pos, CArtifactInstance * art)
|
||||
{
|
||||
if(art && art->canBeDisassembled() && (pos < ArtifactPosition::AFTER_LAST))
|
||||
{
|
||||
for(auto & part : dynamic_cast<CCombinedArtifactInstance*>(art)->constituentsInfo)
|
||||
{
|
||||
// For the ArtFittingSet is no needed to do figureMainConstituent, just lock slots
|
||||
this->setNewArtSlot(part.art->firstAvailableSlot(this), part.art, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->setNewArtSlot(pos, art, false);
|
||||
}
|
||||
}
|
||||
|
||||
ArtBearer::ArtBearer CArtifactFittingSet::bearerType() const
|
||||
{
|
||||
return this->Bearer;
|
||||
}
|
||||
|
||||
DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtifactDstPosition( const CArtifactInstance * artifact,
|
||||
const CArtifactSet * target,
|
||||
ArtBearer::ArtBearer bearer)
|
||||
{
|
||||
for(auto slot : artifact->artType->possibleSlots.at(bearer))
|
||||
{
|
||||
auto existingArtifact = target->getArt(slot);
|
||||
auto existingArtInfo = target->getSlot(slot);
|
||||
|
||||
if(!existingArtifact
|
||||
&& (!existingArtInfo || !existingArtInfo->locked)
|
||||
&& artifact->canBePutAt(target, slot))
|
||||
{
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
return ArtifactPosition(GameConstants::BACKPACK_START);
|
||||
}
|
||||
|
||||
DLL_LINKAGE std::vector<ArtifactPosition> ArtifactUtils::unmovablePositions()
|
||||
{
|
||||
return { ArtifactPosition::SPELLBOOK, ArtifactPosition::MACH4 };
|
||||
}
|
||||
|
||||
DLL_LINKAGE bool ArtifactUtils::isArtRemovable(const std::pair<ArtifactPosition, ArtSlotInfo> & slot)
|
||||
{
|
||||
return slot.second.artifact
|
||||
&& !slot.second.locked
|
||||
&& !vstd::contains(unmovablePositions(), slot.first);
|
||||
}
|
||||
|
||||
DLL_LINKAGE bool ArtifactUtils::checkSpellbookIsNeeded(const CGHeroInstance * heroPtr, ArtifactID artID, ArtifactPosition slot)
|
||||
{
|
||||
// TODO what'll happen if Titan's thunder is equipped by pickin git up or the start of game?
|
||||
// Titan's Thunder creates new spellbook on equip
|
||||
if(artID == ArtifactID::TITANS_THUNDER && slot == ArtifactPosition::RIGHT_HAND)
|
||||
{
|
||||
if(heroPtr)
|
||||
{
|
||||
if(heroPtr && !heroPtr->hasSpellbook())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -303,8 +303,9 @@ struct DLL_LINKAGE ArtSlotInfo
|
||||
ui8 locked; //if locked, then artifact points to the combined artifact
|
||||
|
||||
ArtSlotInfo() : locked(false) {}
|
||||
const CArtifactInstance * getArt() const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & artifact;
|
||||
h & locked;
|
||||
@ -363,4 +364,28 @@ private:
|
||||
void serializeJsonSlot(JsonSerializeFormat & handler, const ArtifactPosition & slot, CMap * map);//normal slots
|
||||
};
|
||||
|
||||
// Used to try on artifacts before the claimed changes have been applied
|
||||
class DLL_LINKAGE CArtifactFittingSet : public CArtifactSet
|
||||
{
|
||||
public:
|
||||
CArtifactFittingSet(ArtBearer::ArtBearer Bearer);
|
||||
void setNewArtSlot(ArtifactPosition slot, CArtifactInstance * art, bool locked);
|
||||
void putArtifact(ArtifactPosition pos, CArtifactInstance * art) override;
|
||||
ArtBearer::ArtBearer bearerType() const override;
|
||||
|
||||
protected:
|
||||
ArtBearer::ArtBearer Bearer;
|
||||
};
|
||||
|
||||
namespace ArtifactUtils
|
||||
{
|
||||
// Calculates where an artifact gets placed when it gets transferred from one hero to another.
|
||||
DLL_LINKAGE ArtifactPosition getArtifactDstPosition( const CArtifactInstance * artifact,
|
||||
const CArtifactSet * target,
|
||||
ArtBearer::ArtBearer bearer);
|
||||
DLL_LINKAGE std::vector<ArtifactPosition> unmovablePositions(); // TODO: Make this constexpr when the toolset is upgraded
|
||||
DLL_LINKAGE bool isArtRemovable(const std::pair<ArtifactPosition, ArtSlotInfo> & slot);
|
||||
DLL_LINKAGE bool checkSpellbookIsNeeded(const CGHeroInstance * heroPtr, ArtifactID artID, ArtifactPosition slot);
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -94,7 +94,9 @@ std::string MacroString::build(const GetValue & getValue) const
|
||||
CBonusType::CBonusType()
|
||||
{
|
||||
hidden = true;
|
||||
icon = nameTemplate = descriptionTemplate = "";
|
||||
icon.clear();
|
||||
nameTemplate.clear();
|
||||
descriptionTemplate.clear();
|
||||
}
|
||||
|
||||
CBonusType::~CBonusType()
|
||||
|
@ -1345,12 +1345,12 @@ void CCreatureHandler::buildBonusTreeForTiers()
|
||||
for(CCreature * c : objects)
|
||||
{
|
||||
if(vstd::isbetween(c->level, 0, ARRAY_COUNT(creaturesOfLevel)))
|
||||
c->attachTo(&creaturesOfLevel[c->level]);
|
||||
c->attachTo(creaturesOfLevel[c->level]);
|
||||
else
|
||||
c->attachTo(&creaturesOfLevel[0]);
|
||||
c->attachTo(creaturesOfLevel[0]);
|
||||
}
|
||||
for(CBonusSystemNode &b : creaturesOfLevel)
|
||||
b.attachTo(&allCreatures);
|
||||
b.attachTo(allCreatures);
|
||||
}
|
||||
|
||||
void CCreatureHandler::afterLoadFinalization()
|
||||
|
@ -773,7 +773,7 @@ void CStackInstance::setType(const CCreature *c)
|
||||
{
|
||||
if(type)
|
||||
{
|
||||
detachFrom(const_cast<CCreature*>(type));
|
||||
detachFrom(const_cast<CCreature&>(*type));
|
||||
if (type->isMyUpgrade(c) && VLC->modh->modules.STACK_EXP)
|
||||
experience = static_cast<TExpType>(experience * VLC->creh->expAfterUpgrade / 100.0);
|
||||
}
|
||||
@ -781,7 +781,7 @@ void CStackInstance::setType(const CCreature *c)
|
||||
CStackBasicDescriptor::setType(c);
|
||||
|
||||
if(type)
|
||||
attachTo(const_cast<CCreature*>(type));
|
||||
attachTo(const_cast<CCreature&>(*type));
|
||||
}
|
||||
std::string CStackInstance::bonusToString(const std::shared_ptr<Bonus>& bonus, bool description) const
|
||||
{
|
||||
@ -804,12 +804,12 @@ std::string CStackInstance::bonusToGraphics(const std::shared_ptr<Bonus>& bonus)
|
||||
void CStackInstance::setArmyObj(const CArmedInstance * ArmyObj)
|
||||
{
|
||||
if(_armyObj)
|
||||
detachFrom(const_cast<CArmedInstance*>(_armyObj));
|
||||
detachFrom(const_cast<CArmedInstance&>(*_armyObj));
|
||||
|
||||
_armyObj = ArmyObj;
|
||||
|
||||
if(ArmyObj)
|
||||
attachTo(const_cast<CArmedInstance*>(_armyObj));
|
||||
attachTo(const_cast<CArmedInstance&>(*_armyObj));
|
||||
}
|
||||
|
||||
std::string CStackInstance::getQuantityTXT(bool capitalized) const
|
||||
@ -1052,7 +1052,7 @@ void CStackBasicDescriptor::serializeJson(JsonSerializeFormat & handler)
|
||||
{
|
||||
std::string typeName("");
|
||||
handler.serializeString("type", typeName);
|
||||
if(typeName != "")
|
||||
if(!typeName.empty())
|
||||
setType(VLC->creh->getCreature("core", typeName));
|
||||
}
|
||||
}
|
||||
|
@ -532,7 +532,7 @@ std::pair<Obj,int> CGameState::pickObject (CGObjectInstance *obj)
|
||||
if (auto info = dynamic_cast<CCreGenAsCastleInfo*>(dwl->info))
|
||||
{
|
||||
faction = getRandomGenerator().nextInt((int)VLC->townh->size() - 1);
|
||||
if(info->asCastle && info->instanceId != "")
|
||||
if(info->asCastle && !info->instanceId.empty())
|
||||
{
|
||||
auto iter = map->instanceNames.find(info->instanceId);
|
||||
|
||||
@ -2724,13 +2724,13 @@ void CGameState::buildGlobalTeamPlayerTree()
|
||||
for(auto k=teams.begin(); k!=teams.end(); ++k)
|
||||
{
|
||||
TeamState *t = &k->second;
|
||||
t->attachTo(&globalEffects);
|
||||
t->attachTo(globalEffects);
|
||||
|
||||
for(PlayerColor teamMember : k->second.players)
|
||||
{
|
||||
PlayerState *p = getPlayerState(teamMember);
|
||||
assert(p);
|
||||
p->attachTo(t);
|
||||
p->attachTo(*t);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2740,7 +2740,9 @@ void CGameState::attachArmedObjects()
|
||||
for(CGObjectInstance *obj : map->objects)
|
||||
{
|
||||
if(CArmedInstance *armed = dynamic_cast<CArmedInstance*>(obj))
|
||||
armed->whatShouldBeAttached()->attachTo(armed->whereShouldBeAttached(this));
|
||||
{
|
||||
armed->whatShouldBeAttached().attachTo(armed->whereShouldBeAttached(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,7 +226,7 @@ std::vector<CIdentifierStorage::ObjectData> CIdentifierStorage::getPossibleIdent
|
||||
|
||||
//for map format support core mod has access to any mod
|
||||
//TODO: better solution for access from map?
|
||||
if(request.localScope == "core" || request.localScope == "")
|
||||
if(request.localScope == "core" || request.localScope.empty())
|
||||
{
|
||||
allowedScopes.insert(request.remoteScope);
|
||||
}
|
||||
@ -1116,13 +1116,13 @@ void CModHandler::parseIdentifier(const std::string & fullIdentifier, std::strin
|
||||
else
|
||||
{
|
||||
type = p.second;
|
||||
identifier = "";
|
||||
identifier.clear();
|
||||
}
|
||||
}
|
||||
|
||||
std::string CModHandler::makeFullIdentifier(const std::string & scope, const std::string & type, const std::string & identifier)
|
||||
{
|
||||
if(type == "")
|
||||
if(type.empty())
|
||||
logGlobal->error("Full identifier (%s %s) requires type name", scope, identifier);
|
||||
|
||||
std::string actualScope = scope;
|
||||
@ -1137,13 +1137,13 @@ std::string CModHandler::makeFullIdentifier(const std::string & scope, const std
|
||||
actualName = scopeAndName.second;
|
||||
}
|
||||
|
||||
if(actualScope == "")
|
||||
if(actualScope.empty())
|
||||
{
|
||||
return actualName == "" ? type : type + "." + actualName;
|
||||
return actualName.empty() ? type : type + "." + actualName;
|
||||
}
|
||||
else
|
||||
{
|
||||
return actualName == "" ? actualScope+ ":" + type : actualScope + ":" + type + "." + actualName;
|
||||
return actualName.empty() ? actualScope+ ":" + type : actualScope + ":" + type + "." + actualName;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -339,7 +339,7 @@ void CPathfinder::calculatePaths()
|
||||
auto hlp = config->getOrCreatePathfinderHelper(source, gs);
|
||||
|
||||
if(hlp->isHeroPatrolLocked())
|
||||
break;
|
||||
continue;
|
||||
|
||||
pq.push(initialNode);
|
||||
}
|
||||
@ -1252,7 +1252,7 @@ int CPathfinderHelper::getMovementCost(
|
||||
if(src.x != dst.x && src.y != dst.y) //it's diagonal move
|
||||
{
|
||||
int old = ret;
|
||||
ret = static_cast < int>(ret * 1.414213);
|
||||
ret = static_cast<int>(ret * M_SQRT2);
|
||||
//diagonal move costs too much but normal move is possible - allow diagonal move for remaining move points
|
||||
if(ret > remainingMovePoints && remainingMovePoints >= old)
|
||||
{
|
||||
|
@ -82,13 +82,14 @@ void CStack::localInit(BattleInfo * battleInfo)
|
||||
exportBonuses();
|
||||
if(base) //stack originating from "real" stack in garrison -> attach to it
|
||||
{
|
||||
attachTo(const_cast<CStackInstance *>(base));
|
||||
attachTo(const_cast<CStackInstance&>(*base));
|
||||
}
|
||||
else //attach directly to obj to which stack belongs and creature type
|
||||
{
|
||||
CArmedInstance * army = battle->battleGetArmyObject(side);
|
||||
attachTo(army);
|
||||
attachTo(const_cast<CCreature *>(type));
|
||||
assert(army);
|
||||
attachTo(*army);
|
||||
attachTo(const_cast<CCreature&>(*type));
|
||||
}
|
||||
nativeTerrain = type->getNativeTerrain(); //save nativeTerrain in the variable on the battle start to avoid dead lock
|
||||
CUnitState::localInit(this); //it causes execution of the CStack::isOnNativeTerrain where nativeTerrain will be considered
|
||||
|
@ -822,11 +822,11 @@ void CTownHandler::loadClientData(CTown &town, const JsonNode & source)
|
||||
info.buildingsIcons = source["buildingsIcons"].String();
|
||||
|
||||
//left for back compatibility - will be removed later
|
||||
if (source["guildBackground"].String() != "")
|
||||
if(!source["guildBackground"].String().empty())
|
||||
info.guildBackground = source["guildBackground"].String();
|
||||
else
|
||||
info.guildBackground = "TPMAGE.bmp";
|
||||
if (source["tavernVideo"].String() != "")
|
||||
if(!source["tavernVideo"].String().empty())
|
||||
info.tavernVideo = source["tavernVideo"].String();
|
||||
else
|
||||
info.tavernVideo = "TAVERN.BIK";
|
||||
@ -963,7 +963,6 @@ TerrainId CTownHandler::getDefaultTerrainForAlignment(EAlignment::EAlignment ali
|
||||
CFaction * CTownHandler::loadFromJson(const std::string & scope, const JsonNode & source, const std::string & identifier, size_t index)
|
||||
{
|
||||
auto faction = new CFaction();
|
||||
faction->index = index;
|
||||
|
||||
faction->index = static_cast<TFaction>(index);
|
||||
faction->name = source["name"].String();
|
||||
|
@ -1016,7 +1016,7 @@ TConstBonusListPtr CBonusSystemNode::getAllBonuses(const CSelector &selector, co
|
||||
|
||||
// If a bonus system request comes with a caching string then look up in the map if there are any
|
||||
// pre-calculated bonus results. Limiters can't be cached so they have to be calculated.
|
||||
if (cachingStr != "")
|
||||
if(!cachingStr.empty())
|
||||
{
|
||||
auto it = cachedRequests.find(cachingStr);
|
||||
if(it != cachedRequests.end())
|
||||
@ -1032,7 +1032,7 @@ TConstBonusListPtr CBonusSystemNode::getAllBonuses(const CSelector &selector, co
|
||||
cachedBonuses.getBonuses(*ret, selector, limit);
|
||||
|
||||
// Save the results in the cache
|
||||
if(cachingStr != "")
|
||||
if(!cachingStr.empty())
|
||||
cachedRequests[cachingStr] = ret;
|
||||
|
||||
return ret;
|
||||
@ -1150,53 +1150,53 @@ CBonusSystemNode::~CBonusSystemNode()
|
||||
if(children.size())
|
||||
{
|
||||
while(children.size())
|
||||
children.front()->detachFrom(this);
|
||||
children.front()->detachFrom(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void CBonusSystemNode::attachTo(CBonusSystemNode *parent)
|
||||
void CBonusSystemNode::attachTo(CBonusSystemNode & parent)
|
||||
{
|
||||
assert(!vstd::contains(parents, parent));
|
||||
parents.push_back(parent);
|
||||
assert(!vstd::contains(parents, &parent));
|
||||
parents.push_back(&parent);
|
||||
|
||||
if(!isHypothetic())
|
||||
{
|
||||
if(parent->actsAsBonusSourceOnly())
|
||||
parent->newRedDescendant(this);
|
||||
if(parent.actsAsBonusSourceOnly())
|
||||
parent.newRedDescendant(*this);
|
||||
else
|
||||
newRedDescendant(parent);
|
||||
|
||||
parent->newChildAttached(this);
|
||||
parent.newChildAttached(*this);
|
||||
}
|
||||
|
||||
CBonusSystemNode::treeHasChanged();
|
||||
}
|
||||
|
||||
void CBonusSystemNode::detachFrom(CBonusSystemNode *parent)
|
||||
void CBonusSystemNode::detachFrom(CBonusSystemNode & parent)
|
||||
{
|
||||
assert(vstd::contains(parents, parent));
|
||||
assert(vstd::contains(parents, &parent));
|
||||
|
||||
if(!isHypothetic())
|
||||
{
|
||||
if(parent->actsAsBonusSourceOnly())
|
||||
parent->removedRedDescendant(this);
|
||||
if(parent.actsAsBonusSourceOnly())
|
||||
parent.removedRedDescendant(*this);
|
||||
else
|
||||
removedRedDescendant(parent);
|
||||
}
|
||||
|
||||
if (vstd::contains(parents, parent))
|
||||
if (vstd::contains(parents, &parent))
|
||||
{
|
||||
parents -= parent;
|
||||
parents -= &parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
logBonus->error("Error on Detach. Node %s (nodeType=%d) has not parent %s (nodeType=%d)"
|
||||
, nodeShortInfo(), nodeType, parent->nodeShortInfo(), parent->nodeType);
|
||||
, nodeShortInfo(), nodeType, parent.nodeShortInfo(), parent.nodeType);
|
||||
}
|
||||
|
||||
if(!isHypothetic())
|
||||
{
|
||||
parent->childDetached(this);
|
||||
parent.childDetached(*this);
|
||||
}
|
||||
CBonusSystemNode::treeHasChanged();
|
||||
}
|
||||
@ -1304,27 +1304,27 @@ void CBonusSystemNode::unpropagateBonus(std::shared_ptr<Bonus> b)
|
||||
child->unpropagateBonus(b);
|
||||
}
|
||||
|
||||
void CBonusSystemNode::newChildAttached(CBonusSystemNode *child)
|
||||
void CBonusSystemNode::newChildAttached(CBonusSystemNode & child)
|
||||
{
|
||||
assert(!vstd::contains(children, child));
|
||||
children.push_back(child);
|
||||
assert(!vstd::contains(children, &child));
|
||||
children.push_back(&child);
|
||||
}
|
||||
|
||||
void CBonusSystemNode::childDetached(CBonusSystemNode *child)
|
||||
void CBonusSystemNode::childDetached(CBonusSystemNode & child)
|
||||
{
|
||||
if(vstd::contains(children, child))
|
||||
children -= child;
|
||||
if(vstd::contains(children, &child))
|
||||
children -= &child;
|
||||
else
|
||||
{
|
||||
logBonus->error("Error on Detach. Node %s (nodeType=%d) is not a child of %s (nodeType=%d)"
|
||||
, child->nodeShortInfo(), child->nodeType, nodeShortInfo(), nodeType);
|
||||
, child.nodeShortInfo(), child.nodeType, nodeShortInfo(), nodeType);
|
||||
}
|
||||
}
|
||||
|
||||
void CBonusSystemNode::detachFromAll()
|
||||
{
|
||||
while(parents.size())
|
||||
detachFrom(parents.front());
|
||||
detachFrom(*parents.front());
|
||||
}
|
||||
|
||||
bool CBonusSystemNode::isIndependentNode() const
|
||||
@ -1393,12 +1393,12 @@ void CBonusSystemNode::getRedChildren(TNodes &out)
|
||||
}
|
||||
}
|
||||
|
||||
void CBonusSystemNode::newRedDescendant(CBonusSystemNode * descendant)
|
||||
void CBonusSystemNode::newRedDescendant(CBonusSystemNode & descendant)
|
||||
{
|
||||
for(auto b : exportedBonuses)
|
||||
{
|
||||
if(b->propagator)
|
||||
descendant->propagateBonus(b, *this);
|
||||
descendant.propagateBonus(b, *this);
|
||||
}
|
||||
TNodes redParents;
|
||||
getRedAncestors(redParents); //get all red parents recursively
|
||||
@ -1408,16 +1408,16 @@ void CBonusSystemNode::newRedDescendant(CBonusSystemNode * descendant)
|
||||
for(auto b : parent->exportedBonuses)
|
||||
{
|
||||
if(b->propagator)
|
||||
descendant->propagateBonus(b, *this);
|
||||
descendant.propagateBonus(b, *this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBonusSystemNode::removedRedDescendant(CBonusSystemNode *descendant)
|
||||
void CBonusSystemNode::removedRedDescendant(CBonusSystemNode & descendant)
|
||||
{
|
||||
for(auto b : exportedBonuses)
|
||||
if(b->propagator)
|
||||
descendant->unpropagateBonus(b);
|
||||
descendant.unpropagateBonus(b);
|
||||
|
||||
TNodes redParents;
|
||||
getRedAncestors(redParents); //get all red parents recursively
|
||||
@ -1426,7 +1426,7 @@ void CBonusSystemNode::removedRedDescendant(CBonusSystemNode *descendant)
|
||||
{
|
||||
for(auto b : parent->exportedBonuses)
|
||||
if(b->propagator)
|
||||
descendant->unpropagateBonus(b);
|
||||
descendant.unpropagateBonus(b);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1708,9 +1708,9 @@ JsonNode Bonus::toJsonNode() const
|
||||
root["val"].Integer() = val;
|
||||
if(valType != ADDITIVE_VALUE)
|
||||
root["valueType"].String() = vstd::findKey(bonusValueMap, valType);
|
||||
if(stacking != "")
|
||||
if(!stacking.empty())
|
||||
root["stacking"].String() = stacking;
|
||||
if(description != "")
|
||||
if(!description.empty())
|
||||
root["description"].String() = description;
|
||||
if(effectRange != NO_LIMIT)
|
||||
root["effectRange"].String() = vstd::findKey(bonusLimitEffect, effectRange);
|
||||
|
@ -791,21 +791,21 @@ public:
|
||||
static PlayerColor retrieveNodeOwner(const CBonusSystemNode * node);
|
||||
std::shared_ptr<Bonus> getBonusLocalFirst(const CSelector & selector);
|
||||
|
||||
void attachTo(CBonusSystemNode *parent);
|
||||
void detachFrom(CBonusSystemNode *parent);
|
||||
void attachTo(CBonusSystemNode & parent);
|
||||
void detachFrom(CBonusSystemNode & parent);
|
||||
void detachFromAll();
|
||||
virtual void addNewBonus(const std::shared_ptr<Bonus>& b);
|
||||
void accumulateBonus(const std::shared_ptr<Bonus>& b); //add value of bonus with same type/subtype or create new
|
||||
|
||||
void newChildAttached(CBonusSystemNode *child);
|
||||
void childDetached(CBonusSystemNode *child);
|
||||
void newChildAttached(CBonusSystemNode & child);
|
||||
void childDetached(CBonusSystemNode & child);
|
||||
void propagateBonus(std::shared_ptr<Bonus> b, const CBonusSystemNode & source);
|
||||
void unpropagateBonus(std::shared_ptr<Bonus> b);
|
||||
void removeBonus(const std::shared_ptr<Bonus>& b);
|
||||
void removeBonuses(const CSelector & selector);
|
||||
void removeBonusesRecursive(const CSelector & s);
|
||||
void newRedDescendant(CBonusSystemNode *descendant); //propagation needed
|
||||
void removedRedDescendant(CBonusSystemNode *descendant); //de-propagation needed
|
||||
void newRedDescendant(CBonusSystemNode & descendant); //propagation needed
|
||||
void removedRedDescendant(CBonusSystemNode & descendant); //de-propagation needed
|
||||
|
||||
bool isIndependentNode() const; //node is independent when it has no parents nor children
|
||||
bool actsAsBonusSourceOnly() const;
|
||||
|
@ -91,6 +91,7 @@ public:
|
||||
virtual void artifactAssembled(const ArtifactLocation &al){};
|
||||
virtual void artifactDisassembled(const ArtifactLocation &al){};
|
||||
virtual void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst){};
|
||||
virtual void artifactPossibleAssembling(const ArtifactLocation & dst) {};
|
||||
|
||||
virtual void heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visitedObj, bool start){};
|
||||
virtual void heroCreated(const CGHeroInstance*){};
|
||||
|
@ -994,18 +994,64 @@ struct EraseArtifact : CArtifactOperationPack
|
||||
|
||||
struct MoveArtifact : CArtifactOperationPack
|
||||
{
|
||||
MoveArtifact() {}
|
||||
MoveArtifact(ArtifactLocation * src, ArtifactLocation * dst)
|
||||
: src(*src), dst(*dst) {}
|
||||
ArtifactLocation src, dst;
|
||||
|
||||
void applyCl(CClient *cl);
|
||||
DLL_LINKAGE void applyGs(CGameState *gs);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & src;
|
||||
h & dst;
|
||||
}
|
||||
};
|
||||
|
||||
struct BulkMoveArtifacts : CArtifactOperationPack
|
||||
{
|
||||
struct LinkedSlots
|
||||
{
|
||||
ArtifactPosition srcPos;
|
||||
ArtifactPosition dstPos;
|
||||
|
||||
LinkedSlots() {}
|
||||
LinkedSlots(ArtifactPosition srcPos, ArtifactPosition dstPos)
|
||||
: srcPos(srcPos), dstPos(dstPos) {}
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & srcPos;
|
||||
h & dstPos;
|
||||
}
|
||||
};
|
||||
|
||||
TArtHolder srcArtHolder;
|
||||
TArtHolder dstArtHolder;
|
||||
|
||||
BulkMoveArtifacts()
|
||||
: swap(false) {}
|
||||
BulkMoveArtifacts(TArtHolder srcArtHolder, TArtHolder dstArtHolder, bool swap)
|
||||
: srcArtHolder(srcArtHolder), dstArtHolder(dstArtHolder), swap(swap) {}
|
||||
|
||||
void applyCl(CClient * cl);
|
||||
DLL_LINKAGE void applyGs(CGameState * gs);
|
||||
|
||||
std::vector<LinkedSlots> artsPack0;
|
||||
std::vector<LinkedSlots> artsPack1;
|
||||
bool swap;
|
||||
CArtifactSet * getSrcHolderArtSet();
|
||||
CArtifactSet * getDstHolderArtSet();
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & artsPack0;
|
||||
h & artsPack1;
|
||||
h & srcArtHolder;
|
||||
h & dstArtHolder;
|
||||
h & swap;
|
||||
}
|
||||
};
|
||||
|
||||
struct AssembledArtifact : CArtifactOperationPack
|
||||
{
|
||||
ArtifactLocation al; //where assembly will be put
|
||||
@ -2197,6 +2243,27 @@ struct ExchangeArtifacts : public CPackForServer
|
||||
}
|
||||
};
|
||||
|
||||
struct BulkExchangeArtifacts : public CPackForServer
|
||||
{
|
||||
ObjectInstanceID srcHero;
|
||||
ObjectInstanceID dstHero;
|
||||
bool swap;
|
||||
|
||||
BulkExchangeArtifacts()
|
||||
: swap(false) {}
|
||||
BulkExchangeArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap)
|
||||
: srcHero(srcHero), dstHero(dstHero), swap(swap) {}
|
||||
|
||||
bool applyGh(CGameHandler * gh);
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & static_cast<CPackForServer&>(*this);
|
||||
h & srcHero;
|
||||
h & dstHero;
|
||||
h & swap;
|
||||
}
|
||||
};
|
||||
|
||||
struct AssembleArtifacts : public CPackForServer
|
||||
{
|
||||
AssembleArtifacts():assemble(false){};
|
||||
|
@ -414,7 +414,7 @@ DLL_LINKAGE void RemoveObject::applyGs(CGameState *gs)
|
||||
PlayerState * p = gs->getPlayerState(beatenHero->tempOwner);
|
||||
gs->map->heroesOnMap -= beatenHero;
|
||||
p->heroes -= beatenHero;
|
||||
beatenHero->detachFrom(beatenHero->whereShouldBeAttachedOnSiege(gs));
|
||||
beatenHero->detachFrom(*beatenHero->whereShouldBeAttachedOnSiege(gs));
|
||||
beatenHero->tempOwner = PlayerColor::NEUTRAL; //no one owns beaten hero
|
||||
vstd::erase_if(beatenHero->artifactsInBackpack, [](const ArtSlotInfo& asi)
|
||||
{
|
||||
@ -683,7 +683,7 @@ DLL_LINKAGE void HeroRecruited::applyGs(CGameState *gs)
|
||||
|
||||
gs->map->heroesOnMap.push_back(h);
|
||||
p->heroes.push_back(h);
|
||||
h->attachTo(p);
|
||||
h->attachTo(*p);
|
||||
if(fresh)
|
||||
{
|
||||
h->initObj(gs->getRandomGenerator());
|
||||
@ -701,8 +701,8 @@ DLL_LINKAGE void GiveHero::applyGs(CGameState *gs)
|
||||
CGHeroInstance *h = gs->getHero(id);
|
||||
|
||||
//bonus system
|
||||
h->detachFrom(&gs->globalEffects);
|
||||
h->attachTo(gs->getPlayerState(player));
|
||||
h->detachFrom(gs->globalEffects);
|
||||
h->attachTo(*gs->getPlayerState(player));
|
||||
h->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, h->type->heroClass->getIndex())->getTemplates().front();
|
||||
|
||||
gs->map->removeBlockVisTiles(h,true);
|
||||
@ -845,18 +845,11 @@ DLL_LINKAGE CBonusSystemNode *ArtifactLocation::getHolderNode()
|
||||
|
||||
DLL_LINKAGE const CArtifactInstance *ArtifactLocation::getArt() const
|
||||
{
|
||||
const ArtSlotInfo *s = getSlot();
|
||||
if(s && s->artifact)
|
||||
{
|
||||
if(!s->locked)
|
||||
return s->artifact;
|
||||
else
|
||||
{
|
||||
logNetwork->warn("ArtifactLocation::getArt: This location is locked!");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
auto s = getSlot();
|
||||
if(s)
|
||||
return s->getArt();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DLL_LINKAGE const CArtifactSet * ArtifactLocation::getHolderArtSet() const
|
||||
@ -1093,24 +1086,82 @@ DLL_LINKAGE void EraseArtifact::applyGs(CGameState *gs)
|
||||
al.removeArtifact();
|
||||
}
|
||||
|
||||
DLL_LINKAGE void MoveArtifact::applyGs(CGameState *gs)
|
||||
DLL_LINKAGE void MoveArtifact::applyGs(CGameState * gs)
|
||||
{
|
||||
CArtifactInstance *a = src.getArt();
|
||||
CArtifactInstance * art = src.getArt();
|
||||
if(dst.slot < GameConstants::BACKPACK_START)
|
||||
assert(!dst.getArt());
|
||||
|
||||
a->move(src, dst);
|
||||
art->move(src, dst);
|
||||
}
|
||||
|
||||
//TODO what'll happen if Titan's thunder is equipped by pickin git up or the start of game?
|
||||
if (a->artType->id == ArtifactID::TITANS_THUNDER && dst.slot == ArtifactPosition::RIGHT_HAND) //Titan's Thunder creates new spellbook on equip
|
||||
DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs)
|
||||
{
|
||||
enum class EBulkArtsOp
|
||||
{
|
||||
auto hPtr = boost::get<ConstTransitivePtr<CGHeroInstance> >(&dst.artHolder);
|
||||
if(hPtr)
|
||||
BULK_MOVE,
|
||||
BULK_REMOVE,
|
||||
BULK_PUT
|
||||
};
|
||||
|
||||
auto bulkArtsOperation = [this](std::vector<LinkedSlots> & artsPack,
|
||||
CArtifactSet * artSet, EBulkArtsOp operation) -> void
|
||||
{
|
||||
int numBackpackArtifactsMoved = 0;
|
||||
for(auto & slot : artsPack)
|
||||
{
|
||||
CGHeroInstance *h = *hPtr;
|
||||
if(h && !h->hasSpellbook())
|
||||
gs->giveHeroArtifact(h, ArtifactID::SPELLBOOK);
|
||||
// When an object gets removed from the backpack, the backpack shrinks
|
||||
// so all the following indices will be affected. Thus, we need to update
|
||||
// the subsequent artifact slots to account for that
|
||||
auto srcPos = slot.srcPos;
|
||||
if((srcPos >= GameConstants::BACKPACK_START) && (operation != EBulkArtsOp::BULK_PUT))
|
||||
{
|
||||
srcPos = ArtifactPosition(srcPos.num - numBackpackArtifactsMoved);
|
||||
}
|
||||
auto slotInfo = artSet->getSlot(srcPos);
|
||||
assert(slotInfo);
|
||||
auto art = const_cast<CArtifactInstance*>(slotInfo->getArt());
|
||||
assert(art);
|
||||
switch(operation)
|
||||
{
|
||||
case EBulkArtsOp::BULK_MOVE:
|
||||
const_cast<CArtifactInstance*>(art)->move(
|
||||
ArtifactLocation(srcArtHolder, srcPos), ArtifactLocation(dstArtHolder, slot.dstPos));
|
||||
break;
|
||||
case EBulkArtsOp::BULK_REMOVE:
|
||||
art->removeFrom(ArtifactLocation(dstArtHolder, srcPos));
|
||||
break;
|
||||
case EBulkArtsOp::BULK_PUT:
|
||||
art->putAt(ArtifactLocation(srcArtHolder, slot.dstPos));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(srcPos >= GameConstants::BACKPACK_START)
|
||||
{
|
||||
numBackpackArtifactsMoved++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if(swap)
|
||||
{
|
||||
// Swap
|
||||
auto leftSet = getSrcHolderArtSet();
|
||||
auto rightSet = getDstHolderArtSet();
|
||||
CArtifactFittingSet artFittingSet(leftSet->bearerType());
|
||||
|
||||
artFittingSet.artifactsWorn = rightSet->artifactsWorn;
|
||||
artFittingSet.artifactsInBackpack = rightSet->artifactsInBackpack;
|
||||
|
||||
bulkArtsOperation(artsPack1, rightSet, EBulkArtsOp::BULK_REMOVE);
|
||||
bulkArtsOperation(artsPack0, leftSet, EBulkArtsOp::BULK_MOVE);
|
||||
bulkArtsOperation(artsPack1, &artFittingSet, EBulkArtsOp::BULK_PUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
bulkArtsOperation(artsPack0, getSrcHolderArtSet(), EBulkArtsOp::BULK_MOVE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1153,7 +1204,7 @@ DLL_LINKAGE void DisassembledArtifact::applyGs(CGameState *gs)
|
||||
{
|
||||
ArtifactLocation constituentLoc = al;
|
||||
constituentLoc.slot = (ci.slot >= 0 ? ci.slot : al.slot); //-1 is slot of main constituent -> it'll replace combined artifact in its pos
|
||||
disassembled->detachFrom(ci.art);
|
||||
disassembled->detachFrom(*ci.art);
|
||||
ci.art->putAt(constituentLoc);
|
||||
}
|
||||
|
||||
@ -1281,10 +1332,10 @@ DLL_LINKAGE void SetObjectProperty::applyGs(CGameState *gs)
|
||||
}
|
||||
}
|
||||
|
||||
CBonusSystemNode *nodeToMove = cai->whatShouldBeAttached();
|
||||
nodeToMove->detachFrom(cai->whereShouldBeAttached(gs));
|
||||
CBonusSystemNode & nodeToMove = cai->whatShouldBeAttached();
|
||||
nodeToMove.detachFrom(cai->whereShouldBeAttached(gs));
|
||||
obj->setProperty(what,val);
|
||||
nodeToMove->attachTo(cai->whereShouldBeAttached(gs));
|
||||
nodeToMove.attachTo(cai->whereShouldBeAttached(gs));
|
||||
}
|
||||
else //not an armed instance
|
||||
{
|
||||
@ -1712,4 +1763,24 @@ DLL_LINKAGE void EntitiesChanged::applyGs(CGameState * gs)
|
||||
gs->updateEntity(change.metatype, change.entityIndex, change.data);
|
||||
}
|
||||
|
||||
const CArtifactInstance * ArtSlotInfo::getArt() const
|
||||
{
|
||||
if(locked)
|
||||
{
|
||||
logNetwork->warn("ArtifactLocation::getArt: This location is locked!");
|
||||
return nullptr;
|
||||
}
|
||||
return artifact;
|
||||
}
|
||||
|
||||
CArtifactSet * BulkMoveArtifacts::getSrcHolderArtSet()
|
||||
{
|
||||
return boost::apply_visitor(GetBase<CArtifactSet>(), srcArtHolder);
|
||||
}
|
||||
|
||||
CArtifactSet * BulkMoveArtifacts::getDstHolderArtSet()
|
||||
{
|
||||
return boost::apply_visitor(GetBase<CArtifactSet>(), dstArtHolder);
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -85,7 +85,7 @@ ObstacleInfo * ObstacleHandler::loadFromJson(const std::string & scope, const Js
|
||||
info->animation = json["animation"].String();
|
||||
info->width = json["width"].Integer();
|
||||
info->height = json["height"].Integer();
|
||||
for(auto & t : json["allowedTerrain"].Vector())
|
||||
for(auto & t : json["allowedTerrains"].Vector())
|
||||
info->allowedTerrains.emplace_back(VLC->terrainTypeHandler->getInfoByName(t.String())->id);
|
||||
for(auto & t : json["specialBattlefields"].Vector())
|
||||
info->allowedSpecialBfields.emplace_back(t.String());
|
||||
|
@ -84,7 +84,7 @@ void BattleInfo::localInit()
|
||||
{
|
||||
auto armyObj = battleGetArmyObject(i);
|
||||
armyObj->battle = this;
|
||||
armyObj->attachTo(this);
|
||||
armyObj->attachTo(*this);
|
||||
}
|
||||
|
||||
for(CStack * s : stacks)
|
||||
|
@ -55,7 +55,7 @@ static void retrieveTurretDamageRange(const CGTownInstance * town, const battle:
|
||||
const int baseDamage = 15;
|
||||
|
||||
outMinDmg = multiplier * (baseDamage + town->getTownLevel() * 3);
|
||||
outMaxDmg = multiplier * (baseDamage + town->getTownLevel() * 3);
|
||||
outMaxDmg = outMinDmg;
|
||||
}
|
||||
|
||||
static BattleHex lineToWallHex(int line) //returns hex with wall in given line (y coordinate)
|
||||
|
@ -142,17 +142,18 @@ void CArmedInstance::armyChanged()
|
||||
updateMoraleBonusFromArmy();
|
||||
}
|
||||
|
||||
CBonusSystemNode * CArmedInstance::whereShouldBeAttached(CGameState *gs)
|
||||
CBonusSystemNode & CArmedInstance::whereShouldBeAttached(CGameState * gs)
|
||||
{
|
||||
if(tempOwner < PlayerColor::PLAYER_LIMIT)
|
||||
return gs->getPlayerState(tempOwner);
|
||||
else
|
||||
return &gs->globalEffects;
|
||||
if(auto * where = gs->getPlayerState(tempOwner))
|
||||
return *where;
|
||||
|
||||
return gs->globalEffects;
|
||||
}
|
||||
|
||||
CBonusSystemNode * CArmedInstance::whatShouldBeAttached()
|
||||
CBonusSystemNode & CArmedInstance::whatShouldBeAttached()
|
||||
{
|
||||
return this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -33,8 +33,8 @@ public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// int valOfGlobalBonuses(CSelector selector) const; //used only for castle interface ???
|
||||
virtual CBonusSystemNode *whereShouldBeAttached(CGameState *gs);
|
||||
virtual CBonusSystemNode *whatShouldBeAttached();
|
||||
virtual CBonusSystemNode & whereShouldBeAttached(CGameState * gs);
|
||||
virtual CBonusSystemNode & whatShouldBeAttached();
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CArmedInstance();
|
||||
|
@ -195,6 +195,23 @@ bool CGHeroInstance::canLearnSkill() const
|
||||
return secSkills.size() < GameConstants::SKILL_PER_HERO;
|
||||
}
|
||||
|
||||
bool CGHeroInstance::canLearnSkill(SecondarySkill which) const
|
||||
{
|
||||
if ( !canLearnSkill())
|
||||
return false;
|
||||
|
||||
if (!cb->isAllowed(2, which))
|
||||
return false;
|
||||
|
||||
if (getSecSkillLevel(which) > 0)
|
||||
return false;
|
||||
|
||||
if (type->heroClass->secSkillProbability[which] == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CGHeroInstance::maxMovePoints(bool onLand) const
|
||||
{
|
||||
TurnInfo ti(this);
|
||||
@ -1062,17 +1079,17 @@ CBonusSystemNode * CGHeroInstance::whereShouldBeAttachedOnSiege(CGameState * gs)
|
||||
if(visitedTown)
|
||||
return whereShouldBeAttachedOnSiege(visitedTown->isBattleOutsideTown(this));
|
||||
|
||||
return CArmedInstance::whereShouldBeAttached(gs);
|
||||
return &CArmedInstance::whereShouldBeAttached(gs);
|
||||
}
|
||||
|
||||
CBonusSystemNode * CGHeroInstance::whereShouldBeAttached(CGameState * gs)
|
||||
CBonusSystemNode & CGHeroInstance::whereShouldBeAttached(CGameState * gs)
|
||||
{
|
||||
if(visitedTown)
|
||||
{
|
||||
if(inTownGarrison)
|
||||
return visitedTown;
|
||||
return *visitedTown;
|
||||
else
|
||||
return &visitedTown->townAndVis;
|
||||
return visitedTown->townAndVis;
|
||||
}
|
||||
else
|
||||
return CArmedInstance::whereShouldBeAttached(gs);
|
||||
@ -1117,7 +1134,7 @@ std::vector<SecondarySkill> CGHeroInstance::getLevelUpProposedSecondarySkills()
|
||||
std::vector<SecondarySkill> obligatorySkills; //hero is offered magic school or wisdom if possible
|
||||
if (!skillsInfo.wisdomCounter)
|
||||
{
|
||||
if (cb->isAllowed(2, SecondarySkill::WISDOM) && !getSecSkillLevel(SecondarySkill::WISDOM))
|
||||
if (canLearnSkill(SecondarySkill::WISDOM))
|
||||
obligatorySkills.push_back(SecondarySkill::WISDOM);
|
||||
}
|
||||
if (!skillsInfo.magicSchoolCounter)
|
||||
@ -1131,7 +1148,7 @@ std::vector<SecondarySkill> CGHeroInstance::getLevelUpProposedSecondarySkills()
|
||||
|
||||
for (auto skill : ss)
|
||||
{
|
||||
if (cb->isAllowed(2, skill) && !getSecSkillLevel(skill)) //only schools hero doesn't know yet
|
||||
if (canLearnSkill(skill)) //only schools hero doesn't know yet
|
||||
{
|
||||
obligatorySkills.push_back(skill);
|
||||
break; //only one
|
||||
@ -1143,7 +1160,7 @@ std::vector<SecondarySkill> CGHeroInstance::getLevelUpProposedSecondarySkills()
|
||||
//picking sec. skills for choice
|
||||
std::set<SecondarySkill> basicAndAdv, expert, none;
|
||||
for(int i = 0; i < VLC->skillh->size(); i++)
|
||||
if (cb->isAllowed(2,i))
|
||||
if (canLearnSkill(SecondarySkill(i)))
|
||||
none.insert(SecondarySkill(i));
|
||||
|
||||
for(auto & elem : secSkills)
|
||||
|
@ -187,6 +187,7 @@ public:
|
||||
|
||||
/// Returns true if hero has free secondary skill slot.
|
||||
bool canLearnSkill() const;
|
||||
bool canLearnSkill(SecondarySkill which) const;
|
||||
|
||||
void setPrimarySkill(PrimarySkill::PrimarySkill primarySkill, si64 value, ui8 abs);
|
||||
void setSecSkillLevel(SecondarySkill which, int val, bool abs);// abs == 0 - changes by value; 1 - sets to value
|
||||
@ -240,7 +241,7 @@ public:
|
||||
ArtBearer::ArtBearer bearerType() const override;
|
||||
|
||||
///IBonusBearer
|
||||
CBonusSystemNode * whereShouldBeAttached(CGameState *gs) override;
|
||||
CBonusSystemNode & whereShouldBeAttached(CGameState * gs) override;
|
||||
std::string nodeName() const override;
|
||||
|
||||
CBonusSystemNode * whereShouldBeAttachedOnSiege(const bool isBattleOutsideTown) const;
|
||||
|
@ -46,7 +46,7 @@ void CCreGenAsCastleInfo::serializeJson(JsonSerializeFormat & handler)
|
||||
|
||||
if(!handler.saving)
|
||||
{
|
||||
asCastle = (instanceId != "");
|
||||
asCastle = !instanceId.empty();
|
||||
allowedFactions.clear();
|
||||
}
|
||||
|
||||
@ -1146,7 +1146,7 @@ std::string CGTownInstance::nodeName() const
|
||||
|
||||
void CGTownInstance::deserializationFix()
|
||||
{
|
||||
attachTo(&townAndVis);
|
||||
attachTo(townAndVis);
|
||||
|
||||
//Hero is already handled by CGameState::attachArmedObjects
|
||||
|
||||
@ -1216,8 +1216,8 @@ void CGTownInstance::setVisitingHero(CGHeroInstance *h)
|
||||
{
|
||||
PlayerState *p = cb->gameState()->getPlayerState(h->tempOwner);
|
||||
assert(p);
|
||||
h->detachFrom(p);
|
||||
h->attachTo(&townAndVis);
|
||||
h->detachFrom(*p);
|
||||
h->attachTo(townAndVis);
|
||||
visitingHero = h;
|
||||
h->visitedTown = this;
|
||||
h->inTownGarrison = false;
|
||||
@ -1226,8 +1226,8 @@ void CGTownInstance::setVisitingHero(CGHeroInstance *h)
|
||||
{
|
||||
PlayerState *p = cb->gameState()->getPlayerState(visitingHero->tempOwner);
|
||||
visitingHero->visitedTown = nullptr;
|
||||
visitingHero->detachFrom(&townAndVis);
|
||||
visitingHero->attachTo(p);
|
||||
visitingHero->detachFrom(townAndVis);
|
||||
visitingHero->attachTo(*p);
|
||||
visitingHero = nullptr;
|
||||
}
|
||||
}
|
||||
@ -1239,8 +1239,8 @@ void CGTownInstance::setGarrisonedHero(CGHeroInstance *h)
|
||||
{
|
||||
PlayerState *p = cb->gameState()->getPlayerState(h->tempOwner);
|
||||
assert(p);
|
||||
h->detachFrom(p);
|
||||
h->attachTo(this);
|
||||
h->detachFrom(*p);
|
||||
h->attachTo(*this);
|
||||
garrisonHero = h;
|
||||
h->visitedTown = this;
|
||||
h->inTownGarrison = true;
|
||||
@ -1250,8 +1250,8 @@ void CGTownInstance::setGarrisonedHero(CGHeroInstance *h)
|
||||
PlayerState *p = cb->gameState()->getPlayerState(garrisonHero->tempOwner);
|
||||
garrisonHero->visitedTown = nullptr;
|
||||
garrisonHero->inTownGarrison = false;
|
||||
garrisonHero->detachFrom(this);
|
||||
garrisonHero->attachTo(p);
|
||||
garrisonHero->detachFrom(*this);
|
||||
garrisonHero->attachTo(*p);
|
||||
garrisonHero = nullptr;
|
||||
}
|
||||
updateMoraleBonusFromArmy(); //avoid giving morale bonus for same army twice
|
||||
@ -1290,9 +1290,9 @@ int CGTownInstance::getTownLevel() const
|
||||
return level;
|
||||
}
|
||||
|
||||
CBonusSystemNode * CGTownInstance::whatShouldBeAttached()
|
||||
CBonusSystemNode & CGTownInstance::whatShouldBeAttached()
|
||||
{
|
||||
return &townAndVis;
|
||||
return townAndVis;
|
||||
}
|
||||
|
||||
const CArmedInstance * CGTownInstance::getUpperArmy() const
|
||||
|
@ -274,7 +274,7 @@ public:
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CBonusSystemNode *whatShouldBeAttached() override;
|
||||
CBonusSystemNode & whatShouldBeAttached() override;
|
||||
std::string nodeName() const override;
|
||||
void updateMoraleBonusFromArmy() override;
|
||||
void deserializationFix();
|
||||
|
@ -572,7 +572,7 @@ void AObjectTypeHandler::addTemplate(JsonNode config)
|
||||
auto tmpl = new ObjectTemplate;
|
||||
tmpl->id = Obj(type);
|
||||
tmpl->subid = subtype;
|
||||
tmpl->stringID = ""; // TODO?
|
||||
tmpl->stringID.clear(); // TODO?
|
||||
tmpl->readJson(config);
|
||||
templates.emplace_back(tmpl);
|
||||
}
|
||||
|
@ -938,7 +938,7 @@ void CGSeerHut::serializeJsonOptions(JsonSerializeFormat & handler)
|
||||
case MANA_POINTS:
|
||||
case MORALE_BONUS:
|
||||
case LUCK_BONUS:
|
||||
identifier = "";
|
||||
identifier.clear();
|
||||
break;
|
||||
case RESOURCES:
|
||||
identifier = GameConstants::RESOURCE_NAMES[rID];
|
||||
@ -976,7 +976,7 @@ void CGSeerHut::serializeJsonOptions(JsonSerializeFormat & handler)
|
||||
|
||||
const JsonNode & rewardsJson = handler.getCurrent();
|
||||
|
||||
fullIdentifier = "";
|
||||
fullIdentifier.clear();
|
||||
|
||||
if(rewardsJson.Struct().empty())
|
||||
return;
|
||||
|
@ -1802,7 +1802,7 @@ void CGScholar::serializeJsonOptions(JsonSerializeFormat & handler)
|
||||
//TODO: unify
|
||||
const JsonNode & json = handler.getCurrent();
|
||||
bonusType = RANDOM;
|
||||
if(json["rewardPrimSkill"].String() != "")
|
||||
if(!json["rewardPrimSkill"].String().empty())
|
||||
{
|
||||
auto raw = VLC->modh->identifiers.getIdentifier("core", "primSkill", json["rewardPrimSkill"].String());
|
||||
if(raw)
|
||||
@ -1811,7 +1811,7 @@ void CGScholar::serializeJsonOptions(JsonSerializeFormat & handler)
|
||||
bonusID = raw.get();
|
||||
}
|
||||
}
|
||||
else if(json["rewardSkill"].String() != "")
|
||||
else if(!json["rewardSkill"].String().empty())
|
||||
{
|
||||
auto raw = VLC->modh->identifiers.getIdentifier("core", "skill", json["rewardSkill"].String());
|
||||
if(raw)
|
||||
@ -1820,7 +1820,7 @@ void CGScholar::serializeJsonOptions(JsonSerializeFormat & handler)
|
||||
bonusID = raw.get();
|
||||
}
|
||||
}
|
||||
else if(json["rewardSpell"].String() != "")
|
||||
else if(!json["rewardSpell"].String().empty())
|
||||
{
|
||||
auto raw = VLC->modh->identifiers.getIdentifier("core", "spell", json["rewardSpell"].String());
|
||||
if(raw)
|
||||
|
@ -203,7 +203,7 @@ void CMapHeader::setupEvents()
|
||||
standardVictory.effect.type = EventEffect::VICTORY;
|
||||
standardVictory.effect.toOtherMessage = VLC->generaltexth->allTexts[5];
|
||||
standardVictory.identifier = "standardVictory";
|
||||
standardVictory.description = ""; // TODO: display in quest window
|
||||
standardVictory.description.clear(); // TODO: display in quest window
|
||||
standardVictory.onFulfill = VLC->generaltexth->allTexts[659];
|
||||
standardVictory.trigger = EventExpression(victoryCondition);
|
||||
|
||||
@ -212,7 +212,7 @@ void CMapHeader::setupEvents()
|
||||
standardDefeat.effect.type = EventEffect::DEFEAT;
|
||||
standardDefeat.effect.toOtherMessage = VLC->generaltexth->allTexts[8];
|
||||
standardDefeat.identifier = "standardDefeat";
|
||||
standardDefeat.description = ""; // TODO: display in quest window
|
||||
standardDefeat.description.clear(); // TODO: display in quest window
|
||||
standardDefeat.onFulfill = VLC->generaltexth->allTexts[7];
|
||||
standardDefeat.trigger = EventExpression(defeatCondition);
|
||||
|
||||
@ -651,7 +651,7 @@ void CMap::addNewObject(CGObjectInstance * obj)
|
||||
if(obj->id != ObjectInstanceID((si32)objects.size()))
|
||||
throw std::runtime_error("Invalid object instance id");
|
||||
|
||||
if(obj->instanceName == "")
|
||||
if(obj->instanceName.empty())
|
||||
throw std::runtime_error("Object instance name missing");
|
||||
|
||||
if (vstd::contains(instanceNames, obj->instanceName))
|
||||
|
@ -313,7 +313,7 @@ void CMapLoaderH3M::readVictoryLossConditions()
|
||||
standardVictory.effect.type = EventEffect::VICTORY;
|
||||
standardVictory.effect.toOtherMessage = VLC->generaltexth->allTexts[5];
|
||||
standardVictory.identifier = "standardVictory";
|
||||
standardVictory.description = ""; // TODO: display in quest window
|
||||
standardVictory.description.clear(); // TODO: display in quest window
|
||||
standardVictory.onFulfill = VLC->generaltexth->allTexts[659];
|
||||
standardVictory.trigger = EventExpression(victoryCondition);
|
||||
|
||||
@ -321,7 +321,7 @@ void CMapLoaderH3M::readVictoryLossConditions()
|
||||
standardDefeat.effect.type = EventEffect::DEFEAT;
|
||||
standardDefeat.effect.toOtherMessage = VLC->generaltexth->allTexts[8];
|
||||
standardDefeat.identifier = "standardDefeat";
|
||||
standardDefeat.description = ""; // TODO: display in quest window
|
||||
standardDefeat.description.clear(); // TODO: display in quest window
|
||||
standardDefeat.onFulfill = VLC->generaltexth->allTexts[7];
|
||||
standardDefeat.trigger = EventExpression(defeatCondition);
|
||||
|
||||
@ -338,7 +338,7 @@ void CMapLoaderH3M::readVictoryLossConditions()
|
||||
TriggeredEvent specialVictory;
|
||||
specialVictory.effect.type = EventEffect::VICTORY;
|
||||
specialVictory.identifier = "specialVictory";
|
||||
specialVictory.description = ""; // TODO: display in quest window
|
||||
specialVictory.description.clear(); // TODO: display in quest window
|
||||
|
||||
mapHeader->victoryIconIndex = ui16(vicCondition);
|
||||
mapHeader->victoryMessage = VLC->generaltexth->victoryConditions[size_t(vicCondition) + 1];
|
||||
@ -526,7 +526,7 @@ void CMapLoaderH3M::readVictoryLossConditions()
|
||||
specialDefeat.effect.type = EventEffect::DEFEAT;
|
||||
specialDefeat.effect.toOtherMessage = VLC->generaltexth->allTexts[5];
|
||||
specialDefeat.identifier = "specialDefeat";
|
||||
specialDefeat.description = ""; // TODO: display in quest window
|
||||
specialDefeat.description.clear(); // TODO: display in quest window
|
||||
|
||||
mapHeader->defeatIconIndex = ui16(lossCond);
|
||||
mapHeader->defeatMessage = VLC->generaltexth->lossCondtions[size_t(lossCond) + 1];
|
||||
|
@ -134,7 +134,7 @@ namespace TriggeredEventsDetail
|
||||
|
||||
static EMetaclass decodeMetaclass(const std::string & source)
|
||||
{
|
||||
if(source == "")
|
||||
if(source.empty())
|
||||
return EMetaclass::INVALID;
|
||||
auto rawId = vstd::find_pos(NMetaclass::names, source);
|
||||
|
||||
@ -286,7 +286,7 @@ namespace TriggeredEventsDetail
|
||||
if(event.value > 0)
|
||||
data["value"].Integer() = event.value;
|
||||
|
||||
if(event.objectInstanceName != "")
|
||||
if(!event.objectInstanceName.empty())
|
||||
data["object"].String() = event.objectInstanceName;
|
||||
}
|
||||
break;
|
||||
|
@ -319,6 +319,7 @@ void registerTypesClientPacks2(Serializer &s)
|
||||
s.template registerType<CArtifactOperationPack, MoveArtifact>();
|
||||
s.template registerType<CArtifactOperationPack, AssembledArtifact>();
|
||||
s.template registerType<CArtifactOperationPack, DisassembledArtifact>();
|
||||
s.template registerType<CArtifactOperationPack, BulkMoveArtifacts>();
|
||||
|
||||
s.template registerType<CPackForClient, SaveGameClient>();
|
||||
s.template registerType<CPackForClient, PlayerMessageClient>();
|
||||
@ -358,6 +359,7 @@ void registerTypesServerPacks(Serializer &s)
|
||||
s.template registerType<CPackForServer, BulkMergeStacks>();
|
||||
s.template registerType<CPackForServer, BulkSmartSplitStack>();
|
||||
s.template registerType<CPackForServer, BulkMoveArmy>();
|
||||
s.template registerType<CPackForServer, BulkExchangeArtifacts>();
|
||||
}
|
||||
|
||||
template<typename Serializer>
|
||||
|
@ -38,7 +38,7 @@ void JsonDeserializer::serializeInternal(const std::string & fieldName, si32 & v
|
||||
|
||||
value = defaultValue ? defaultValue.get() : 0;
|
||||
|
||||
if(identifier != "")
|
||||
if(!identifier.empty())
|
||||
{
|
||||
si32 rawId = decoder(identifier);
|
||||
|
||||
|
@ -108,7 +108,7 @@ void JsonSerializer::serializeLIC(const std::string & fieldName, LICSet & value)
|
||||
|
||||
void JsonSerializer::serializeString(const std::string & fieldName, std::string & value)
|
||||
{
|
||||
if(value != "")
|
||||
if(!value.empty())
|
||||
currentObject->operator[](fieldName).String() = value;
|
||||
}
|
||||
|
||||
|
@ -1011,7 +1011,7 @@ void MainWindow::onSelectionMade(int level, bool anythingSelected)
|
||||
{
|
||||
if (level == mapLevel)
|
||||
{
|
||||
auto info = QString::asprintf("Selection on layer %d: %b", level, anythingSelected ? "true" : "false");
|
||||
auto info = QString::asprintf("Selection on layer %d: %s", level, anythingSelected ? "true" : "false");
|
||||
setStatusMessage(info);
|
||||
|
||||
ui->actionErase->setEnabled(anythingSelected);
|
||||
|
@ -51,7 +51,7 @@ bool ObjectBrowser::filterAcceptsRow(int source_row, const QModelIndex & source_
|
||||
auto factory = VLC->objtypeh->getHandlerFor(objId, objSubId);
|
||||
auto templ = factory->getTemplates()[templateId];
|
||||
|
||||
result = result & templ->canBePlacedAt(terrain);
|
||||
result = result && templ->canBePlacedAt(terrain);
|
||||
|
||||
//if we are here, just text filter will be applied
|
||||
return result;
|
||||
|
@ -3916,10 +3916,101 @@ bool CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocat
|
||||
moveArtifact(dst, ArtifactLocation(dst.artHolder, ArtifactPosition(
|
||||
(si32)dst.getHolderArtSet()->artifactsInBackpack.size() + GameConstants::BACKPACK_START)));
|
||||
}
|
||||
auto hero = boost::get<ConstTransitivePtr<CGHeroInstance>>(dst.artHolder);
|
||||
if(ArtifactUtils::checkSpellbookIsNeeded(hero, srcArtifact->artType->id, dst.slot))
|
||||
giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
|
||||
|
||||
MoveArtifact ma;
|
||||
ma.src = src;
|
||||
ma.dst = dst;
|
||||
MoveArtifact ma(&src, &dst);
|
||||
sendAndApply(&ma);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap)
|
||||
{
|
||||
// Make sure exchange is even possible between the two heroes.
|
||||
if(!isAllowedExchange(srcHero, dstHero))
|
||||
COMPLAIN_RET("That heroes cannot make any exchange!");
|
||||
|
||||
auto psrcHero = getHero(srcHero);
|
||||
auto pdstHero = getHero(dstHero);
|
||||
if((!psrcHero) || (!pdstHero))
|
||||
COMPLAIN_RET("bulkMoveArtifacts: wrong hero's ID");
|
||||
|
||||
BulkMoveArtifacts ma(static_cast<ConstTransitivePtr<CGHeroInstance>>(psrcHero),
|
||||
static_cast<ConstTransitivePtr<CGHeroInstance>>(pdstHero), swap);
|
||||
auto & slotsSrcDst = ma.artsPack0;
|
||||
auto & slotsDstSrc = ma.artsPack1;
|
||||
|
||||
if(swap)
|
||||
{
|
||||
auto moveArtsWorn = [this](const CGHeroInstance * srcHero, const CGHeroInstance * dstHero,
|
||||
std::vector<BulkMoveArtifacts::LinkedSlots> & slots) -> void
|
||||
{
|
||||
for(auto & artifact : srcHero->artifactsWorn)
|
||||
{
|
||||
if(artifact.second.locked)
|
||||
continue;
|
||||
if(!ArtifactUtils::isArtRemovable(artifact))
|
||||
continue;
|
||||
slots.push_back(BulkMoveArtifacts::LinkedSlots(artifact.first, artifact.first));
|
||||
|
||||
auto art = artifact.second.getArt();
|
||||
assert(art);
|
||||
if(ArtifactUtils::checkSpellbookIsNeeded(dstHero, art->artType->id, artifact.first))
|
||||
giveHeroNewArtifact(dstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
|
||||
}
|
||||
};
|
||||
auto moveArtsInBackpack = [](const CGHeroInstance * pHero,
|
||||
std::vector<BulkMoveArtifacts::LinkedSlots> & slots) -> void
|
||||
{
|
||||
for(auto & slotInfo : pHero->artifactsInBackpack)
|
||||
{
|
||||
auto slot = pHero->getArtPos(slotInfo.artifact);
|
||||
slots.push_back(BulkMoveArtifacts::LinkedSlots(slot, slot));
|
||||
}
|
||||
};
|
||||
// Move over artifacts that are worn srcHero -> dstHero
|
||||
moveArtsWorn(psrcHero, pdstHero, slotsSrcDst);
|
||||
// Move over artifacts that are worn dstHero -> srcHero
|
||||
moveArtsWorn(pdstHero, psrcHero, slotsDstSrc);
|
||||
// Move over artifacts that are in backpack srcHero -> dstHero
|
||||
moveArtsInBackpack(psrcHero, slotsSrcDst);
|
||||
// Move over artifacts that are in backpack dstHero -> srcHero
|
||||
moveArtsInBackpack(pdstHero, slotsDstSrc);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Temporary fitting set for artifacts. Used to select available slots before sending data.
|
||||
CArtifactFittingSet artFittingSet(pdstHero->bearerType());
|
||||
artFittingSet.artifactsInBackpack = pdstHero->artifactsInBackpack;
|
||||
artFittingSet.artifactsWorn = pdstHero->artifactsWorn;
|
||||
|
||||
auto moveArtifact = [this, &artFittingSet, &slotsSrcDst](const CArtifactInstance * artifact,
|
||||
ArtifactPosition srcSlot, const CGHeroInstance * pdstHero) -> void
|
||||
{
|
||||
assert(artifact);
|
||||
auto dstSlot = ArtifactUtils::getArtifactDstPosition(artifact, &artFittingSet, pdstHero->bearerType());
|
||||
artFittingSet.putArtifact(dstSlot, static_cast<ConstTransitivePtr<CArtifactInstance>>(artifact));
|
||||
slotsSrcDst.push_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot));
|
||||
|
||||
if(ArtifactUtils::checkSpellbookIsNeeded(pdstHero, artifact->artType->id, dstSlot))
|
||||
giveHeroNewArtifact(pdstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
|
||||
};
|
||||
|
||||
// Move over artifacts that are worn
|
||||
for(auto & artInfo : psrcHero->artifactsWorn)
|
||||
{
|
||||
if(ArtifactUtils::isArtRemovable(artInfo))
|
||||
{
|
||||
moveArtifact(psrcHero->getArt(artInfo.first), artInfo.first, pdstHero);
|
||||
}
|
||||
}
|
||||
// Move over artifacts that are in backpack
|
||||
for(auto & slotInfo : psrcHero->artifactsInBackpack)
|
||||
{
|
||||
moveArtifact(psrcHero->getArt(psrcHero->getArtPos(slotInfo.artifact)), psrcHero->getArtPos(slotInfo.artifact), pdstHero);
|
||||
}
|
||||
}
|
||||
sendAndApply(&ma);
|
||||
return true;
|
||||
}
|
||||
@ -3947,6 +4038,9 @@ bool CGameHandler::assembleArtifacts (ObjectInstanceID heroID, ArtifactPosition
|
||||
COMPLAIN_RET("assembleArtifacts: Artifact being attempted to assemble is not a combined artifacts!");
|
||||
if (!vstd::contains(destArtifact->assemblyPossibilities(hero), combinedArt))
|
||||
COMPLAIN_RET("assembleArtifacts: It's impossible to assemble requested artifact!");
|
||||
|
||||
if(ArtifactUtils::checkSpellbookIsNeeded(hero, assembleTo, artifactSlot))
|
||||
giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
|
||||
|
||||
AssembledArtifact aa;
|
||||
aa.al = ArtifactLocation(hero, artifactSlot);
|
||||
@ -4083,7 +4177,7 @@ bool CGameHandler::buySecSkill(const IMarket *m, const CGHeroInstance *h, Second
|
||||
if (!h->canLearnSkill())
|
||||
COMPLAIN_RET("Hero can't learn any more skills");
|
||||
|
||||
if (h->type->heroClass->secSkillProbability.at(skill)==0)//can't learn this skill (like necromancy for most of non-necros)
|
||||
if (!h->canLearnSkill(skill))
|
||||
COMPLAIN_RET("The hero can't learn this skill!");
|
||||
|
||||
if (!vstd::contains(m->availableItemsIds(EMarketMode::RESOURCE_SKILL), skill))
|
||||
|
@ -180,7 +180,8 @@ public:
|
||||
void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, ArtifactPosition pos) override;
|
||||
void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) override;
|
||||
void removeArtifact(const ArtifactLocation &al) override;
|
||||
bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) override;
|
||||
bool moveArtifact(const ArtifactLocation & al1, const ArtifactLocation & al2) override;
|
||||
bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap);
|
||||
void synchronizeArtifactHandlerLists();
|
||||
|
||||
void showCompInfo(ShowInInfobox * comp) override;
|
||||
|
@ -370,6 +370,9 @@ bool CGarrisonDialogQuery::blocksPack(const CPack * pack) const
|
||||
}
|
||||
if(auto dismiss = dynamic_ptr_cast<DisbandCreature>(pack))
|
||||
return !vstd::contains(ourIds, dismiss->id);
|
||||
|
||||
if(auto arts = dynamic_ptr_cast<BulkExchangeArtifacts>(pack))
|
||||
return !vstd::contains(ourIds, arts->srcHero) || !vstd::contains(ourIds, arts->dstHero);
|
||||
|
||||
if(auto dismiss = dynamic_ptr_cast<AssembleArtifacts>(pack))
|
||||
return !vstd::contains(ourIds, dismiss->heroID);
|
||||
|
@ -180,6 +180,13 @@ bool ExchangeArtifacts::applyGh(CGameHandler * gh)
|
||||
return gh->moveArtifact(src, dst);
|
||||
}
|
||||
|
||||
bool BulkExchangeArtifacts::applyGh(CGameHandler * gh)
|
||||
{
|
||||
const CGHeroInstance * pSrcHero = gh->getHero(srcHero);
|
||||
throwOnWrongPlayer(gh, pSrcHero->getOwner());
|
||||
return gh->bulkMoveArtifacts(srcHero, dstHero, swap);
|
||||
}
|
||||
|
||||
bool AssembleArtifacts::applyGh(CGameHandler * gh)
|
||||
{
|
||||
throwOnWrongOwner(gh, heroID);
|
||||
|
Loading…
Reference in New Issue
Block a user