diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp index 6249c1d3e..422edf3ba 100644 --- a/lib/mapObjects/MiscObjects.cpp +++ b/lib/mapObjects/MiscObjects.cpp @@ -200,7 +200,6 @@ void CGCreature::initObj() amount = 1; } } - formation.randomFormation = cb->gameState()->getRandomGenerator().nextInt(); temppower = stacks[SlotID(0)]->count * 1000; refusedJoining = false; @@ -367,33 +366,8 @@ void CGCreature::fight( const CGHeroInstance *h ) const int basicType = stacks.begin()->second->type->idNumber; cb->setObjProperty(id, ObjProperty::MONSTER_RESTORE_TYPE, basicType); //store info about creature stack - double relativePower = static_cast(h->getTotalStrength()) / getArmyStrength(); - int stacksCount; - //TODO: number depends on tile type - if (relativePower < 0.5) - { - stacksCount = 7; - } - else if (relativePower < 0.67) - { - stacksCount = 7; - } - else if (relativePower < 1) - { - stacksCount = 6; - } - else if (relativePower < 1.5) - { - stacksCount = 5; - } - else if (relativePower < 2) - { - stacksCount = 4; - } - else - { - stacksCount = 3; - } + int stacksCount = getNumberOfStacks(h); + SlotID sourceSlot = stacks.begin()->first; SlotID destSlot; for (int stacksLeft = stacksCount; stacksLeft > 1; --stacksLeft) @@ -413,7 +387,7 @@ void CGCreature::fight( const CGHeroInstance *h ) const } if (stacksCount > 1) { - if (formation.randomFormation % 100 < 50) //upgrade + if (containsUpgradedStack()) //upgrade { SlotID slotId = SlotID(stacks.size() / 2); const auto & upgrades = getStack(slotId).type->upgrades; @@ -489,6 +463,62 @@ void CGCreature::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) assert(0); } +bool CGCreature::containsUpgradedStack() const +{ + //source http://heroescommunity.com/viewthread.php3?TID=27539&PID=830557#focus + + float a = 2992.911117; + float b = 14174.264968; + float c = 5325.181015; + float d = 32788.727920; + + int val = std::floor (a*pos.x + b*pos.y + c*pos.z + d); + return ((val % 32768) % 100) < 50; +} + +int CGCreature::getNumberOfStacks(const CGHeroInstance *hero) const +{ + //source http://heroescommunity.com/viewthread.php3?TID=27539&PID=1266094#focus + + float strengthRatio = hero->getArmyStrength() / getArmyStrength(); + int split = 1; + + if (strengthRatio < 0.5f) + split = 7; + else if (strengthRatio < 0.67f) + split = 6; + else if (strengthRatio < 1) + split = 5; + else if (strengthRatio < 1.5f) + split = 4; + else if (strengthRatio < 2) + split = 3; + else + split = 2; + + int a = 1550811371; + int b = -935900487; + int c = 1943276003; + int d = -1120346418; + + int R1 = a * pos.x + b * pos.y + c * pos.z + d; + int R2 = R1 / 65536; + int R3 = R2 % 32768; + if (R3 < 0) + R3 += 32767; //is it ever needed if we do modulo calculus? + int R4 = R3 % 100 + 1; + + if (R4 <= 20) + split -= 1; + else if (R4 >= 80) + split += 1; + + vstd::amin(split, getStack(SlotID(0)).count); //can't divide into more stacks than creatures total + vstd::amin(split, 7); //can't have more than 7 stacks + + return split; +} + void CGMine::onHeroVisit( const CGHeroInstance * h ) const { int relations = cb->gameState()->getPlayerRelations(h->tempOwner, tempOwner); diff --git a/lib/mapObjects/MiscObjects.h b/lib/mapObjects/MiscObjects.h index c1e730e8d..bed4498c0 100644 --- a/lib/mapObjects/MiscObjects.h +++ b/lib/mapObjects/MiscObjects.h @@ -56,14 +56,17 @@ public: void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override; void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override; + //stack formation depends on position, + bool containsUpgradedStack() const; + int getNumberOfStacks(const CGHeroInstance *hero) const; struct DLL_LINKAGE formationInfo // info about merging stacks after battle back into one { si32 basicType; - ui32 randomFormation; //random seed used to determine number of stacks and is there's upgraded stack + ui8 upgrade; //random seed used to determine number of stacks and is there's upgraded stack template void serialize(Handler &h, const int version) { - h & basicType & randomFormation; + h & basicType & upgrade; } } formation;