From c047fea44ca518d85d069c8b6498339d448c785d Mon Sep 17 00:00:00 2001 From: DjWarmonger Date: Mon, 2 Nov 2015 16:39:57 +0100 Subject: [PATCH 01/20] Updated changelog. To be released as VCMI 0.98e. --- ChangeLog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ChangeLog b/ChangeLog index 52d54291b..0c22d23f9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 0.98 -> 0.next +GENERAL: +* New Bonus NO_TERRAIN_PENALTY +* Nomads will remove Sand movement penalty from army + ADVETURE AI: * Fixed AI trying to go through underground rock * Fixed several cases causing AI wandering aimlessly From 349f16a35914afbd867700faa7686e35a179b9c8 Mon Sep 17 00:00:00 2001 From: DjWarmonger Date: Mon, 2 Nov 2015 17:28:54 +0100 Subject: [PATCH 02/20] Version bump. --- lib/GameConstants.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/GameConstants.h b/lib/GameConstants.h index 0a1f74945..05d3128eb 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -14,7 +14,7 @@ namespace GameConstants { - const std::string VCMI_VERSION = "VCMI 0.98e"; + const std::string VCMI_VERSION = "VCMI 0.98f"; const int BFIELD_WIDTH = 17; const int BFIELD_HEIGHT = 11; From b024237e8ade279301b5a9686409684788168986 Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Wed, 14 Oct 2015 11:47:45 +0300 Subject: [PATCH 03/20] Remove stack instancies of removed stacks --- server/CGameHandler.cpp | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 4634ae5c7..f6fc0ae6f 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -3854,12 +3854,13 @@ bool CGameHandler::makeBattleAction( BattleAction &ba ) const CStack *summoner = gs->curB->battleGetStackByID(ba.stackNumber), *destStack = gs->curB->battleGetStackByPos(ba.destinationTile, false); + CreatureID summonedType(summoner->getBonusLocalFirst(Selector::type(Bonus::DAEMON_SUMMONING))->subtype);//in case summoner can summon more than one type of monsters... scream! BattleStackAdded bsa; bsa.attacker = summoner->attackerOwned; - bsa.creID = CreatureID(summoner->getBonusLocalFirst(Selector::type(Bonus::DAEMON_SUMMONING))->subtype); //in case summoner can summon more than one type of monsters... scream! + bsa.creID = summonedType; ui64 risedHp = summoner->count * summoner->valOfBonuses(Bonus::DAEMON_SUMMONING, bsa.creID.toEnum()); - ui64 targetHealth = destStack->getCreature()->MaxHealth() * destStack->baseAmount; + ui64 targetHealth = destStack->getCreature()->MaxHealth() * destStack->baseAmount;//todo: ignore AGE effect ui64 canRiseHp = std::min(targetHealth, risedHp); ui32 canRiseAmount = canRiseHp / VLC->creh->creatures.at(bsa.creID)->MaxHealth(); @@ -5812,6 +5813,32 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleI if(color == PlayerColor::UNFLAGGABLE) color = PlayerColor::NEUTRAL; + //1. Find removed stacks. + for(const auto & slotInfo : army->stacks) + { + const SlotID slot = slotInfo.first; + const CStackInstance * instance = slotInfo.second; + + if(nullptr != instance)//just in case + { + bool found = false; + for(const CStack * sta : bat->stacks) + { + if(sta->base == instance) + { + found = true; + break; + } + } + //stack in this slot was removed == it is dead + if(!found) + { + StackLocation sl(army, slot); + newStackCounts.push_back(TStackAndItsNewCount(sl, 0)); + } + } + } + for(CStack *st : bat->stacks) { if(vstd::contains(st->state, EBattleStackState::SUMMONED)) //don't take into account summoned stacks From c94bea51e30c01125d03e3feed64e73de0afa0b3 Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Thu, 15 Oct 2015 17:03:22 +0300 Subject: [PATCH 04/20] Update army in case of summoned creatures --- server/CGameHandler.cpp | 77 +++++++++++++++++++++++++++++------------ server/CGameHandler.h | 9 +++-- 2 files changed, 60 insertions(+), 26 deletions(-) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index f6fc0ae6f..dcf61666c 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -651,8 +651,8 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer sendAndApply(&cs); } - cab1.takeFromArmy(this); - cab2.takeFromArmy(this); //take casualties after battle is deleted + cab1.updateArmy(this); + cab2.updateArmy(this); //take casualties after battle is deleted //if one hero has lost we will erase him if(battleResult.data->winner!=0 && hero1) @@ -5805,13 +5805,29 @@ void CGameHandler::duelFinished() return; } -CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat) +CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance * _army, BattleInfo *bat): + army(_army) { heroWithDeadCommander = ObjectInstanceID(); PlayerColor color = army->tempOwner; if(color == PlayerColor::UNFLAGGABLE) color = PlayerColor::NEUTRAL; + + auto killStack = [&, this](const SlotID slot, const CStackInstance * instance) + { + StackLocation sl(army, slot); + newStackCounts.push_back(TStackAndItsNewCount(sl, 0)); + if(nullptr == instance) + return; + auto c = dynamic_cast (instance); + if (c) //switch commander status to dead + { + auto h = dynamic_cast (army); + if (h && h->commander == c) + heroWithDeadCommander = army->id; //TODO: unify commander handling + } + }; //1. Find removed stacks. for(const auto & slotInfo : army->stacks) @@ -5832,10 +5848,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleI } //stack in this slot was removed == it is dead if(!found) - { - StackLocation sl(army, slot); - newStackCounts.push_back(TStackAndItsNewCount(sl, 0)); - } + killStack(slot, instance); } } @@ -5859,29 +5872,32 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleI removedWarMachines.push_back (ArtifactLocation(hero, hero->getArtPos(warMachine, true))); } } - - if(!army->slotEmpty(st->slot) && st->count < army->getStackCount(st->slot)) + + if(army->slotEmpty(st->slot)) { - StackLocation sl(army, st->slot); - if(st->alive()) - newStackCounts.push_back(std::pair(sl, st->count)); - else - newStackCounts.push_back(std::pair(sl, 0)); - } - if (st->base && !st->count) - { - auto c = dynamic_cast (st->base); - if (c) //switch commander status to dead + if(st->slot == SlotID(255) && !vstd::contains(st->state, EBattleStackState::SUMMONED) && st->alive()) { - auto h = dynamic_cast (army); - if (h && h->commander == c) - heroWithDeadCommander = army->id; //TODO: unify commander handling + //this stack was permanently summoned + const CreatureID summonedType = st->type->idNumber; + summoned[summonedType] += st->count; + } + } + else + { + if(st->count == 0 || !st->alive()) + { + killStack(st->slot, st->base); + } + else if(st->count < army->getStackCount(st->slot)) + { + StackLocation sl(army, st->slot); + newStackCounts.push_back(TStackAndItsNewCount(sl, st->count)); } } } } -void CasualtiesAfterBattle::takeFromArmy(CGameHandler *gh) +void CasualtiesAfterBattle::updateArmy(CGameHandler *gh) { for(TStackAndItsNewCount &ncount : newStackCounts) { @@ -5890,6 +5906,21 @@ void CasualtiesAfterBattle::takeFromArmy(CGameHandler *gh) else gh->eraseStack(ncount.first, true); } + for(auto summoned_iter : summoned) + { + SlotID slot = army->getSlotFor(summoned_iter.first); + if(slot.validSlot()) + { + StackLocation location(army, slot); + gh->addToSlot(location, summoned_iter.first.toCreature(), summoned_iter.second); + } + else + { + //even if it will be possible to summon anything permanently it should be checked for free slot + //necromancy is handled separately + gh->complain("No free slot to put summoned creature"); + } + } for (auto al : removedWarMachines) { gh->removeArtifact(al); diff --git a/server/CGameHandler.h b/server/CGameHandler.h index acf1698a2..bc2a336a7 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -71,13 +71,16 @@ public: struct CasualtiesAfterBattle { typedef std::pair TStackAndItsNewCount; + typedef std::map TSummoned; enum {ERASE = -1}; + const CArmedInstance * army; std::vector newStackCounts; std::vector removedWarMachines; - ObjectInstanceID heroWithDeadCommander; //TODO: unify stack loactions + TSummoned summoned; + ObjectInstanceID heroWithDeadCommander; //TODO: unify stack locations - CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat); - void takeFromArmy(CGameHandler *gh); + CasualtiesAfterBattle(const CArmedInstance * _army, BattleInfo *bat); + void updateArmy(CGameHandler *gh); }; class CGameHandler : public IGameCallback, CBattleInfoCallback From f6b9015324c5cb38adc6b4eb5d8ef4e814065141 Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Thu, 15 Oct 2015 17:43:03 +0300 Subject: [PATCH 05/20] Use constant for summoned creature slot --- lib/GameConstants.cpp | 1 + lib/GameConstants.h | 1 + lib/NetPacksLib.cpp | 2 +- server/CGameHandler.cpp | 4 ++-- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/GameConstants.cpp b/lib/GameConstants.cpp index 9a48b476f..3b5acc577 100644 --- a/lib/GameConstants.cpp +++ b/lib/GameConstants.cpp @@ -19,6 +19,7 @@ #include "spells/CSpellHandler.h" const SlotID SlotID::COMMANDER_SLOT_PLACEHOLDER = SlotID(-2); +const SlotID SlotID::SUMMONED_SLOT_PLACEHOLDER = SlotID(255); const PlayerColor PlayerColor::CANNOT_DETERMINE = PlayerColor(253); const PlayerColor PlayerColor::UNFLAGGABLE = PlayerColor(254); const PlayerColor PlayerColor::NEUTRAL = PlayerColor(255); diff --git a/lib/GameConstants.h b/lib/GameConstants.h index 05d3128eb..98e344d6b 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -216,6 +216,7 @@ class SlotID : public BaseForID friend class CNonConstInfoCallback; DLL_LINKAGE static const SlotID COMMANDER_SLOT_PLACEHOLDER; + DLL_LINKAGE static const SlotID SUMMONED_SLOT_PLACEHOLDER; ///curB->generateNewStack(csbd, attacker, SlotID(255), pos); //TODO: netpacks? + CStack * addedStack = gs->curB->generateNewStack(csbd, attacker, SlotID::SUMMONED_SLOT_PLACEHOLDER, pos); //TODO: netpacks? if (summoned) addedStack->state.insert(EBattleStackState::SUMMONED); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index dcf61666c..bd546edc5 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -5862,7 +5862,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance * _army, Battl //FIXME: this info is also used in BattleInfo::calculateCasualties, refactor st->count = std::max (0, st->count - st->resurrected); - if (!st->count && !st->base) //we can imagine stacks of war mahcines that are not spawned by artifacts? + if (!st->count && !st->base) //we can imagine stacks of war machines that are not spawned by artifacts? { auto warMachine = VLC->arth->creatureToMachineID(st->type->idNumber); if (warMachine != ArtifactID::NONE) @@ -5875,7 +5875,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance * _army, Battl if(army->slotEmpty(st->slot)) { - if(st->slot == SlotID(255) && !vstd::contains(st->state, EBattleStackState::SUMMONED) && st->alive()) + if(st->slot == SlotID::SUMMONED_SLOT_PLACEHOLDER && !vstd::contains(st->state, EBattleStackState::SUMMONED) && st->alive()) { //this stack was permanently summoned const CreatureID summonedType = st->type->idNumber; From fbebbf39f3642823628312d44dbb46132d2cd85c Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Fri, 16 Oct 2015 09:11:11 +0300 Subject: [PATCH 06/20] Fix zero size stack summoned in case of basic resurrection. --- server/CGameHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index bd546edc5..051c778d1 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -5875,7 +5875,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance * _army, Battl if(army->slotEmpty(st->slot)) { - if(st->slot == SlotID::SUMMONED_SLOT_PLACEHOLDER && !vstd::contains(st->state, EBattleStackState::SUMMONED) && st->alive()) + if(st->slot == SlotID::SUMMONED_SLOT_PLACEHOLDER && !vstd::contains(st->state, EBattleStackState::SUMMONED) && st->alive() && st->count > 0) { //this stack was permanently summoned const CreatureID summonedType = st->type->idNumber; From 6a9dc78dcd9735a6c9290f91f8f4d0b21370f51e Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Sat, 24 Oct 2015 00:29:45 +0300 Subject: [PATCH 07/20] [WiP]Added some checks for RISE_DEMONS action. --- client/battle/CBattleInterface.cpp | 14 ++++++++++++-- server/CGameHandler.cpp | 10 +++++----- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/client/battle/CBattleInterface.cpp b/client/battle/CBattleInterface.cpp index 452b41d76..a914e623e 100644 --- a/client/battle/CBattleInterface.cpp +++ b/client/battle/CBattleInterface.cpp @@ -2163,7 +2163,14 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType) break; case RISE_DEMONS: if (shere && ourStack && !shere->alive()) - legalAction = true; + { + if(!(shere->hasBonusOfType(Bonus::UNDEAD) + || shere->hasBonusOfType(Bonus::NON_LIVING) + || vstd::contains(shere->state, EBattleStackState::SUMMONED) + || vstd::contains(shere->state, EBattleStackState::CLONED) + )) + legalAction = true; + } break; } if (legalAction) @@ -2320,7 +2327,10 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType) break; case RISE_DEMONS: cursorType = ECursor::SPELLBOOK; - realizeAction = [=]{ giveCommand(Battle::DAEMON_SUMMONING, myNumber, activeStack->ID); }; + realizeAction = [=] + { + giveCommand(Battle::DAEMON_SUMMONING, myNumber, activeStack->ID); + }; break; case CATAPULT: cursorFrame = ECursor::COMBAT_SHOOT_CATAPULT; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 051c778d1..f747a4bc5 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -3848,9 +3848,6 @@ bool CGameHandler::makeBattleAction( BattleAction &ba ) //TODO: From Strategija: //Summon Demon is a level 2 spell. { - StartAction start_action(ba); - sendAndApply(&start_action); - const CStack *summoner = gs->curB->battleGetStackByID(ba.stackNumber), *destStack = gs->curB->battleGetStackByPos(ba.destinationTile, false); @@ -3872,6 +3869,9 @@ bool CGameHandler::makeBattleAction( BattleAction &ba ) if (bsa.amount) //there's rare possibility single creature cannot rise desired type { + StartAction start_action(ba); + sendAndApply(&start_action); + BattleStacksRemoved bsr; //remove body bsr.stackIDs.insert(destStack->ID); sendAndApply(&bsr); @@ -3883,9 +3883,9 @@ bool CGameHandler::makeBattleAction( BattleAction &ba ) ssp.val = -1; ssp.absolute = false; sendAndApply(&ssp); - } - sendAndApply(&end_action); + sendAndApply(&end_action); + } break; } case Battle::MONSTER_SPELL: From 4b5cb3599a9d6495e3fafd732262896d2e89601a Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Sun, 1 Nov 2015 01:05:31 +0300 Subject: [PATCH 08/20] Do not try to rise demons from war machines --- client/battle/CBattleInterface.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/client/battle/CBattleInterface.cpp b/client/battle/CBattleInterface.cpp index a914e623e..c1ea5ec45 100644 --- a/client/battle/CBattleInterface.cpp +++ b/client/battle/CBattleInterface.cpp @@ -2168,6 +2168,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType) || shere->hasBonusOfType(Bonus::NON_LIVING) || vstd::contains(shere->state, EBattleStackState::SUMMONED) || vstd::contains(shere->state, EBattleStackState::CLONED) + || shere->hasBonusOfType(Bonus::SIEGE_WEAPON) )) legalAction = true; } From 8b6b4e2e0b81169444a1879b3ac505ca346925f3 Mon Sep 17 00:00:00 2001 From: ArseniyShestakov Date: Tue, 3 Nov 2015 14:40:36 +0300 Subject: [PATCH 09/20] Fix header case for Linux to Windows cross compilation using MingGW --- lib/CConsoleHandler.cpp | 2 +- lib/VCMIDirs.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/CConsoleHandler.cpp b/lib/CConsoleHandler.cpp index 649df26aa..20a992f68 100644 --- a/lib/CConsoleHandler.cpp +++ b/lib/CConsoleHandler.cpp @@ -27,7 +27,7 @@ DLL_LINKAGE CConsoleHandler * console = nullptr; #define CONSOLE_GRAY "\x1b[1;30m" #define CONSOLE_TEAL "\x1b[1;36m" #else - #include + #include #include #ifndef __MINGW32__ #pragma comment(lib, "dbghelp.lib") diff --git a/lib/VCMIDirs.cpp b/lib/VCMIDirs.cpp index 679b68fd0..7c2110afa 100644 --- a/lib/VCMIDirs.cpp +++ b/lib/VCMIDirs.cpp @@ -34,9 +34,9 @@ void IVCMIDirs::init() #endif #endif // __MINGW32__ -#include -#include -#include +#include +#include +#include // Generates script file named _temp.bat in 'to' directory and runs it // Script will: From f80c1410b31d758adc2b3ec3ada3e27133eb41a4 Mon Sep 17 00:00:00 2001 From: Andreas Cadhalpun Date: Thu, 5 Nov 2015 10:53:44 +0100 Subject: [PATCH 10/20] Replace deprecated FFmpeg API for compatibility with ffmpeg 2.9 --- client/CVideoHandler.cpp | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/client/CVideoHandler.cpp b/client/CVideoHandler.cpp index c33472517..1218fc0d2 100644 --- a/client/CVideoHandler.cpp +++ b/client/CVideoHandler.cpp @@ -151,7 +151,11 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scal } // Allocate video frame +#if LIBAVUTIL_VERSION_MAJOR > 52 + frame = av_alloc_frame(); +#else frame = avcodec_alloc_frame(); +#endif //setup scaling @@ -185,21 +189,36 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scal if (texture) { // Convert the image into YUV format that SDL uses sws = sws_getContext(codecContext->width, codecContext->height, codecContext->pix_fmt, - pos.w, pos.h, PIX_FMT_YUV420P, + pos.w, pos.h, +#if LIBAVUTIL_VERSION_MAJOR > 51 + AV_PIX_FMT_YUV420P, +#else + PIX_FMT_YUV420P, +#endif SWS_BICUBIC, nullptr, nullptr, nullptr); } else { +#if LIBAVUTIL_VERSION_MAJOR > 51 + AVPixelFormat screenFormat = AV_PIX_FMT_NONE; +#else PixelFormat screenFormat = PIX_FMT_NONE; +#endif if (screen->format->Bshift > screen->format->Rshift) { // this a BGR surface switch (screen->format->BytesPerPixel) { +#if LIBAVUTIL_VERSION_MAJOR > 51 + case 2: screenFormat = AV_PIX_FMT_BGR565; break; + case 3: screenFormat = AV_PIX_FMT_BGR24; break; + case 4: screenFormat = AV_PIX_FMT_BGR32; break; +#else case 2: screenFormat = PIX_FMT_BGR565; break; case 3: screenFormat = PIX_FMT_BGR24; break; case 4: screenFormat = PIX_FMT_BGR32; break; +#endif default: return false; } } @@ -208,9 +227,15 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scal // this a RGB surface switch (screen->format->BytesPerPixel) { +#if LIBAVUTIL_VERSION_MAJOR > 51 + case 2: screenFormat = AV_PIX_FMT_RGB565; break; + case 3: screenFormat = AV_PIX_FMT_RGB24; break; + case 4: screenFormat = AV_PIX_FMT_RGB32; break; +#else case 2: screenFormat = PIX_FMT_RGB565; break; case 3: screenFormat = PIX_FMT_RGB24; break; case 4: screenFormat = PIX_FMT_RGB32; break; +#endif default: return false; } } @@ -367,7 +392,11 @@ void CVideoPlayer::close() if (frame) { +#if LIBAVUTIL_VERSION_MAJOR > 52 + av_frame_free(frame); +#else av_free(frame); +#endif frame = nullptr; } From bd12989ad69be16ebcbb8e995b1f1f5c194fcdae Mon Sep 17 00:00:00 2001 From: ArseniyShestakov Date: Fri, 6 Nov 2015 21:54:51 +0300 Subject: [PATCH 11/20] Artifacts: use ArtifactID instead of ints --- lib/CArtHandler.cpp | 4 ++-- server/CGameHandler.cpp | 36 ++++++++++++++++++------------------ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 84abf0173..ac4a310a9 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -738,8 +738,8 @@ std::string CArtifactInstance::nodeName() const CArtifactInstance * CArtifactInstance::createScroll( const CSpell *s) { - auto ret = new CArtifactInstance(VLC->arth->artifacts[1]); - auto b = new Bonus(Bonus::PERMANENT, Bonus::SPELL, Bonus::ARTIFACT_INSTANCE, -1, 1, s->id); + auto ret = new CArtifactInstance(VLC->arth->artifacts[ArtifactID::SPELL_SCROLL]); + auto b = new Bonus(Bonus::PERMANENT, Bonus::SPELL, Bonus::ARTIFACT_INSTANCE, -1, ArtifactID::SPELL_SCROLL, s->id); ret->addNewBonus(b); return ret; } diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index f747a4bc5..ba81d0f77 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2772,14 +2772,14 @@ bool CGameHandler::recruitCreatures(ObjectInstanceID objid, ObjectInstanceID dst switch(crid) { - case 146: - giveHeroNewArtifact(h, VLC->arth->artifacts[4], ArtifactPosition::MACH1); + case CreatureID::BALLISTA: + giveHeroNewArtifact(h, VLC->arth->artifacts[ArtifactID::BALLISTA], ArtifactPosition::MACH1); break; - case 147: - giveHeroNewArtifact(h, VLC->arth->artifacts[6], ArtifactPosition::MACH3); + case CreatureID::FIRST_AID_TENT: + giveHeroNewArtifact(h, VLC->arth->artifacts[ArtifactID::FIRST_AID_TENT], ArtifactPosition::MACH3); break; - case 148: - giveHeroNewArtifact(h, VLC->arth->artifacts[5], ArtifactPosition::MACH2); + case CreatureID::AMMO_CART: + giveHeroNewArtifact(h, VLC->arth->artifacts[ArtifactID::AMMO_CART], ArtifactPosition::MACH2); break; default: complain("This war machine cannot be recruited!"); @@ -2998,7 +2998,7 @@ bool CGameHandler::assembleArtifacts (ObjectInstanceID heroID, ArtifactPosition if(assemble) { - CArtifact *combinedArt = VLC->arth->artifacts.at(assembleTo); + CArtifact *combinedArt = VLC->arth->artifacts[assembleTo]; if(!combinedArt->constituents) COMPLAIN_RET("assembleArtifacts: Artifact being attempted to assemble is not a combined artifacts!"); if(!vstd::contains(destArtifact->assemblyPossibilities(hero), combinedArt)) @@ -3042,7 +3042,7 @@ bool CGameHandler::buyArtifact( ObjectInstanceID hid, ArtifactID aid ) } else if(aid < 7 && aid > 3) //war machine { - int price = VLC->arth->artifacts.at(aid)->price; + int price = VLC->arth->artifacts[aid]->price; if(( hero->getArt(ArtifactPosition(9+aid)) && complain("Hero already has this machine!")) || (gs->getPlayer(hero->getOwner())->resources.at(Res::GOLD) < price && complain("Not enough gold!"))) @@ -3053,7 +3053,7 @@ bool CGameHandler::buyArtifact( ObjectInstanceID hid, ArtifactID aid ) || ((town->hasBuilt(BuildingID::BALLISTA_YARD, ETownType::STRONGHOLD)) && aid == ArtifactID::BALLISTA)) { giveResource(hero->getOwner(),Res::GOLD,-price); - giveHeroNewArtifact(hero, VLC->arth->artifacts.at(aid), ArtifactPosition(9+aid)); + giveHeroNewArtifact(hero, VLC->arth->artifacts[aid], ArtifactPosition(9+aid)); return true; } else @@ -3110,7 +3110,7 @@ bool CGameHandler::buyArtifact(const IMarket *m, const CGHeroInstance *h, Res::E sendAndApply(&saa); - giveHeroNewArtifact(h, VLC->arth->artifacts.at(aid), ArtifactPosition::FIRST_AVAILABLE); + giveHeroNewArtifact(h, VLC->arth->artifacts[aid], ArtifactPosition::FIRST_AVAILABLE); return true; } @@ -3962,7 +3962,7 @@ void CGameHandler::playerMessage( PlayerColor player, const std::string &message sm.absolute = true; if(!h->hasSpellbook()) //hero doesn't have spellbook - giveHeroNewArtifact(h, VLC->arth->artifacts.at(0), ArtifactPosition::SPELLBOOK); //give spellbook + giveHeroNewArtifact(h, VLC->arth->artifacts[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); //give spellbook sendAndApply(&sm); } @@ -4015,18 +4015,18 @@ void CGameHandler::playerMessage( PlayerColor player, const std::string &message if(!hero) return; if(!hero->getArt(ArtifactPosition::MACH1)) - giveHeroNewArtifact(hero, VLC->arth->artifacts.at(4), ArtifactPosition::MACH1); + giveHeroNewArtifact(hero, VLC->arth->artifacts[ArtifactID::BALLISTA], ArtifactPosition::MACH1); if(!hero->getArt(ArtifactPosition::MACH2)) - giveHeroNewArtifact(hero, VLC->arth->artifacts.at(5), ArtifactPosition::MACH2); + giveHeroNewArtifact(hero, VLC->arth->artifacts[ArtifactID::AMMO_CART], ArtifactPosition::MACH2); if(!hero->getArt(ArtifactPosition::MACH3)) - giveHeroNewArtifact(hero, VLC->arth->artifacts.at(6), ArtifactPosition::MACH3); + giveHeroNewArtifact(hero, VLC->arth->artifacts[ArtifactID::FIRST_AID_TENT], ArtifactPosition::MACH3); } else if (message == "vcmiforgeofnoldorking") //hero gets all artifacts except war machines, spell scrolls and spell book { CGHeroInstance *hero = gs->getHero(currObj); if(!hero) return; for (int g = 7; g < VLC->arth->artifacts.size(); ++g) //including artifacts from mods - giveHeroNewArtifact(hero, VLC->arth->artifacts.at(g), ArtifactPosition::PRE_FIRST); + giveHeroNewArtifact(hero, VLC->arth->artifacts[g], ArtifactPosition::PRE_FIRST); } else if(message == "vcmiglorfindel") //selected hero gains a new level { @@ -4900,14 +4900,14 @@ bool CGameHandler::dig( const CGHeroInstance *h ) if(gs->map->grailPos == h->getPosition()) { iw.text.addTxt(MetaString::GENERAL_TXT, 58); //"Congratulations! After spending many hours digging here, your hero has uncovered the " - iw.text.addTxt(MetaString::ART_NAMES, 2); + iw.text.addTxt(MetaString::ART_NAMES, ArtifactID::GRAIL); iw.soundID = soundBase::ULTIMATEARTIFACT; - giveHeroNewArtifact(h, VLC->arth->artifacts.at(2), ArtifactPosition::PRE_FIRST); //give grail + giveHeroNewArtifact(h, VLC->arth->artifacts[ArtifactID::GRAIL], ArtifactPosition::PRE_FIRST); //give grail sendAndApply(&iw); iw.soundID = soundBase::invalid; iw.text.clear(); - iw.text.addTxt(MetaString::ART_DESCR, 2); + iw.text.addTxt(MetaString::ART_DESCR, ArtifactID::GRAIL); sendAndApply(&iw); } else From e645b46aed8f58042d3ee9b812d68559b471a1c8 Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Sat, 7 Nov 2015 11:35:02 +0300 Subject: [PATCH 12/20] Revert "Merge pull request #124 from vcmi/issue/1372" This reverts commit da01af319b8e803bc737587fdf88b83bf412f2d1, reversing changes made to 8b6b4e2e0b81169444a1879b3ac505ca346925f3. --- client/battle/CBattleInterface.cpp | 15 +--- lib/GameConstants.cpp | 1 - lib/GameConstants.h | 1 - lib/NetPacksLib.cpp | 2 +- server/CGameHandler.cpp | 108 +++++++---------------------- server/CGameHandler.h | 9 +-- 6 files changed, 31 insertions(+), 105 deletions(-) diff --git a/client/battle/CBattleInterface.cpp b/client/battle/CBattleInterface.cpp index c1ea5ec45..452b41d76 100644 --- a/client/battle/CBattleInterface.cpp +++ b/client/battle/CBattleInterface.cpp @@ -2163,15 +2163,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType) break; case RISE_DEMONS: if (shere && ourStack && !shere->alive()) - { - if(!(shere->hasBonusOfType(Bonus::UNDEAD) - || shere->hasBonusOfType(Bonus::NON_LIVING) - || vstd::contains(shere->state, EBattleStackState::SUMMONED) - || vstd::contains(shere->state, EBattleStackState::CLONED) - || shere->hasBonusOfType(Bonus::SIEGE_WEAPON) - )) - legalAction = true; - } + legalAction = true; break; } if (legalAction) @@ -2328,10 +2320,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType) break; case RISE_DEMONS: cursorType = ECursor::SPELLBOOK; - realizeAction = [=] - { - giveCommand(Battle::DAEMON_SUMMONING, myNumber, activeStack->ID); - }; + realizeAction = [=]{ giveCommand(Battle::DAEMON_SUMMONING, myNumber, activeStack->ID); }; break; case CATAPULT: cursorFrame = ECursor::COMBAT_SHOOT_CATAPULT; diff --git a/lib/GameConstants.cpp b/lib/GameConstants.cpp index 3b5acc577..9a48b476f 100644 --- a/lib/GameConstants.cpp +++ b/lib/GameConstants.cpp @@ -19,7 +19,6 @@ #include "spells/CSpellHandler.h" const SlotID SlotID::COMMANDER_SLOT_PLACEHOLDER = SlotID(-2); -const SlotID SlotID::SUMMONED_SLOT_PLACEHOLDER = SlotID(255); const PlayerColor PlayerColor::CANNOT_DETERMINE = PlayerColor(253); const PlayerColor PlayerColor::UNFLAGGABLE = PlayerColor(254); const PlayerColor PlayerColor::NEUTRAL = PlayerColor(255); diff --git a/lib/GameConstants.h b/lib/GameConstants.h index 98e344d6b..05d3128eb 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -216,7 +216,6 @@ class SlotID : public BaseForID friend class CNonConstInfoCallback; DLL_LINKAGE static const SlotID COMMANDER_SLOT_PLACEHOLDER; - DLL_LINKAGE static const SlotID SUMMONED_SLOT_PLACEHOLDER; ///curB->generateNewStack(csbd, attacker, SlotID::SUMMONED_SLOT_PLACEHOLDER, pos); //TODO: netpacks? + CStack * addedStack = gs->curB->generateNewStack(csbd, attacker, SlotID(255), pos); //TODO: netpacks? if (summoned) addedStack->state.insert(EBattleStackState::SUMMONED); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index ba81d0f77..88f43533e 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -651,8 +651,8 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer sendAndApply(&cs); } - cab1.updateArmy(this); - cab2.updateArmy(this); //take casualties after battle is deleted + cab1.takeFromArmy(this); + cab2.takeFromArmy(this); //take casualties after battle is deleted //if one hero has lost we will erase him if(battleResult.data->winner!=0 && hero1) @@ -3848,16 +3848,18 @@ bool CGameHandler::makeBattleAction( BattleAction &ba ) //TODO: From Strategija: //Summon Demon is a level 2 spell. { + StartAction start_action(ba); + sendAndApply(&start_action); + const CStack *summoner = gs->curB->battleGetStackByID(ba.stackNumber), *destStack = gs->curB->battleGetStackByPos(ba.destinationTile, false); - CreatureID summonedType(summoner->getBonusLocalFirst(Selector::type(Bonus::DAEMON_SUMMONING))->subtype);//in case summoner can summon more than one type of monsters... scream! BattleStackAdded bsa; bsa.attacker = summoner->attackerOwned; - bsa.creID = summonedType; + bsa.creID = CreatureID(summoner->getBonusLocalFirst(Selector::type(Bonus::DAEMON_SUMMONING))->subtype); //in case summoner can summon more than one type of monsters... scream! ui64 risedHp = summoner->count * summoner->valOfBonuses(Bonus::DAEMON_SUMMONING, bsa.creID.toEnum()); - ui64 targetHealth = destStack->getCreature()->MaxHealth() * destStack->baseAmount;//todo: ignore AGE effect + ui64 targetHealth = destStack->getCreature()->MaxHealth() * destStack->baseAmount; ui64 canRiseHp = std::min(targetHealth, risedHp); ui32 canRiseAmount = canRiseHp / VLC->creh->creatures.at(bsa.creID)->MaxHealth(); @@ -3869,9 +3871,6 @@ bool CGameHandler::makeBattleAction( BattleAction &ba ) if (bsa.amount) //there's rare possibility single creature cannot rise desired type { - StartAction start_action(ba); - sendAndApply(&start_action); - BattleStacksRemoved bsr; //remove body bsr.stackIDs.insert(destStack->ID); sendAndApply(&bsr); @@ -3883,9 +3882,9 @@ bool CGameHandler::makeBattleAction( BattleAction &ba ) ssp.val = -1; ssp.absolute = false; sendAndApply(&ssp); - - sendAndApply(&end_action); } + + sendAndApply(&end_action); break; } case Battle::MONSTER_SPELL: @@ -5805,52 +5804,13 @@ void CGameHandler::duelFinished() return; } -CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance * _army, BattleInfo *bat): - army(_army) +CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat) { heroWithDeadCommander = ObjectInstanceID(); PlayerColor color = army->tempOwner; if(color == PlayerColor::UNFLAGGABLE) color = PlayerColor::NEUTRAL; - - auto killStack = [&, this](const SlotID slot, const CStackInstance * instance) - { - StackLocation sl(army, slot); - newStackCounts.push_back(TStackAndItsNewCount(sl, 0)); - if(nullptr == instance) - return; - auto c = dynamic_cast (instance); - if (c) //switch commander status to dead - { - auto h = dynamic_cast (army); - if (h && h->commander == c) - heroWithDeadCommander = army->id; //TODO: unify commander handling - } - }; - - //1. Find removed stacks. - for(const auto & slotInfo : army->stacks) - { - const SlotID slot = slotInfo.first; - const CStackInstance * instance = slotInfo.second; - - if(nullptr != instance)//just in case - { - bool found = false; - for(const CStack * sta : bat->stacks) - { - if(sta->base == instance) - { - found = true; - break; - } - } - //stack in this slot was removed == it is dead - if(!found) - killStack(slot, instance); - } - } for(CStack *st : bat->stacks) { @@ -5862,7 +5822,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance * _army, Battl //FIXME: this info is also used in BattleInfo::calculateCasualties, refactor st->count = std::max (0, st->count - st->resurrected); - if (!st->count && !st->base) //we can imagine stacks of war machines that are not spawned by artifacts? + if (!st->count && !st->base) //we can imagine stacks of war mahcines that are not spawned by artifacts? { auto warMachine = VLC->arth->creatureToMachineID(st->type->idNumber); if (warMachine != ArtifactID::NONE) @@ -5872,32 +5832,29 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance * _army, Battl removedWarMachines.push_back (ArtifactLocation(hero, hero->getArtPos(warMachine, true))); } } - - if(army->slotEmpty(st->slot)) + + if(!army->slotEmpty(st->slot) && st->count < army->getStackCount(st->slot)) { - if(st->slot == SlotID::SUMMONED_SLOT_PLACEHOLDER && !vstd::contains(st->state, EBattleStackState::SUMMONED) && st->alive() && st->count > 0) - { - //this stack was permanently summoned - const CreatureID summonedType = st->type->idNumber; - summoned[summonedType] += st->count; - } + StackLocation sl(army, st->slot); + if(st->alive()) + newStackCounts.push_back(std::pair(sl, st->count)); + else + newStackCounts.push_back(std::pair(sl, 0)); } - else + if (st->base && !st->count) { - if(st->count == 0 || !st->alive()) + auto c = dynamic_cast (st->base); + if (c) //switch commander status to dead { - killStack(st->slot, st->base); - } - else if(st->count < army->getStackCount(st->slot)) - { - StackLocation sl(army, st->slot); - newStackCounts.push_back(TStackAndItsNewCount(sl, st->count)); + auto h = dynamic_cast (army); + if (h && h->commander == c) + heroWithDeadCommander = army->id; //TODO: unify commander handling } } } } -void CasualtiesAfterBattle::updateArmy(CGameHandler *gh) +void CasualtiesAfterBattle::takeFromArmy(CGameHandler *gh) { for(TStackAndItsNewCount &ncount : newStackCounts) { @@ -5906,21 +5863,6 @@ void CasualtiesAfterBattle::updateArmy(CGameHandler *gh) else gh->eraseStack(ncount.first, true); } - for(auto summoned_iter : summoned) - { - SlotID slot = army->getSlotFor(summoned_iter.first); - if(slot.validSlot()) - { - StackLocation location(army, slot); - gh->addToSlot(location, summoned_iter.first.toCreature(), summoned_iter.second); - } - else - { - //even if it will be possible to summon anything permanently it should be checked for free slot - //necromancy is handled separately - gh->complain("No free slot to put summoned creature"); - } - } for (auto al : removedWarMachines) { gh->removeArtifact(al); diff --git a/server/CGameHandler.h b/server/CGameHandler.h index bc2a336a7..acf1698a2 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -71,16 +71,13 @@ public: struct CasualtiesAfterBattle { typedef std::pair TStackAndItsNewCount; - typedef std::map TSummoned; enum {ERASE = -1}; - const CArmedInstance * army; std::vector newStackCounts; std::vector removedWarMachines; - TSummoned summoned; - ObjectInstanceID heroWithDeadCommander; //TODO: unify stack locations + ObjectInstanceID heroWithDeadCommander; //TODO: unify stack loactions - CasualtiesAfterBattle(const CArmedInstance * _army, BattleInfo *bat); - void updateArmy(CGameHandler *gh); + CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat); + void takeFromArmy(CGameHandler *gh); }; class CGameHandler : public IGameCallback, CBattleInfoCallback From 7eebcb9d60922ad2633cd4a4866abb57877292ec Mon Sep 17 00:00:00 2001 From: ArseniyShestakov Date: Sat, 7 Nov 2015 11:46:58 +0300 Subject: [PATCH 13/20] Artifacts: replace few more ints by ArtifactID --- lib/CGameState.cpp | 2 +- lib/GameConstants.h | 1 + lib/mapObjects/CGHeroInstance.cpp | 4 ++-- lib/mapping/MapFormatH3M.cpp | 3 +-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index 3b4217ac5..57bb16597 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -907,7 +907,7 @@ void CGameState::initDuel() if(!ss.spells.empty()) { - h->putArtifact(ArtifactPosition::SPELLBOOK, CArtifactInstance::createNewArtifactInstance(0)); + h->putArtifact(ArtifactPosition::SPELLBOOK, CArtifactInstance::createNewArtifactInstance(ArtifactID::SPELLBOOK)); boost::copy(ss.spells, std::inserter(h->spells, h->spells.begin())); } diff --git a/lib/GameConstants.h b/lib/GameConstants.h index 05d3128eb..dfbc789e8 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -824,6 +824,7 @@ public: FIRST_AID_TENT = 6, //CENTAUR_AXE = 7, //BLACKSHARD_OF_THE_DEAD_KNIGHT = 8, + ARMAGEDDONS_BLADE = 128, TITANS_THUNDER = 135, //CORNUCOPIA = 140, //FIXME: the following is only true if WoG is enabled. Otherwise other mod artifacts will take these slots. diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 3042e35df..c50055bcc 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -261,10 +261,10 @@ void CGHeroInstance::initHero() spells -= SpellID::PRESET; if(!getArt(ArtifactPosition::MACH4) && !getArt(ArtifactPosition::SPELLBOOK) && type->haveSpellBook) //no catapult means we haven't read pre-existent set -> use default rules for spellbook - putArtifact(ArtifactPosition::SPELLBOOK, CArtifactInstance::createNewArtifactInstance(0)); + putArtifact(ArtifactPosition::SPELLBOOK, CArtifactInstance::createNewArtifactInstance(ArtifactID::SPELLBOOK)); if(!getArt(ArtifactPosition::MACH4)) - putArtifact(ArtifactPosition::MACH4, CArtifactInstance::createNewArtifactInstance(3)); //everyone has a catapult + putArtifact(ArtifactPosition::MACH4, CArtifactInstance::createNewArtifactInstance(ArtifactID::CATAPULT)); //everyone has a catapult if(portrait < 0 || portrait == 255) portrait = type->imageIndex; diff --git a/lib/mapping/MapFormatH3M.cpp b/lib/mapping/MapFormatH3M.cpp index eba380123..1831e373a 100644 --- a/lib/mapping/MapFormatH3M.cpp +++ b/lib/mapping/MapFormatH3M.cpp @@ -668,8 +668,7 @@ void CMapLoaderH3M::readAllowedArtifacts() } if (map->version == EMapFormat::ROE) { - // Armageddon's Blade - map->allowedArtifact[128] = false; + map->allowedArtifact[ArtifactID::ARMAGEDDONS_BLADE] = false; } } From a49950e958d896c02f20cb2332ee748a1a0ca356 Mon Sep 17 00:00:00 2001 From: ArseniyShestakov Date: Sun, 8 Nov 2015 22:16:58 +0300 Subject: [PATCH 14/20] Fix 2292. Fix chat on adventure map, increase maxOutputPerLine --- client/CMT.cpp | 10 ++++++---- client/NetPacksClient.cpp | 6 +++--- client/windows/CAdvmapInterface.cpp | 4 ++-- config/resolutions.json | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/client/CMT.cpp b/client/CMT.cpp index 318c60c9d..53d154ffb 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -529,8 +529,9 @@ void processCommand(const std::string &message) std::string cn; //command name readed >> cn; - if(LOCPLINT && LOCPLINT->cingconsole) - LOCPLINT->cingconsole->print(message); +// Check mantis issue 2292 for details +// if(LOCPLINT && LOCPLINT->cingconsole) +// LOCPLINT->cingconsole->print(message); if(ermInteractiveMode) { @@ -789,11 +790,12 @@ void processCommand(const std::string &message) Settings session = settings.write["session"]; session["autoSkip"].Bool() = !session["autoSkip"].Bool(); } - else if(client && client->serv && client->serv->connected && LOCPLINT) //send to server + // Check mantis issue 2292 for details +/* else if(client && client->serv && client->serv->connected && LOCPLINT) //send to server { boost::unique_lock un(*LOCPLINT->pim); LOCPLINT->cb->sendMessage(message); - } + }*/ } //plays intro, ends when intro is over or button has been pressed (handles events) diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 5453fbc22..eb95d44b9 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -819,10 +819,10 @@ void SaveGame::applyCl(CClient *cl) void PlayerMessage::applyCl(CClient *cl) { - std::ostringstream str; - str << "Player "<< player <<" sends a message: " << text; + logNetwork->debugStream() << "Player "<< player <<" sends a message: " << text; - logNetwork->debugStream() << str.str(); + std::ostringstream str; + str << cl->getPlayer(player)->nodeName() <<": " << text; if(LOCPLINT) LOCPLINT->cingconsole->print(str.str()); } diff --git a/client/windows/CAdvmapInterface.cpp b/client/windows/CAdvmapInterface.cpp index e1b96e049..2f9958a9c 100644 --- a/client/windows/CAdvmapInterface.cpp +++ b/client/windows/CAdvmapInterface.cpp @@ -881,7 +881,7 @@ void CAdvMapInt::showAll(SDL_Surface * to) statusbar.show(to); - LOCPLINT->cingconsole->showAll(to); + LOCPLINT->cingconsole->show(to); } bool CAdvMapInt::isHeroSleeping(const CGHeroInstance *hero) @@ -958,7 +958,7 @@ void CAdvMapInt::show(SDL_Surface * to) for(int i=0;i<4;i++) blitAt(gems[i]->ourImages[LOCPLINT->playerID.getNum()].bitmap,ADVOPT.gemX[i],ADVOPT.gemY[i],to); updateScreen=false; - LOCPLINT->cingconsole->showAll(to); + LOCPLINT->cingconsole->show(to); } else if (terrain.needsAnimUpdate()) { diff --git a/config/resolutions.json b/config/resolutions.json index 1917a62da..e0e83be0b 100644 --- a/config/resolutions.json +++ b/config/resolutions.json @@ -3,7 +3,7 @@ [ { "resolution": { "x": 800, "y": 600 }, - "InGameConsole": { "maxInputPerLine": 60, "maxOutputPerLine": 39 }, + "InGameConsole": { "maxInputPerLine": 60, "maxOutputPerLine": 60 }, "AdvMap": { "x": 7, "y": 7, "width": 594, "height": 546, "smoothMove": 1, "puzzleSepia": 1, "objectFading" : 1, "screenFading" : 1 }, "InfoBox": { "x": 605, "y": 389 }, "gem0": { "x": 6, "y": 508, "graphic": "agemLL.def" }, From 866a0a1fc021f8131796dbaa9865b63bcd66d68f Mon Sep 17 00:00:00 2001 From: ArseniyShestakov Date: Sun, 8 Nov 2015 23:02:59 +0300 Subject: [PATCH 15/20] VCAI: little improvement for 2a59cb619137cb443adce6aba009ecf37a6a57da --- AI/VCAI/VCAI.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index dfa906580..399d1a5ac 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -3372,7 +3372,8 @@ int3 SectorMap::findFirstVisitableTile (HeroPtr h, crint3 dst) while(curtile != h->visitablePos()) { auto topObj = cb->getTopObj(curtile); - if (topObj && topObj->ID == Obj::HERO && h->tempOwner == topObj->tempOwner && topObj != h.h) + if(topObj && topObj->ID == Obj::HERO && topObj != h.h && + cb->getPlayerRelations(h->tempOwner, topObj->tempOwner) != PlayerRelations::ENEMIES) { logAi->warnStream() << ("Another allied hero stands in our way"); return ret; From 74198a537b2dddac062d5bcaf167da87cfa0a087 Mon Sep 17 00:00:00 2001 From: ArseniyShestakov Date: Mon, 9 Nov 2015 00:54:59 +0300 Subject: [PATCH 16/20] CGameHandler::setOwner: fix InfoWindow text on last town loss --- server/CGameHandler.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 88f43533e..fb649b1ac 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -1961,7 +1961,8 @@ void CGameHandler::setOwner(const CGObjectInstance * obj, PlayerColor owner) { InfoWindow iw; iw.player = oldOwner; - iw.text.addTxt (MetaString::GENERAL_TXT, 6); //%s, you have lost your last town. If you do not conquer another town in the next week, you will be eliminated. + iw.text.addTxt(MetaString::GENERAL_TXT, 6); //%s, you have lost your last town. If you do not conquer another town in the next week, you will be eliminated. + iw.text.addReplacement(MetaString::COLOR, oldOwner.getNum()); sendAndApply(&iw); } } From 5bfbd8526bfd7b68ac518d1dca9255a70aa99fc1 Mon Sep 17 00:00:00 2001 From: ArseniyShestakov Date: Mon, 9 Nov 2015 14:18:36 +0300 Subject: [PATCH 17/20] Bonus system: fix N_DAYS bonus duration --- lib/HeroBonus.cpp | 18 ++++++++++++++++++ lib/HeroBonus.h | 1 + lib/NetPacksLib.cpp | 1 + 3 files changed, 20 insertions(+) diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index 0380d0144..765d6dc46 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -763,6 +763,24 @@ void CBonusSystemNode::popBonuses(const CSelector &s) child->popBonuses(s); } +void CBonusSystemNode::updateBonuses(const CSelector &s) +{ + BonusList bl; + exportedBonuses.getBonuses(bl, s); + for(Bonus *b : bl) + { + if(b->duration & Bonus::N_DAYS) + { + b->turnsRemain--; + if(b->turnsRemain <= 0) + removeBonus(b); + } + } + + for(CBonusSystemNode *child : children) + child->updateBonuses(s); +} + void CBonusSystemNode::addNewBonus(Bonus *b) { assert(!vstd::contains(exportedBonuses,b)); diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index 75f1b956c..f930f63e0 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -686,6 +686,7 @@ public: //bool isLimitedOnUs(Bonus *b) const; //if bonus should be removed from list acquired from this node void popBonuses(const CSelector &s); + void updateBonuses(const CSelector &s); virtual std::string bonusToString(const Bonus *bonus, bool description) const {return "";}; //description or bonus name virtual std::string nodeName() const; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index ede41bd8b..a298b0641 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -1026,6 +1026,7 @@ DLL_LINKAGE void NewTurn::applyGs( CGameState *gs ) if(gs->getDate(Date::DAY_OF_WEEK) == 1) //new week gs->globalEffects.popBonuses(Bonus::OneWeek); //works for children -> all game objs + gs->globalEffects.updateBonuses(Bonus::NDays); //TODO not really a single root hierarchy, what about bonuses placed elsewhere? [not an issue with H3 mechanics but in the future...] for(CGTownInstance* t : gs->map->towns) From ee1c5e452f39bfe227c7aaffc5c5c0375877b5ba Mon Sep 17 00:00:00 2001 From: ArseniyShestakov Date: Mon, 9 Nov 2015 15:01:58 +0300 Subject: [PATCH 18/20] Bonus system: add CWillLastDays selector --- lib/HeroBonus.cpp | 1 + lib/HeroBonus.h | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index 765d6dc46..e9ac989a8 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -1201,6 +1201,7 @@ namespace Selector DLL_LINKAGE CSelectFieldEqual sourceType(&Bonus::source); DLL_LINKAGE CSelectFieldEqual effectRange(&Bonus::effectRange); DLL_LINKAGE CWillLastTurns turns; + DLL_LINKAGE CWillLastDays days; DLL_LINKAGE CSelectFieldAny anyRange(&Bonus::effectRange); CSelector DLL_LINKAGE typeSubtype(Bonus::BonusType Type, TBonusSubtype Subtype) diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index f930f63e0..188442ff9 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -821,6 +821,31 @@ public: } }; +class DLL_LINKAGE CWillLastDays +{ +public: + int daysRequested; + + bool operator()(const Bonus *bonus) const + { + if(daysRequested <= 0) + return true; + else if(bonus->duration & Bonus::ONE_DAY) + return false; + else if(bonus->duration & Bonus::N_DAYS) + { + return bonus->turnsRemain > daysRequested; + } + + return false; // TODO: ONE_WEEK need support for turnsRemain, but for now we'll exclude all unhandled durations + } + CWillLastDays& operator()(const int &setVal) + { + daysRequested = setVal; + return *this; + } +}; + //Stores multiple limiters. If any of them fails -> bonus is dropped. class DLL_LINKAGE LimiterList : public ILimiter { @@ -959,6 +984,7 @@ namespace Selector extern DLL_LINKAGE CSelectFieldEqual sourceType; extern DLL_LINKAGE CSelectFieldEqual effectRange; extern DLL_LINKAGE CWillLastTurns turns; + extern DLL_LINKAGE CWillLastDays days; extern DLL_LINKAGE CSelectFieldAny anyRange; CSelector DLL_LINKAGE typeSubtype(Bonus::BonusType Type, TBonusSubtype Subtype); From 7f0b0bd1b5daddbb4809ab39ff7340ee7d29a37d Mon Sep 17 00:00:00 2001 From: ArseniyShestakov Date: Mon, 9 Nov 2015 15:48:07 +0300 Subject: [PATCH 19/20] Bonus system: use updateBonuses in battleTurnPasseed --- lib/HeroBonus.cpp | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index e9ac989a8..9b89111db 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -769,12 +769,9 @@ void CBonusSystemNode::updateBonuses(const CSelector &s) exportedBonuses.getBonuses(bl, s); for(Bonus *b : bl) { - if(b->duration & Bonus::N_DAYS) - { - b->turnsRemain--; - if(b->turnsRemain <= 0) - removeBonus(b); - } + b->turnsRemain--; + if(b->turnsRemain <= 0) + removeBonus(b); } for(CBonusSystemNode *child : children) @@ -968,18 +965,7 @@ void CBonusSystemNode::getRedDescendants(TNodes &out) void CBonusSystemNode::battleTurnPassed() { - BonusList bonusesCpy = exportedBonuses; //copy, because removing bonuses invalidates iters - for (auto & elem : bonusesCpy) - { - Bonus *b = elem; - - if(b->duration & Bonus::N_TURNS) - { - b->turnsRemain--; - if(b->turnsRemain <= 0) - removeBonus(b); - } - } + updateBonuses(Bonus::NTurns); } void CBonusSystemNode::exportBonus(Bonus * b) From 96897acc46d51f7e4b9c37ec708aba41975ece25 Mon Sep 17 00:00:00 2001 From: ArseniyShestakov Date: Mon, 9 Nov 2015 19:05:22 +0300 Subject: [PATCH 20/20] CWillLastDays: add condition for permanent durations Accidentally missed them in pull request --- lib/HeroBonus.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index 188442ff9..a95e2c9b6 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -832,6 +832,8 @@ public: return true; else if(bonus->duration & Bonus::ONE_DAY) return false; + else if(bonus->duration & Bonus::PERMANENT || bonus->duration & Bonus::ONE_BATTLE) + return true; else if(bonus->duration & Bonus::N_DAYS) { return bonus->turnsRemain > daysRequested;