Selaa lähdekoodia

Correct handling of merging & moving stacks with experience.

DjWarmonger 14 vuotta sitten
vanhempi
sitoutus
15d80d040f
3 muutettua tiedostoa jossa 46 lisäystä ja 7 poistoa
  1. 17 2
      lib/CCreatureSet.cpp
  2. 2 0
      lib/CCreatureSet.h
  3. 27 5
      lib/NetPacksLib.cpp

+ 17 - 2
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<TSlot, TSlot> &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()
 {

+ 2 - 0
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

+ 27 - 5
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));
 		}
 	}
 }