Explorar o código

Configurable duels.

Michał W. Urbańczyk %!s(int64=15) %!d(string=hai) anos
pai
achega
ed07cfe073
Modificáronse 7 ficheiros con 195 adicións e 104 borrados
  1. 2 1
      client/CMT.cpp
  2. 46 46
      lib/CCreatureSet.cpp
  3. 4 4
      lib/CCreatureSet.h
  4. 82 28
      lib/CGameState.cpp
  5. 36 0
      lib/CGameState.h
  6. 10 10
      lib/CObjectHandler.cpp
  7. 15 15
      server/CGameHandler.cpp

+ 2 - 1
client/CMT.cpp

@@ -197,7 +197,7 @@ int main(int argc, char** argv)
 	opts.add_options()
 		("help,h", "display help and exit")
 		("version,v", "display version information and exit")
-		("battle,b", "runs game in duel mode (battle-only");
+		("battle,b", po::value<std::string>(), "runs game in duel mode (battle-only");
 
 	po::variables_map vm;
 	if(argc > 1)
@@ -280,6 +280,7 @@ int main(int argc, char** argv)
 	{
 		StartInfo *si = new StartInfo();
 		si->mode = StartInfo::DUEL;
+		si->mapname = vm["battle"].as<std::string>();
 		si->playerInfos[0].color = 0;
 		si->playerInfos[1].color = 1;
 		startGame(si);

+ 46 - 46
lib/CCreatureSet.cpp

@@ -11,8 +11,8 @@
 
 const CStackInstance &CCreatureSet::operator[](TSlot slot) const
 {
-	TSlots::const_iterator i = slots.find(slot);
-	if (i != slots.end())
+	TSlots::const_iterator i = stacks.find(slot);
+	if (i != stacks.end())
 		return *i->second;
 	else
 		throw std::string("That slot is empty!");
@@ -20,8 +20,8 @@ const CStackInstance &CCreatureSet::operator[](TSlot slot) const
 
 const CCreature* CCreatureSet::getCreature(TSlot slot) const
 {
-	TSlots::const_iterator i = slots.find(slot);
-	if (i != slots.end())
+	TSlots::const_iterator i = stacks.find(slot);
+	if (i != stacks.end())
 		return i->second->type;
 	else
 		return NULL;
@@ -41,7 +41,7 @@ bool CCreatureSet::setCreature(TSlot slot, TCreature type, TQuantity quantity) /
 		return true;
 	}
 
-	if(vstd::contains(slots, slot)) //remove old creature
+	if(vstd::contains(stacks, slot)) //remove old creature
 		eraseStack(slot);
 
 	putStack(slot, new CStackInstance(type, quantity));
@@ -56,7 +56,7 @@ TSlot CCreatureSet::getSlotFor(TCreature creature, ui32 slotsAmount/*=7*/) const
 TSlot CCreatureSet::getSlotFor(const CCreature *c, ui32 slotsAmount/*=ARMY_SIZE*/) const
 {
 	assert(c->valid());
-	for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i)
+	for(TSlots::const_iterator i=stacks.begin(); i!=stacks.end(); ++i)
 	{
 		assert(i->second->type->valid());
 		if(i->second->type == c)
@@ -66,7 +66,7 @@ TSlot CCreatureSet::getSlotFor(const CCreature *c, ui32 slotsAmount/*=ARMY_SIZE*
 	}
 	for(ui32 i=0; i<slotsAmount; i++)
 	{
-		if(slots.find(i) == slots.end())
+		if(stacks.find(i) == stacks.end())
 		{
 			return i; //return first free slot
 		}
@@ -76,8 +76,8 @@ TSlot CCreatureSet::getSlotFor(const CCreature *c, ui32 slotsAmount/*=ARMY_SIZE*
 
 int CCreatureSet::getStackCount(TSlot slot) const
 {
-	TSlots::const_iterator i = slots.find(slot);
-	if (i != slots.end())
+	TSlots::const_iterator i = stacks.find(slot);
+	if (i != stacks.end())
 		return i->second->count;
 	else
 		return 0; //TODO? consider issuing a warning
@@ -86,10 +86,10 @@ int CCreatureSet::getStackCount(TSlot slot) const
 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
-	if(preferable >= 0  &&  vstd::contains(slots, preferable))
+	if(preferable >= 0  &&  vstd::contains(stacks, preferable))
 	{
-		const CCreature *cr = slots.find(preferable)->second->type;
-		for(TSlots::const_iterator j=slots.begin(); j!=slots.end(); ++j)
+		const CCreature *cr = stacks.find(preferable)->second->type;
+		for(TSlots::const_iterator j=stacks.begin(); j!=stacks.end(); ++j)
 		{
 			if(cr == j->second->type && j->first != preferable)
 			{
@@ -100,9 +100,9 @@ bool CCreatureSet::mergableStacks(std::pair<TSlot, TSlot> &out, TSlot preferable
 		}
 	}
 
-	for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i)
+	for(TSlots::const_iterator i=stacks.begin(); i!=stacks.end(); ++i)
 	{
-		for(TSlots::const_iterator j=slots.begin(); j!=slots.end(); ++j)
+		for(TSlots::const_iterator j=stacks.begin(); j!=stacks.end(); ++j)
 		{
 			if(i->second->type == j->second->type  &&  i->first != j->first)
 			{
@@ -117,11 +117,11 @@ bool CCreatureSet::mergableStacks(std::pair<TSlot, TSlot> &out, TSlot preferable
 
 void CCreatureSet::sweep()
 {
-	for(TSlots::iterator i=slots.begin(); i!=slots.end(); ++i)
+	for(TSlots::iterator i=stacks.begin(); i!=stacks.end(); ++i)
 	{
 		if(!i->second->count)
 		{
-			slots.erase(i);
+			stacks.erase(i);
 			sweep();
 			break;
 		}
@@ -132,7 +132,7 @@ void CCreatureSet::addToSlot(TSlot slot, TCreature cre, TQuantity count, bool al
 {
 	const CCreature *c = VLC->creh->creatures[cre];
 
-	if(!vstd::contains(slots, slot))
+	if(!vstd::contains(stacks, slot))
 	{
 		setCreature(slot, cre, count);
 	}
@@ -150,7 +150,7 @@ void CCreatureSet::addToSlot(TSlot slot, CStackInstance *stack, bool allowMergin
 {
 	assert(stack->valid(true));
 
-	if(!vstd::contains(slots, slot))
+	if(!vstd::contains(stacks, slot))
 	{
 		putStack(slot, stack);
 	}
@@ -166,7 +166,7 @@ void CCreatureSet::addToSlot(TSlot slot, CStackInstance *stack, bool allowMergin
 
 bool CCreatureSet::validTypes(bool allowUnrandomized /*= false*/) const
 {
-	for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i)
+	for(TSlots::const_iterator i=stacks.begin(); i!=stacks.end(); ++i)
 	{
 		if(!i->second->valid(allowUnrandomized))
 			return false;
@@ -176,7 +176,7 @@ bool CCreatureSet::validTypes(bool allowUnrandomized /*= false*/) const
 
 bool CCreatureSet::slotEmpty(TSlot slot) const
 {
-	return !vstd::contains(slots, slot);
+	return !vstd::contains(stacks, slot);
 }
 
 bool CCreatureSet::needsLastStack() const
@@ -187,7 +187,7 @@ bool CCreatureSet::needsLastStack() const
 int CCreatureSet::getArmyStrength() const
 {
 	int ret = 0;
-	for(TSlots::const_iterator i = slots.begin(); i != slots.end(); i++)
+	for(TSlots::const_iterator i = stacks.begin(); i != stacks.end(); i++)
 		ret += i->second->type->AIValue * i->second->count;
 	return ret;
 }
@@ -203,7 +203,7 @@ std::string CCreatureSet::getRoughAmount (TSlot slot) const
 
 int CCreatureSet::stacksCount() const
 {
-	return slots.size();
+	return stacks.size();
 }
 
 void CCreatureSet::setFormation(bool tight)
@@ -213,30 +213,30 @@ void CCreatureSet::setFormation(bool tight)
 
 void CCreatureSet::setStackCount(TSlot slot, TQuantity count)
 {
-	assert(vstd::contains(slots, slot));
+	assert(vstd::contains(stacks, slot));
 	assert(count > 0);
-	slots[slot]->count = count;
+	stacks[slot]->count = count;
 }
 
 void CCreatureSet::clear()
 {
-	while(!slots.empty())
+	while(!stacks.empty())
 	{
-		eraseStack(slots.begin()->first);
+		eraseStack(stacks.begin()->first);
 	}
 }
 
 const CStackInstance& CCreatureSet::getStack(TSlot slot) const
 {
-	assert(vstd::contains(slots, slot));
-	return *slots.find(slot)->second;
+	assert(vstd::contains(stacks, slot));
+	return *stacks.find(slot)->second;
 }
 
 void CCreatureSet::eraseStack(TSlot slot)
 {
-	assert(vstd::contains(slots, slot));
-	delNull(slots[slot]);
-	slots.erase(slot);
+	assert(vstd::contains(stacks, slot));
+	delNull(stacks[slot]);
+	stacks.erase(slot);
 }
 
 bool CCreatureSet::contains(const CStackInstance *stack) const
@@ -244,7 +244,7 @@ bool CCreatureSet::contains(const CStackInstance *stack) const
 	if(!stack) 
 		return false;
 
-	for(TSlots::const_iterator i = slots.begin(); i != slots.end(); ++i)
+	for(TSlots::const_iterator i = stacks.begin(); i != stacks.end(); ++i)
 		if(i->second == stack)
 			return true;
 
@@ -256,7 +256,7 @@ TSlot CCreatureSet::findStack(const CStackInstance *stack) const
 	if(!stack) 
 		return -1;
 
-	for(TSlots::const_iterator i = slots.begin(); i != slots.end(); ++i)
+	for(TSlots::const_iterator i = stacks.begin(); i != stacks.end(); ++i)
 		if(i->second == stack)
 			return i->first;
 
@@ -270,8 +270,8 @@ CArmedInstance * CCreatureSet::castToArmyObj()
 
 void CCreatureSet::putStack(TSlot slot, CStackInstance *stack)
 {
-	assert(!vstd::contains(slots, slot));
-	slots[slot] = stack;
+	assert(!vstd::contains(stacks, slot));
+	stacks[slot] = stack;
 	stack->setArmyObj(castToArmyObj());
 }
 
@@ -311,21 +311,21 @@ void CCreatureSet::setToArmy(CCreatureSet &src)
 	clear();
 	while(src)
 	{
-		TSlots::iterator i = src.slots.begin();
+		TSlots::iterator i = src.stacks.begin();
 
 		assert(i->second->type);
 		assert(i->second->valid(false));
 		assert(i->second->armyObj == NULL);
 
 		putStack(i->first, i->second);
-		src.slots.erase(i);
+		src.stacks.erase(i);
 	}
 }
 
 CStackInstance * CCreatureSet::detachStack(TSlot slot)
 {
-	assert(vstd::contains(slots, slot));
-	CStackInstance *ret = slots[slot];
+	assert(vstd::contains(stacks, slot));
+	CStackInstance *ret = stacks[slot];
 
 	if(CArmedInstance *armedObj = castToArmyObj())
 	{
@@ -334,14 +334,14 @@ CStackInstance * CCreatureSet::detachStack(TSlot slot)
 
 	assert(!ret->armyObj); //we failed detaching?
 
-	slots.erase(slot);
+	stacks.erase(slot);
 	return ret;
 }
 
 void CCreatureSet::setStackType(TSlot slot, const CCreature *type)
 {
-	assert(vstd::contains(slots, slot));
-	CStackInstance *s = slots[slot];
+	assert(vstd::contains(stacks, slot));
+	CStackInstance *s = stacks[slot];
 	s->setType(type->idNumber);
 }
 
@@ -351,7 +351,7 @@ bool CCreatureSet::canBeMergedWith(const CCreatureSet &cs, bool allowMergingStac
 	{
 		int freeSlots = stacksCount() - ARMY_SIZE;
 		std::set<const CCreature*> cresToAdd;
-		for(TSlots::const_iterator i = cs.slots.begin(); i != cs.slots.end(); i++)
+		for(TSlots::const_iterator i = cs.stacks.begin(); i != cs.stacks.end(); i++)
 		{
 			TSlot dest = getSlotFor(i->second->type);
 			if(dest < 0 || hasStackAtSlot(dest))
@@ -364,9 +364,9 @@ bool CCreatureSet::canBeMergedWith(const CCreatureSet &cs, bool allowMergingStac
 		std::set<const CCreature*> cres;
 
 		//get types of creatures that need their own slot
-		for(TSlots::const_iterator i = cs.slots.begin(); i != cs.slots.end(); i++)
+		for(TSlots::const_iterator i = cs.stacks.begin(); i != cs.stacks.end(); i++)
 			cres.insert(i->second->type);
-		for(TSlots::const_iterator i = slots.begin(); i != slots.end(); i++)
+		for(TSlots::const_iterator i = stacks.begin(); i != stacks.end(); i++)
 			cres.insert(i->second->type);
 
 		return cres.size() <= ARMY_SIZE;
@@ -375,7 +375,7 @@ bool CCreatureSet::canBeMergedWith(const CCreatureSet &cs, bool allowMergingStac
 
 bool CCreatureSet::hasStackAtSlot(TSlot slot) const
 {
-	return vstd::contains(slots, slot);
+	return vstd::contains(stacks, slot);
 }
 
 CCreatureSet & CCreatureSet::operator=(const CCreatureSet&cs)

+ 4 - 4
lib/CCreatureSet.h

@@ -72,7 +72,7 @@ class DLL_EXPORT CCreatureSet //seven combined creatures
 	CCreatureSet(const CCreatureSet&);;
 	CCreatureSet &operator=(const CCreatureSet&);
 public:
-	TSlots slots; //slots[slot_id]->> pair(creature_id,creature_quantity)
+	TSlots stacks; //slots[slot_id]->> pair(creature_id,creature_quantity)
 	ui8 formation; //false - wide, true - tight
 
 	CCreatureSet();
@@ -80,7 +80,7 @@ public:
 
 	const CStackInstance &operator[](TSlot slot) const; 
 
-	const TSlots &Slots() const {return slots;}
+	const TSlots &Slots() const {return stacks;}
 
 	void addToSlot(TSlot slot, TCreature cre, TQuantity count, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature
 	void addToSlot(TSlot slot, CStackInstance *stack, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature
@@ -122,11 +122,11 @@ public:
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & slots & formation;
+		h & stacks & formation;
 	}
 	operator bool() const
 	{
-		return slots.size() > 0;
+		return stacks.size() > 0;
 	}
 	void sweep();
 };

+ 82 - 28
lib/CGameState.cpp

@@ -894,34 +894,67 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
 		break;
 	case StartInfo::DUEL:
 		{
-			int3 tile;
-			int terType = TerrainTile::grass;
-			int terrain = 15;
-			const CArmedInstance *armies[2];
-			const CGHeroInstance *heroes[2];
-			const CGTownInstance *town = NULL;
-			CGHeroInstance *h = new CGHeroInstance();
-			h->setOwner(0);
-			h->subID = 1;
-			h->initHero(1);
-			h->initObj();
-			h->setCreature(0, 110, 1);
-			h->setCreature(1, 69, 1);
-
-			CGCreature *c = new CGCreature();
-			c->setOwner(1);
-			c->putStack(0, new CStackInstance(69, 6));
-			c->putStack(1, new CStackInstance(11, 3));
-			c->subID = 34;
-			c->initObj();
-
-			heroes[0] = h;
-			heroes[1] = NULL;
-
-			armies[0] = h;
-			armies[1] = c;
-
-			curB = BattleInfo::setupBattle(tile, terrain, terType, armies, heroes, false, town);
+			bool success = false;
+			DuelParameters dp;
+			try
+			{
+				CLoadFile lf(scenarioOps->mapname);
+				lf >> dp;
+				success = true;
+			}
+			catch(...)
+			{}
+
+
+			const CArmedInstance *armies[2] = {0};
+			const CGHeroInstance *heroes[2] = {0};
+			CGTownInstance *town = NULL;
+
+			for(int i = 0; i < 2; i++)
+			{
+				CArmedInstance *obj = NULL;
+				if(dp.sides[i].heroId >= 0)
+				{
+					CGHeroInstance *h = new CGHeroInstance();
+					armies[i] = heroes[i] = h;
+					obj = h;
+					h->subID = dp.sides[i].heroId;
+					h->initHero(h->subID);
+				}
+				else
+				{
+					CGCreature *c = new CGCreature();
+					armies[i] = obj = c;
+					c->subID = 34;
+					
+				}
+
+				obj->initObj();
+				obj->setOwner(i);
+
+				for(int j = 0; j < ARRAY_COUNT(dp.sides[i].stacks); j++)
+				{
+					int cre = dp.sides[i].stacks[j].type, count = dp.sides[i].stacks[j].count;
+					if(!count && obj->hasStackAtSlot(j)
+						|| count)
+						obj->setCreature(j, cre, count);
+				}
+			}
+
+
+// 			h->setCreature(0, 110, 1);
+// 			h->setCreature(1, 69, 1);
+// 
+// 			CGHeroInstance *h = new CGHeroInstance();
+// 
+// 			CGCreature *c = new CGCreature();
+// 			c->setOwner(1);
+// 			c->putStack(0, new CStackInstance(69, 6));
+// 			c->putStack(1, new CStackInstance(11, 3));
+// 			c->subID = 34;
+// 			c->initObj();
+
+			curB = BattleInfo::setupBattle(int3(), dp.bfieldType, dp.terType, armies, heroes, false, town);
 			curB->localInit();
 			return;
 		}
@@ -3068,4 +3101,25 @@ ArmyDescriptor::ArmyDescriptor(const CArmedInstance *army, bool detailed)
 ArmyDescriptor::ArmyDescriptor()
 {
 
+}
+
+DuelParameters::SideSettings::StackSettings::StackSettings()
+	: type(-1), count(0)
+{
+}
+
+DuelParameters::SideSettings::StackSettings::StackSettings(si32 Type, si32 Count)
+	: type(Type), count(Count)
+{
+}
+
+DuelParameters::SideSettings::SideSettings()
+{
+	heroId = -1;
+}
+
+DuelParameters::DuelParameters()
+{
+	terType = TerrainTile::dirt;
+	bfieldType = 15;
 }

+ 36 - 0
lib/CGameState.h

@@ -247,6 +247,42 @@ struct DLL_EXPORT CPathsInfo
 	~CPathsInfo();
 };
 
+struct DLL_EXPORT DuelParameters
+{
+	si32 terType, bfieldType;
+	struct SideSettings
+	{
+		struct StackSettings
+		{
+			si32 type;
+			si32 count;
+			template <typename Handler> void serialize(Handler &h, const int version)
+			{
+				h & type & count;
+			}
+
+			StackSettings();
+			StackSettings(si32 Type, si32 Count);
+		} stacks[ARMY_SIZE];
+
+		si32 heroId; //-1 if none
+		std::set<si32> spells;
+
+		SideSettings();
+		template <typename Handler> void serialize(Handler &h, const int version)
+		{
+			h & stacks & heroId & spells;
+		}
+	} sides[2];
+
+	DuelParameters();
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & terType & bfieldType & sides;
+	}
+};
+
+
 class BattleInfo;
 
 class DLL_EXPORT CGameState

+ 10 - 10
lib/CObjectHandler.cpp

@@ -2845,7 +2845,7 @@ void CTownBonus::onHeroVisit (const CGHeroInstance * h) const
 const std::string & CGCreature::getHoverText() const
 {
 	MetaString ms;
-	int pom = slots.find(0)->second->getQuantityID();
+	int pom = stacks.find(0)->second->getQuantityID();
 	pom = 174 + 3*pom + 1;
 	ms << std::pair<ui8,ui32>(6,pom) << " " << std::pair<ui8,ui32>(7,subID);
 	ms.toString(hoverName);
@@ -2957,8 +2957,8 @@ void CGCreature::initObj()
 		break;
 	}
 
-	slots[0]->setType(subID);
-	TQuantity &amount = slots[0]->count;
+	stacks[0]->setType(subID);
+	TQuantity &amount = stacks[0]->count;
 	CCreature &c = *VLC->creh->creatures[subID];
 	if(!amount)
 	{
@@ -2968,11 +2968,11 @@ void CGCreature::initObj()
 			amount = c.ammMin + (ran() % (c.ammMax - c.ammMin));
 	}
 
-	temppower = slots[0]->count * 1000;
+	temppower = stacks[0]->count * 1000;
 }
 void CGCreature::newTurn() const
 {//Works only for stacks of single type of size up to 2 millions
-	if (slots.begin()->second->count < CREEP_SIZE && cb->getDate(1) == 1 && cb->getDate(0) > 1)
+	if (stacks.begin()->second->count < CREEP_SIZE && cb->getDate(1) == 1 && cb->getDate(0) > 1)
 	{
 		ui32 power = temppower * (100 + WEEKLY_GROWTH)/100;
 		cb->setObjProperty(id, 10, std::min (power/1000 , (ui32)CREEP_SIZE)); //set new amount
@@ -2984,7 +2984,7 @@ void CGCreature::setPropertyDer(ui8 what, ui32 val)
 	switch (what)
 	{
 		case 10:
-			slots[0]->count = val;
+			stacks[0]->count = val;
 			break;
 		case 11:
 			temppower = val;
@@ -4662,13 +4662,13 @@ void CGBonusingObject::onHeroVisit( const CGHeroInstance * h ) const
 		for (TSlots::const_iterator i = h->Slots().begin(); i != h->Slots().end(); ++i)
 		{
 			if(i->second->type->idNumber == 10)
-				creatures.slots.insert(*i);
+				creatures.stacks.insert(*i);
 		}
-		if (creatures.slots.size())
+		if (creatures.stacks.size())
 		{
 			messageID = 138;
 			iw.components.push_back(Component(Component::CREATURE,11,0,1));
-			for (TSlots::const_iterator i = creatures.slots.begin(); i != creatures.slots.end(); ++i)
+			for (TSlots::const_iterator i = creatures.stacks.begin(); i != creatures.stacks.end(); ++i)
 			{
 				cb->changeStackType(StackLocation(h, i->first), VLC->creh->creatures[11]);
 			}
@@ -6534,7 +6534,7 @@ CCreatureSet& CArmedInstance::getArmy() const
 void CArmedInstance::randomizeArmy(int type)
 {
 	int max = VLC->creh->creatures.size();
-	for (TSlots::iterator j = slots.begin(); j != slots.end();j++)
+	for (TSlots::iterator j = stacks.begin(); j != stacks.end();j++)
 	{
 		int randID = j->second->idRand;
 		if(randID > max)

+ 15 - 15
server/CGameHandler.cpp

@@ -389,7 +389,7 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
 	if(duel)
 	{
 		CSaveFile resultFile("result.vdrst");
-		resultFile << battleResult.data;
+		resultFile << *battleResult.data;
 		return;
 	}
 
@@ -1981,8 +1981,8 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
 
 	if(what==1) //swap
 	{
-		if ( ((s1->tempOwner != player && s1->tempOwner != 254) && S1.slots[p1]->count) //why 254??
-		  || ((s2->tempOwner != player && s2->tempOwner != 254) && S2.slots[p2]->count))
+		if ( ((s1->tempOwner != player && s1->tempOwner != 254) && S1.stacks[p1]->count) //why 254??
+		  || ((s2->tempOwner != player && s2->tempOwner != 254) && S2.stacks[p2]->count))
 		{
 			complain("Can't take troops from another player!");
 			return false;
@@ -1992,46 +1992,46 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
 	}
 	else if(what==2)//merge
 	{
-		if (( S1.slots[p1]->type != S2.slots[p2]->type && complain("Cannot merge different creatures stacks!"))
-		|| ((s1->tempOwner != player && s1->tempOwner != 254) && S2.slots[p2]->count) && complain("Can't take troops from another player!"))
+		if (( S1.stacks[p1]->type != S2.stacks[p2]->type && complain("Cannot merge different creatures stacks!"))
+		|| ((s1->tempOwner != player && s1->tempOwner != 254) && S2.stacks[p2]->count) && complain("Can't take troops from another player!"))
 			return false; 
 
 		moveStack(sl1, sl2);
 	}
 	else if(what==3) //split
 	{
-		if ( (s1->tempOwner != player && S1.slots[p1]->count < s1->getArmy().getStackCount(p1) )
-			|| (s2->tempOwner != player && S2.slots[p2]->count < s2->getArmy().getStackCount(p2) ) )
+		if ( (s1->tempOwner != player && S1.stacks[p1]->count < s1->getArmy().getStackCount(p1) )
+			|| (s2->tempOwner != player && S2.stacks[p2]->count < s2->getArmy().getStackCount(p2) ) )
 		{
 			complain("Can't move troops of another player!");
 			return false;
 		}
 
 		//general conditions checking
-		if((!vstd::contains(S1.slots,p1) && complain("no creatures to split"))
+		if((!vstd::contains(S1.stacks,p1) && complain("no creatures to split"))
 			|| (val<1  && complain("no creatures to split"))  )
 		{
 			return false;
 		}
 
 
-		if(vstd::contains(S2.slots,p2))	 //dest. slot not free - it must be "rebalancing"...
+		if(vstd::contains(S2.stacks,p2))	 //dest. slot not free - it must be "rebalancing"...
 		{
-			int total = S1.slots[p1]->count + S2.slots[p2]->count;
+			int total = S1.stacks[p1]->count + S2.stacks[p2]->count;
 			if( (total < val   &&   complain("Cannot split that stack, not enough creatures!"))
-				|| (S2.slots[p2]->type != S1.slots[p1]->type && complain("Cannot rebalance different creatures stacks!"))
+				|| (S2.stacks[p2]->type != S1.stacks[p1]->type && complain("Cannot rebalance different creatures stacks!"))
 			)
 			{
 				return false; 
 			}
 			
-			moveStack(sl1, sl2, val - S2.slots[p2]->count);
+			moveStack(sl1, sl2, val - S2.stacks[p2]->count);
 			//S2.slots[p2]->count = val;
 			//S1.slots[p1]->count = total - val;
 		}
 		else //split one stack to the two
 		{
-			if(S1.slots[p1]->count < val)//not enough creatures
+			if(S1.stacks[p1]->count < val)//not enough creatures
 			{
 				complain("Cannot split that stack, not enough creatures!");
 				return false; 
@@ -2072,7 +2072,7 @@ int CGameHandler::getPlayerAt( CConnection *c ) const
 bool CGameHandler::disbandCreature( si32 id, ui8 pos )
 {
 	CArmedInstance *s1 = static_cast<CArmedInstance*>(gs->map->objects[id].get());
-	if(!vstd::contains(s1->slots,pos))
+	if(!vstd::contains(s1->stacks,pos))
 	{
 		complain("Illegal call to disbandCreature - no such stack in army!");
 		return false;
@@ -2321,7 +2321,7 @@ bool CGameHandler::upgradeCreature( ui32 objid, ui8 pos, ui32 upgID )
 	assert(obj->hasStackAtSlot(pos));
 	UpgradeInfo ui = gs->getUpgradeInfo(obj->getStack(pos));
 	int player = obj->tempOwner;
-	int crQuantity = obj->slots[pos]->count;
+	int crQuantity = obj->stacks[pos]->count;
 	int newIDpos= vstd::findPos(ui.newID, upgID);//get position of new id in UpgradeInfo
 
 	//check if upgrade is possible