1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-14 02:33:51 +02:00

Merge pull request #70 from vcmi/StackSplitting

Stack splitting
This commit is contained in:
DjWarmonger 2014-12-25 19:59:02 +01:00
commit 5271ca156b
3 changed files with 87 additions and 48 deletions

View File

@ -1,3 +1,8 @@
0.97 -> 0.98
BATTLES:
* Implemented OH3 stack split / upgrade formulas according to AlexSpl
0.96 -> 0.97 (Nov 01 2014) 0.96 -> 0.97 (Nov 01 2014)
GENERAL: GENERAL:
* (windows) Moved VCMI data directory from '%userprofile%\vcmi' to '%userprofile%\Documents\My Games\vcmi' * (windows) Moved VCMI data directory from '%userprofile%\vcmi' to '%userprofile%\Documents\My Games\vcmi'

View File

@ -200,7 +200,6 @@ void CGCreature::initObj()
amount = 1; amount = 1;
} }
} }
formation.randomFormation = cb->gameState()->getRandomGenerator().nextInt();
temppower = stacks[SlotID(0)]->count * 1000; temppower = stacks[SlotID(0)]->count * 1000;
refusedJoining = false; refusedJoining = false;
@ -367,60 +366,36 @@ void CGCreature::fight( const CGHeroInstance *h ) const
int basicType = stacks.begin()->second->type->idNumber; int basicType = stacks.begin()->second->type->idNumber;
cb->setObjProperty(id, ObjProperty::MONSTER_RESTORE_TYPE, basicType); //store info about creature stack cb->setObjProperty(id, ObjProperty::MONSTER_RESTORE_TYPE, basicType); //store info about creature stack
double relativePower = static_cast<double>(h->getTotalStrength()) / getArmyStrength(); int stacksCount = getNumberOfStacks(h);
int stacksCount; //source: http://heroescommunity.com/viewthread.php3?TID=27539&PID=1266335#focus
//TODO: number depends on tile type
if (relativePower < 0.5) int amount = getStackCount(SlotID(0));
{ int m = amount / stacksCount;
stacksCount = 7; int b = stacksCount * (m + 1) - amount;
} int a = stacksCount - b;
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;
}
SlotID sourceSlot = stacks.begin()->first; SlotID sourceSlot = stacks.begin()->first;
SlotID destSlot; for (int slotID = 1; slotID < a; ++slotID)
for (int stacksLeft = stacksCount; stacksLeft > 1; --stacksLeft)
{ {
int stackSize = stacks.begin()->second->count / stacksLeft; int stackSize = m + 1;
if (stackSize) cb->moveStack(StackLocation(this, sourceSlot), StackLocation(this, SlotID(slotID)), stackSize);
{
if ((destSlot = getFreeSlot()).validSlot())
cb->moveStack(StackLocation(this, sourceSlot), StackLocation(this, destSlot), stackSize);
else
{
logGlobal->warnStream() <<"Warning! Not enough empty slots to split stack!";
break;
} }
} for (int slotID = a; slotID < stacksCount; ++slotID)
else break; {
int stackSize = m;
if (slotID) //don't do this when a = 0 -> stack is single
cb->moveStack(StackLocation(this, sourceSlot), StackLocation(this, SlotID(slotID)), stackSize);
} }
if (stacksCount > 1) if (stacksCount > 1)
{ {
if (formation.randomFormation % 100 < 50) //upgrade if (containsUpgradedStack()) //upgrade
{ {
SlotID slotId = SlotID(stacks.size() / 2); SlotID slotID = SlotID(std::floor((float)stacks.size() / 2));
const auto & upgrades = getStack(slotId).type->upgrades; const auto & upgrades = getStack(slotID).type->upgrades;
if(!upgrades.empty()) if(!upgrades.empty())
{ {
auto it = RandomGeneratorUtil::nextItem(upgrades, cb->gameState()->getRandomGenerator()); auto it = RandomGeneratorUtil::nextItem(upgrades, cb->gameState()->getRandomGenerator());
cb->changeStackType(StackLocation(this, slotId), VLC->creh->creatures[*it]); cb->changeStackType(StackLocation(this, slotID), VLC->creh->creatures[*it]);
} }
} }
} }
@ -489,6 +464,62 @@ void CGCreature::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer)
assert(0); 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
double strengthRatio = (double)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 void CGMine::onHeroVisit( const CGHeroInstance * h ) const
{ {
int relations = cb->gameState()->getPlayerRelations(h->tempOwner, tempOwner); int relations = cb->gameState()->getPlayerRelations(h->tempOwner, tempOwner);

View File

@ -56,14 +56,17 @@ public:
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override; void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) 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 struct DLL_LINKAGE formationInfo // info about merging stacks after battle back into one
{ {
si32 basicType; 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 <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & basicType & randomFormation; h & basicType & upgrade;
} }
} formation; } formation;