From 15d80d040f7ef8d85a6a4167800e9c6cee7bce46 Mon Sep 17 00:00:00 2001 From: DjWarmonger Date: Sun, 27 Mar 2011 09:31:14 +0000 Subject: [PATCH] Correct handling of merging & moving stacks with experience. --- lib/CCreatureSet.cpp | 19 +++++++++++++++++-- lib/CCreatureSet.h | 2 ++ lib/NetPacksLib.cpp | 32 +++++++++++++++++++++++++++----- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/lib/CCreatureSet.cpp b/lib/CCreatureSet.cpp index 435fc62e3..7ff9b94cd 100644 --- a/lib/CCreatureSet.cpp +++ b/lib/CCreatureSet.cpp @@ -86,6 +86,16 @@ int CCreatureSet::getStackCount(TSlot slot) const return 0; //TODO? consider issuing a warning } +expType CCreatureSet::getStackExperience(TSlot slot) const +{ + TSlots::const_iterator i = stacks.find(slot); + if (i != stacks.end()) + return i->second->experience; + else + return 0; //TODO? consider issuing a warning +} + + bool CCreatureSet::mergableStacks(std::pair &out, TSlot preferable /*= -1*/) const /*looks for two same stacks, returns slot positions */ { //try to match creature to our preferred stack @@ -218,8 +228,8 @@ void CCreatureSet::setStackCount(TSlot slot, TQuantity count) { assert(hasStackAtSlot(slot)); assert(count > 0); - if (STACK_EXP) - stacks[slot]->experience *= ((stacks[slot]->count + count)/(float)stacks[slot]->count); + if (STACK_EXP && count > stacks[slot]->count) + stacks[slot]->experience *= (count/(float)stacks[slot]->count); stacks[slot]->count = count; armyChanged(); } @@ -229,6 +239,11 @@ void CCreatureSet::giveStackExp(expType exp) for(TSlots::const_iterator i = stacks.begin(); i != stacks.end(); i++) i->second->giveStackExp(exp); } +void CCreatureSet::setStackExp(TSlot slot, expType exp) +{ + assert(hasStackAtSlot(slot)); + stacks[slot]->experience = exp; +} void CCreatureSet::clear() { diff --git a/lib/CCreatureSet.h b/lib/CCreatureSet.h index 1e7f93574..45b30d98e 100644 --- a/lib/CCreatureSet.h +++ b/lib/CCreatureSet.h @@ -122,6 +122,7 @@ public: CStackInstance *detachStack(TSlot slot); //removes stack from army but doesn't destroy it (so it can be moved somewhere else or safely deleted) void setStackType(TSlot slot, const CCreature *type); void giveStackExp(expType exp); + void setStackExp(TSlot slot, expType exp); //derivative void eraseStack(TSlot slot); //slot must be occupied @@ -133,6 +134,7 @@ public: const CStackInstance& getStack(TSlot slot) const; const CCreature* getCreature(TSlot slot) const; //workaround of map issue; int getStackCount (TSlot slot) const; + expType getStackExperience(TSlot slot) const; TSlot findStack(const CStackInstance *stack) const; //-1 if none TSlot getSlotFor(TCreature creature, ui32 slotsAmount=ARMY_SIZE) const; //returns -1 if no slot available TSlot getSlotFor(const CCreature *c, ui32 slotsAmount=ARMY_SIZE) const; //returns -1 if no slot available diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 9e2d4d173..842d07f8f 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -597,10 +597,20 @@ DLL_EXPORT void RebalanceStacks::applyGs( CGameState *gs ) if(const CCreature *c = dst.army->getCreature(dst.slot)) //stack at dest -> merge { assert(c == srcType); - src.army->eraseStack(src.slot); - dst.army->changeStackCount(dst.slot, count); + if (STACK_EXP) + { + ui64 totalExp = srcCount * src.army->getStackExperience(src.slot) + dst.army->getStackCount(dst.slot) * dst.army->getStackExperience(dst.slot); + src.army->eraseStack(src.slot); + dst.army->changeStackCount(dst.slot, count); + dst.army->setStackExp(dst.slot, totalExp /(dst.army->getStackCount(dst.slot))); //mean + } + else + { + src.army->eraseStack(src.slot); + dst.army->changeStackCount(dst.slot, count); + } } - else //move stack to an empty slot + else //move stack to an empty slot, no exp change needed { CStackInstance *stackDetached = src.army->detachStack(src.slot); dst.army->putStack(dst.slot, stackDetached); @@ -611,13 +621,25 @@ DLL_EXPORT void RebalanceStacks::applyGs( CGameState *gs ) if(const CCreature *c = dst.army->getCreature(dst.slot)) //stack at dest -> rebalance { assert(c == srcType); - src.army->changeStackCount(src.slot, -count); - dst.army->changeStackCount(dst.slot, count); + if (STACK_EXP) + { + ui64 totalExp = srcCount * src.army->getStackExperience(src.slot) + dst.army->getStackCount(dst.slot) * dst.army->getStackExperience(dst.slot); + src.army->changeStackCount(src.slot, -count); + dst.army->changeStackCount(dst.slot, count); + dst.army->setStackExp(dst.slot, totalExp /(src.army->getStackCount(src.slot) + dst.army->getStackCount(dst.slot))); //mean + } + else + { + src.army->changeStackCount(src.slot, -count); + dst.army->changeStackCount(dst.slot, count); + } } else //split stack to an empty slot { src.army->changeStackCount(src.slot, -count); dst.army->addToSlot(dst.slot, srcType->idNumber, count, false); + if (STACK_EXP) + dst.army->setStackExp(dst.slot, src.army->getStackExperience(src.slot)); } } }