浏览代码

Partial support for splitting neutral stacks. Can't go further until interface is fixed.

DjWarmonger 14 年之前
父节点
当前提交
57d292ba67
共有 3 个文件被更改,包括 81 次插入2 次删除
  1. 13 1
      lib/CCreatureSet.cpp
  2. 1 0
      lib/CCreatureSet.h
  3. 67 1
      lib/CObjectHandler.cpp

+ 13 - 1
lib/CCreatureSet.cpp

@@ -77,6 +77,18 @@ TSlot CCreatureSet::getSlotFor(const CCreature *c, ui32 slotsAmount/*=ARMY_SIZE*
 	return -1; //no slot available
 }
 
+TSlot CCreatureSet::getFreeSlot(ui32 slotsAmount/*=ARMY_SIZE*/) const
+{
+	for (ui32 i = 0; i < slotsAmount; i++)
+	{
+		if(stacks.find(i) == stacks.end())
+		{
+			return i; //return first free slot
+		}
+	}
+	return -1; //no slot available
+}
+
 int CCreatureSet::getStackCount(TSlot slot) const
 {
 	TSlots::const_iterator i = stacks.find(slot);
@@ -227,7 +239,7 @@ void CCreatureSet::setFormation(bool tight)
 void CCreatureSet::setStackCount(TSlot slot, TQuantity count)
 {
 	assert(hasStackAtSlot(slot));
-	assert(count > 0);
+	assert(stacks[slot]->count + count > 0);
 	if (STACK_EXP && count > stacks[slot]->count)
 		stacks[slot]->experience *= (count/(float)stacks[slot]->count);
 	stacks[slot]->count = count;

+ 1 - 0
lib/CCreatureSet.h

@@ -138,6 +138,7 @@ public:
 	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
+	TSlot getFreeSlot(ui32 slotsAmount=ARMY_SIZE) const;
 	bool mergableStacks(std::pair<TSlot, TSlot> &out, TSlot preferable = -1) const; //looks for two same stacks, returns slot positions;
 	bool validTypes(bool allowUnrandomized = false) const; //checks if all types of creatures are set properly
 	bool slotEmpty(TSlot slot) const;

+ 67 - 1
lib/CObjectHandler.cpp

@@ -2852,7 +2852,7 @@ void CTownBonus::onHeroVisit (const CGHeroInstance * h) const
 const std::string & CGCreature::getHoverText() const
 {
 	MetaString ms;
-	int pom = stacks.find(0)->second->getQuantityID();
+	int pom = stacks.begin()->second->getQuantityID();
 	pom = 174 + 3*pom + 1;
 	ms << std::pair<ui8,ui32>(6,pom) << " " << std::pair<ui8,ui32>(7,subID);
 	ms.toString(hoverName);
@@ -3131,7 +3131,73 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co
 
 void CGCreature::fight( const CGHeroInstance *h ) const
 {
+	//split stacks
+	int totalCount; //TODO: multiple creature types in a stack?
+	int basicType = stacks.begin()->second->type->idNumber;
+
+	float relativePower = ((float)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 stackSize;
+	TSlot sourceSlot = stacks.begin()->first;
+	TSlot destSlot;
+	for (int stacksLeft = stacksCount; stacksLeft > 1; --stacksLeft)
+	{
+		stackSize = stacks.begin()->second->count / stacksLeft;
+		if (stackSize)
+		{
+			if ((destSlot = getFreeSlot()) > -1)
+				cb->moveStack(StackLocation(this, sourceSlot), StackLocation(this, destSlot), stackSize);
+			else
+			{
+				tlog2 <<"Warning! Not enough empty slots to split stack!";
+				break;
+			}
+		}
+		else break;
+	}
+	if (stacksCount > 1)
+	{
+		if (rand()%100 > 50) //upgrade
+		{
+			TSlot slotId = (stacks.size() / 2);
+			if(ui32 upgradesSize = getStack(slotId).type->upgrades.size())
+			{
+				std::set<TCreature>::const_iterator it = getStack(slotId).type->upgrades.begin(); //pick random in case there are more
+				std::advance (it, rand() % upgradesSize);
+				cb->changeStackType(StackLocation(this, slotId), VLC->creh->creatures[*it]);
+			}
+		}
+	}
+
 	cb->startBattleI(h, this, boost::bind(&CGCreature::endBattle,this,_1));
+
+	//stacks.clear();
+	//stacks.insert(
 }
 
 void CGCreature::flee( const CGHeroInstance * h ) const