فهرست منبع

Moving stack system to pointers, part #1

Michał W. Urbańczyk 15 سال پیش
والد
کامیت
32ce20af15

+ 8 - 8
AI/GeniusAI/CGeniusAI.cpp

@@ -748,7 +748,7 @@ void CGeniusAI::HeroObjective::fulfill(CGeniusAI& cg,
                j = ui.cost[ii].begin();
                j = ui.cost[ii].begin();
                j != ui.cost[ii].end();
                j != ui.cost[ii].end();
                j++)
                j++)
-					  if (hgs.resourceAmounts[j->first] < j->second * i->second.count)
+					  if (hgs.resourceAmounts[j->first] < j->second * i->second->count)
 						  canUpgrade = false;
 						  canUpgrade = false;
 		  }
 		  }
 			
 			
@@ -756,7 +756,7 @@ void CGeniusAI::HeroObjective::fulfill(CGeniusAI& cg,
 		  {
 		  {
 			  cg.m_cb->upgradeCreature(h->h, i->first, ui.newID.back());
 			  cg.m_cb->upgradeCreature(h->h, i->first, ui.newID.back());
 			  cout << "upgrading hero's "
 			  cout << "upgrading hero's "
-             << i->second.type->namePl
+             << i->second->type->namePl
              << endl;
              << endl;
 		  }
 		  }
 	  }
 	  }
@@ -770,9 +770,9 @@ void CGeniusAI::HeroObjective::fulfill(CGeniusAI& cg,
          i = tcreatures.Slots().begin();
          i = tcreatures.Slots().begin();
          i != tcreatures.Slots().end();
          i != tcreatures.Slots().end();
          i++) {
          i++) {
-		  if (i->second.type->AIValue < 
+		  if (i->second->type->AIValue < 
           weakestCreatureAIValue) {
           weakestCreatureAIValue) {
-			  weakestCreatureAIValue  = i->second.type->AIValue;
+			  weakestCreatureAIValue  = i->second->type->AIValue;
 			  weakestCreatureStack    = i->first;
 			  weakestCreatureStack    = i->first;
 		  }
 		  }
     }
     }
@@ -781,18 +781,18 @@ void CGeniusAI::HeroObjective::fulfill(CGeniusAI& cg,
         i != tcreatures.Slots().end();
         i != tcreatures.Slots().end();
         i++) { // For each town slot.
         i++) { // For each town slot.
 		  hcreatures = h->h->getArmy();
 		  hcreatures = h->h->getArmy();
-		  int hSlot = hcreatures.getSlotFor(i->second.type->idNumber);
+		  int hSlot = hcreatures.getSlotFor(i->second->type->idNumber);
 
 
 		  if (hSlot == -1)
 		  if (hSlot == -1)
         continue;
         continue;
 		  cout << "giving hero "
 		  cout << "giving hero "
-           << i->second.type->namePl
+           << i->second->type->namePl
            << endl;
            << endl;
 		  if (!hcreatures.slotEmpty(hSlot)) {
 		  if (!hcreatures.slotEmpty(hSlot)) {
         // Can't take garrisonHero's last unit.
         // Can't take garrisonHero's last unit.
 			  if ( (i->first == weakestCreatureStack)
 			  if ( (i->first == weakestCreatureStack)
             && (town->garrisonHero != NULL) )
             && (town->garrisonHero != NULL) )
-				  cg.m_cb->splitStack(town, h->h, i->first, hSlot, i->second.count - 1);
+				  cg.m_cb->splitStack(town, h->h, i->first, hSlot, i->second->count - 1);
 			  else
 			  else
           // TODO: the comment says that this code is not safe for the AI.
           // TODO: the comment says that this code is not safe for the AI.
 				  cg.m_cb->mergeStacks(town, h->h, i->first, hSlot);
 				  cg.m_cb->mergeStacks(town, h->h, i->first, hSlot);
@@ -880,7 +880,7 @@ void CGeniusAI::addTownObjectives(HypotheticalGameState::TownModel& t,
           j = ui.cost[upgrade_serial].begin();
           j = ui.cost[upgrade_serial].begin();
           j != ui.cost[upgrade_serial].end();
           j != ui.cost[upgrade_serial].end();
           j++)
           j++)
-				if (hgs.resourceAmounts[j->first] < j->second * i->second.count)
+				if (hgs.resourceAmounts[j->first] < j->second * i->second->count)
 					canAfford = false;
 					canAfford = false;
 			if (canAfford) {
 			if (canAfford) {
 				TownObjective to(hgs,AIObjective::upgradeCreatures,&t,i->first,this);
 				TownObjective to(hgs,AIObjective::upgradeCreatures,&t,i->first,this);

+ 6 - 6
client/CBattleInterface.cpp

@@ -3748,10 +3748,10 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
 		int bestPower = 0;
 		int bestPower = 0;
 		for(TSlots::const_iterator it = owner->army1.Slots().begin(); it!=owner->army1.Slots().end(); ++it)
 		for(TSlots::const_iterator it = owner->army1.Slots().begin(); it!=owner->army1.Slots().end(); ++it)
 		{
 		{
-			if( it->second.type->AIValue > bestPower)
+			if( it->second->type->AIValue > bestPower)
 			{
 			{
-				bestPower = it->second.type->AIValue;
-				bestMonsterID = it->second.type->idNumber;
+				bestPower = it->second->type->AIValue;
+				bestMonsterID = it->second->type->idNumber;
 			}
 			}
 		}
 		}
 		SDL_BlitSurface(graphics->bigImgs[bestMonsterID], NULL, background, &genRect(64, 58, 21, 38));
 		SDL_BlitSurface(graphics->bigImgs[bestMonsterID], NULL, background, &genRect(64, 58, 21, 38));
@@ -3770,10 +3770,10 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
 		int bestPower = 0;
 		int bestPower = 0;
 		for(TSlots::const_iterator it = owner->army2.Slots().begin(); it!=owner->army2.Slots().end(); ++it)
 		for(TSlots::const_iterator it = owner->army2.Slots().begin(); it!=owner->army2.Slots().end(); ++it)
 		{
 		{
-			if( it->second.type->AIValue > bestPower)
+			if( it->second->type->AIValue > bestPower)
 			{
 			{
-				bestPower = it->second.type->AIValue;
-				bestMonsterID = it->second.type->idNumber;
+				bestPower = it->second->type->AIValue;
+				bestMonsterID = it->second->type->idNumber;
 			}
 			}
 		}
 		}
 		SDL_BlitSurface(graphics->bigImgs[bestMonsterID], NULL, background, &genRect(64, 58, 392, 38));
 		SDL_BlitSurface(graphics->bigImgs[bestMonsterID], NULL, background, &genRect(64, 58, 392, 38));

+ 1 - 0
client/Client.h

@@ -112,6 +112,7 @@ public:
 	void giveResource(int player, int which, int val){};
 	void giveResource(int player, int which, int val){};
 	void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet creatures, bool remove) {};
 	void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet creatures, bool remove) {};
 	void takeCreatures (int objid, TSlots creatures){};
 	void takeCreatures (int objid, TSlots creatures){};
+	void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures){};
 	void changeCreatureType (int objid, TSlot slot, TCreature creature){};
 	void changeCreatureType (int objid, TSlot slot, TCreature creature){};
 	void showCompInfo(ShowInInfobox * comp){};
 	void showCompInfo(ShowInInfobox * comp){};
 	void heroVisitCastle(int obj, int heroID){};
 	void heroVisitCastle(int obj, int heroID){};

+ 2 - 2
client/GUIClasses.cpp

@@ -369,7 +369,7 @@ void CGarrisonInt::createSet(std::vector<CGarrisonSlot*> &ret, const CCreatureSe
 	
 	
 	for(TSlots::const_iterator i=set->Slots().begin(); i!=set->Slots().end(); i++)
 	for(TSlots::const_iterator i=set->Slots().begin(); i!=set->Slots().end(); i++)
 	{
 	{
-		ret[i->first] = new CGarrisonSlot(this, posX + (i->first*distance), posY, i->first, Upg, &i->second);
+		ret[i->first] = new CGarrisonSlot(this, posX + (i->first*distance), posY, i->first, Upg, i->second);
 	}
 	}
 
 
 	for(int i=0; i<ret.size(); i++)
 	for(int i=0; i<ret.size(); i++)
@@ -4416,7 +4416,7 @@ void CGarrisonWindow::show(SDL_Surface * to)
 	else
 	else
 	{
 	{
 		title = CGI->generaltexth->allTexts[35];
 		title = CGI->generaltexth->allTexts[35];
-		boost::algorithm::replace_first(title, "%s", garr->oup->Slots().begin()->second.type->namePl);
+		boost::algorithm::replace_first(title, "%s", garr->oup->Slots().begin()->second->type->namePl);
 	}
 	}
 
 
 	blitAt(graphics->flags->ourImages[garr->odown->getOwner()].bitmap,pos.x+28,pos.y+124,to);
 	blitAt(graphics->flags->ourImages[garr->odown->getOwner()].bitmap,pos.x+28,pos.y+124,to);

+ 5 - 5
client/Graphics.cpp

@@ -55,15 +55,15 @@ SDL_Surface * Graphics::drawHeroInfoWin(const InfoAboutHero &curh)
 	//army
 	//army
 	for (TSlots::const_iterator i = curh.army.Slots().begin(); i!=curh.army.Slots().end();i++)
 	for (TSlots::const_iterator i = curh.army.Slots().begin(); i!=curh.army.Slots().end();i++)
 	{
 	{
-		blitAt(graphics->smallImgs[(*i).second.type->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
+		blitAt(graphics->smallImgs[(*i).second->type->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
 		if(curh.details)
 		if(curh.details)
 		{
 		{
-			SDL_itoa((*i).second.count,buf,10);
+			SDL_itoa((*i).second->count,buf,10);
 			printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
 			printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
 		}
 		}
 		else
 		else
 		{
 		{
-			printAtMiddle(VLC->generaltexth->arraytxt[174 + 3*(i->second.count-1)],slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
+			printAtMiddle(VLC->generaltexth->arraytxt[174 + 3*(i->second->count-1)],slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
 		}
 		}
 	}
 	}
 
 
@@ -114,11 +114,11 @@ SDL_Surface * Graphics::drawTownInfoWin( const InfoAboutTown & curh )
 	{
 	{
 		//if(!i->second.second)
 		//if(!i->second.second)
 		//	continue;
 		//	continue;
-		blitAt(graphics->smallImgs[(*i).second.type->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
+		blitAt(graphics->smallImgs[(*i).second->type->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
 		if(curh.details)
 		if(curh.details)
 		{
 		{
 			// Show exact creature amount.
 			// Show exact creature amount.
-			SDL_itoa((*i).second.count,buf,10);
+			SDL_itoa((*i).second->count,buf,10);
 			printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
 			printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
 		}
 		}
 		else
 		else

+ 120 - 116
hch/CObjectHandler.cpp

@@ -553,10 +553,10 @@ static int lowestSpeed(const CGHeroInstance * chi)
 	}
 	}
 	TSlots::const_iterator i = chi->Slots().begin();
 	TSlots::const_iterator i = chi->Slots().begin();
 	//TODO? should speed modifiers (eg from artifacts) affect hero movement?
 	//TODO? should speed modifiers (eg from artifacts) affect hero movement?
-	int ret = (i++)->second.valOfBonuses(Bonus::STACKS_SPEED);
+	int ret = (i++)->second->valOfBonuses(Bonus::STACKS_SPEED);
 	for (;i!=chi->Slots().end();i++)
 	for (;i!=chi->Slots().end();i++)
 	{
 	{
-		ret = std::min(ret, i->second.valOfBonuses(Bonus::STACKS_SPEED));
+		ret = std::min(ret, i->second->valOfBonuses(Bonus::STACKS_SPEED));
 	}
 	}
 	return ret;
 	return ret;
 }
 }
@@ -893,7 +893,7 @@ void CGHeroInstance::initArmy(CCreatureSet *dst /*= NULL*/)
 			}
 			}
 		}
 		}
 		else
 		else
-			dst->addStack(stackNo-warMachinesGiven, CStackInstance(creID, count));
+			dst->addStack(stackNo-warMachinesGiven, new CStackInstance(creID, count));
 	}
 	}
 }
 }
 void CGHeroInstance::initHeroDefInfo()
 void CGHeroInstance::initHeroDefInfo()
@@ -1326,7 +1326,7 @@ bool CGHeroInstance::canCastThisSpell(const CSpell * spell) const
  * type and second value the amount. Both values are returned as -1 if necromancy
  * type and second value the amount. Both values are returned as -1 if necromancy
  * could not be applied.
  * could not be applied.
  */
  */
-CStackInstance CGHeroInstance::calculateNecromancy (const BattleResult &battleResult) const
+CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &battleResult) const
 {
 {
 	const ui8 necromancyLevel = getSecSkillLevel(12);
 	const ui8 necromancyLevel = getSecSkillLevel(12);
 
 
@@ -1365,10 +1365,10 @@ CStackInstance CGHeroInstance::calculateNecromancy (const BattleResult &battleRe
 		if (raisedUnits <= 0)
 		if (raisedUnits <= 0)
 			raisedUnits = 1;
 			raisedUnits = 1;
 
 
-		return CStackInstance(raisedUnitType->idNumber, raisedUnits);
+		return CStackBasicDescriptor(raisedUnitType->idNumber, raisedUnits);
 	}
 	}
 
 
-	return CStackInstance();
+	return CStackBasicDescriptor();
 }
 }
 
 
 /**
 /**
@@ -1376,7 +1376,7 @@ CStackInstance CGHeroInstance::calculateNecromancy (const BattleResult &battleRe
  * @param raisedStack Pair where the first element represents ID of the raised creature
  * @param raisedStack Pair where the first element represents ID of the raised creature
  * and the second element the amount.
  * and the second element the amount.
  */
  */
-void CGHeroInstance::showNecromancyDialog(const CStackInstance &raisedStack) const
+void CGHeroInstance::showNecromancyDialog(const CStackBasicDescriptor &raisedStack) const
 {
 {
 	InfoWindow iw;
 	InfoWindow iw;
 	iw.soundID = soundBase::GENIE;
 	iw.soundID = soundBase::GENIE;
@@ -1587,7 +1587,7 @@ void CGDwelling::initObj()
 			creatures[0].second.push_back(crid);
 			creatures[0].second.push_back(crid);
 			hoverName = VLC->generaltexth->creGens[subID];
 			hoverName = VLC->generaltexth->creGens[subID];
 			if(crs->level > 4)
 			if(crs->level > 4)
-				addStack(0, CStackInstance(crs, (crs->growth) * 3));
+				addStack(0, new CStackInstance(crs, (crs->growth) * 3));
 			if (getOwner() != 255)
 			if (getOwner() != 255)
 				cb->gameState()->players[getOwner()].dwellings.push_back (this);
 				cb->gameState()->players[getOwner()].dwellings.push_back (this);
 		}
 		}
@@ -1602,8 +1602,8 @@ void CGDwelling::initObj()
 			creatures[2].second.push_back(116); //Gold Golem
 			creatures[2].second.push_back(116); //Gold Golem
 			creatures[3].second.push_back(117); //Diamond Golem
 			creatures[3].second.push_back(117); //Diamond Golem
 			//guards
 			//guards
-			addStack(0, CStackInstance(116, 9));
-			addStack(1, CStackInstance(117, 6));
+			addStack(0, new CStackInstance(116, 9));
+			addStack(1, new CStackInstance(117, 6));
 		}
 		}
 		else if(subID == 0) // Elemental Conflux 
 		else if(subID == 0) // Elemental Conflux 
 		{
 		{
@@ -1612,7 +1612,7 @@ void CGDwelling::initObj()
 			creatures[2].second.push_back(113); //Earth Elemental
 			creatures[2].second.push_back(113); //Earth Elemental
 			creatures[3].second.push_back(115); //Water Elemental
 			creatures[3].second.push_back(115); //Water Elemental
 			//guards
 			//guards
-			addStack(0, CStackInstance(113, 12));
+			addStack(0, new CStackInstance(113, 12));
 		}
 		}
 		else
 		else
 		{
 		{
@@ -1686,8 +1686,8 @@ void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const
 		bd.flags = BlockingDialog::ALLOW_CANCEL;
 		bd.flags = BlockingDialog::ALLOW_CANCEL;
 		bd.text.addTxt(MetaString::GENERAL_TXT, 421); //Much to your dismay, the %s is guarded by %s %s. Do you wish to fight the guards?
 		bd.text.addTxt(MetaString::GENERAL_TXT, 421); //Much to your dismay, the %s is guarded by %s %s. Do you wish to fight the guards?
 		bd.text.addReplacement(ID == 17 ? MetaString::CREGENS : MetaString::CREGENS4, subID);
 		bd.text.addReplacement(ID == 17 ? MetaString::CREGENS : MetaString::CREGENS4, subID);
-		bd.text.addReplacement(MetaString::ARRAY_TXT, 176 + Slots().begin()->second.getQuantityID()*3);
-		bd.text.addReplacement(Slots().begin()->second);
+		bd.text.addReplacement(MetaString::ARRAY_TXT, 176 + Slots().begin()->second->getQuantityID()*3);
+		bd.text.addReplacement(*Slots().begin()->second);
 		cb->showBlockingDialog(&bd, boost::bind(&CGDwelling::wantsFight, this, h, _1));
 		cb->showBlockingDialog(&bd, boost::bind(&CGDwelling::wantsFight, this, h, _1));
 		return;
 		return;
 	}
 	}
@@ -2159,34 +2159,36 @@ void CGTownInstance::newTurn() const
 
 
 		if (tempOwner == NEUTRAL_PLAYER) //garrison growth for neutral towns
 		if (tempOwner == NEUTRAL_PLAYER) //garrison growth for neutral towns
 			{
 			{
-				TSlots slt = Slots(); //meh, waste of time
 				std::vector<ui8> nativeCrits; //slots
 				std::vector<ui8> nativeCrits; //slots
-				for (TSlots::const_iterator it = slt.begin(); it != slt.end(); it++)
+				for (TSlots::const_iterator it = Slots().begin(); it != Slots().end(); it++)
 				{
 				{
-					if (it->second.type->faction == subID) //native
+					if (it->second->type->faction == subID) //native
 					{
 					{
 						nativeCrits.push_back(it->first); //collect matching slots
 						nativeCrits.push_back(it->first); //collect matching slots
 					}
 					}
 				}
 				}
 				if (nativeCrits.size())
 				if (nativeCrits.size())
 				{
 				{
-					int pos = nativeCrits[rand() % nativeCrits.size()];
-					if (rand()%100 < 90 || slt[pos].type->upgrades.empty()) //increase number if no upgrade avaliable
+					TSlot pos = nativeCrits[rand() % nativeCrits.size()];
+					const CCreature *c = getCreature(pos);
+					if (rand()%100 < 90 || c->upgrades.empty()) //increase number if no upgrade avaliable
 					{
 					{
 						SetGarrisons sg;
 						SetGarrisons sg;
 						sg.garrs[id] = getArmy();
 						sg.garrs[id] = getArmy();
-						sg.garrs[id].slots[pos].count += slt[pos].type->growth;
+						sg.garrs[id].slots[pos]->count += c->growth;
 						cb->sendAndApply(&sg);	
 						cb->sendAndApply(&sg);	
 					}
 					}
 					else //upgrade
 					else //upgrade
 					{
 					{
 						SetGarrisons sg; //somewhat better upgrade pack would come in handy
 						SetGarrisons sg; //somewhat better upgrade pack would come in handy
 						sg.garrs[id] = getArmy();
 						sg.garrs[id] = getArmy();
-						sg.garrs[id].setCreature(pos, *slt[pos].type->upgrades.begin(), slt[pos].count);
+						//////////////////////////////////////////////////////////////////////////
+						//sg.garrs[id].t (pos, *c->upgrades.begin(), );
+						//sg.garrs[id].setCreature(pos, *c->upgrades.begin(), slt[pos].count);
 						cb->sendAndApply(&sg);	
 						cb->sendAndApply(&sg);	
 					}
 					}
 				}
 				}
-				if ((stacksCount() < ARMY_SIZE && rand()%100 < 25) || slt.empty()) //add new stack
+				if ((stacksCount() < ARMY_SIZE && rand()%100 < 25) || Slots().empty()) //add new stack
 				{
 				{
 					int n, i = rand() % std::min (ARMY_SIZE, cb->getDate(3)<<1);	
 					int n, i = rand() % std::min (ARMY_SIZE, cb->getDate(3)<<1);	
 					{//no lower tiers or above current month
 					{//no lower tiers or above current month
@@ -2840,7 +2842,7 @@ void CTownBonus::onHeroVisit (const CGHeroInstance * h) const
 const std::string & CGCreature::getHoverText() const
 const std::string & CGCreature::getHoverText() const
 {
 {
 	MetaString ms;
 	MetaString ms;
-	int pom = slots.find(0)->second.getQuantityID();
+	int pom = slots.find(0)->second->getQuantityID();
 	pom = 174 + 3*pom + 1;
 	pom = 174 + 3*pom + 1;
 	ms << std::pair<ui8,ui32>(6,pom) << " " << std::pair<ui8,ui32>(7,subID);
 	ms << std::pair<ui8,ui32>(6,pom) << " " << std::pair<ui8,ui32>(7,subID);
 	ms.toString(hoverName);
 	ms.toString(hoverName);
@@ -2894,7 +2896,7 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
 			BlockingDialog ynd(true,false);
 			BlockingDialog ynd(true,false);
 			ynd.player = h->tempOwner;
 			ynd.player = h->tempOwner;
 			std::string tmp = VLC->generaltexth->advobtxt[90];
 			std::string tmp = VLC->generaltexth->advobtxt[90];
-			boost::algorithm::replace_first(tmp,"%d",boost::lexical_cast<std::string>(slots.find(0)->second.count));
+			boost::algorithm::replace_first(tmp,"%d",boost::lexical_cast<std::string>(getAmount(0)));
 			boost::algorithm::replace_first(tmp,"%d",boost::lexical_cast<std::string>(action));
 			boost::algorithm::replace_first(tmp,"%d",boost::lexical_cast<std::string>(action));
 			boost::algorithm::replace_first(tmp,"%s",VLC->creh->creatures[subID]->namePl);
 			boost::algorithm::replace_first(tmp,"%s",VLC->creh->creatures[subID]->namePl);
 			ynd.text << tmp;
 			ynd.text << tmp;
@@ -2952,8 +2954,8 @@ void CGCreature::initObj()
 		break;
 		break;
 	}
 	}
 
 
-	slots[0].setType(subID);
-	si32 &amount = slots[0].count;
+	slots[0]->setType(subID);
+	TQuantity &amount = slots[0]->count;
 	CCreature &c = *VLC->creh->creatures[subID];
 	CCreature &c = *VLC->creh->creatures[subID];
 	if(!amount)
 	if(!amount)
 	{
 	{
@@ -2963,11 +2965,11 @@ void CGCreature::initObj()
 			amount = c.ammMin + (ran() % (c.ammMax - c.ammMin));
 			amount = c.ammMin + (ran() % (c.ammMax - c.ammMin));
 	}
 	}
 
 
-	temppower = slots[0].count * 1000;
+	temppower = slots[0]->count * 1000;
 }
 }
 void CGCreature::newTurn() const
 void CGCreature::newTurn() const
 {//Works only for stacks of single type of size up to 2 millions
 {//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 (slots.begin()->second->count < CREEP_SIZE && cb->getDate(1) == 1 && cb->getDate(0) > 1)
 	{
 	{
 		ui32 power = temppower * (100 + WEEKLY_GROWTH)/100;
 		ui32 power = temppower * (100 + WEEKLY_GROWTH)/100;
 		cb->setObjProperty(id, 10, std::min (power/1000 , (ui32)CREEP_SIZE)); //set new amount
 		cb->setObjProperty(id, 10, std::min (power/1000 , (ui32)CREEP_SIZE)); //set new amount
@@ -2979,7 +2981,7 @@ void CGCreature::setPropertyDer(ui8 what, ui32 val)
 	switch (what)
 	switch (what)
 	{
 	{
 		case 10:
 		case 10:
-			slots[0].count = val;
+			slots[0]->count = val;
 			break;
 			break;
 		case 11:
 		case 11:
 			temppower = val;
 			temppower = val;
@@ -3021,9 +3023,9 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
 
 
 		for (TSlots::const_iterator i = h->Slots().begin(); i != h->Slots().end(); i++)
 		for (TSlots::const_iterator i = h->Slots().begin(); i != h->Slots().end(); i++)
 		{
 		{
-			if(vstd::contains(myKindCres,i->second.type->idNumber))
-				count += i->second.count;
-			totalCount += i->second.count;
+			if(vstd::contains(myKindCres,i->second->type->idNumber))
+				count += i->second->count;
+			totalCount += i->second->count;
 		}
 		}
 
 
 		if(count*2 > totalCount)
 		if(count*2 > totalCount)
@@ -3038,7 +3040,7 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
 			if(h->getSecSkillLevel(4) + sympathy + 1 >= character)
 			if(h->getSecSkillLevel(4) + sympathy + 1 >= character)
 				return 0; //join for free
 				return 0; //join for free
 			else if(h->getSecSkillLevel(4) * 2  +  sympathy  +  1 >= character)
 			else if(h->getSecSkillLevel(4) * 2  +  sympathy  +  1 >= character)
-				return VLC->creh->creatures[subID]->cost[6] * Slots().find(0)->second.count; //join for gold
+				return VLC->creh->creatures[subID]->cost[6] * getAmount(0); //join for gold
 		}
 		}
 	}
 	}
 
 
@@ -3177,7 +3179,7 @@ void CGMine::initObj()
 	{
 	{
 		//set guardians
 		//set guardians
 		int howManyTroglodytes = 100 + ran()%100;
 		int howManyTroglodytes = 100 + ran()%100;
-		CStackInstance troglodytes(70, howManyTroglodytes);
+		CStackInstance *troglodytes = new CStackInstance(70, howManyTroglodytes);
 		addStack(0, troglodytes);
 		addStack(0, troglodytes);
 
 
 		//after map reading tempOwner placeholds bitmask for allowed resources
 		//after map reading tempOwner placeholds bitmask for allowed resources
@@ -3189,7 +3191,7 @@ void CGMine::initObj()
 		assert(possibleResources.size());
 		assert(possibleResources.size());
 		producedResource = possibleResources[ran()%possibleResources.size()];
 		producedResource = possibleResources[ran()%possibleResources.size()];
 		tempOwner = NEUTRAL_PLAYER;
 		tempOwner = NEUTRAL_PLAYER;
-		hoverName = VLC->generaltexth->mines[7].first + "\n" + VLC->generaltexth->allTexts[202] + " " + troglodytes.getQuantityTXT(false) + " " + troglodytes.type->namePl;
+		hoverName = VLC->generaltexth->mines[7].first + "\n" + VLC->generaltexth->allTexts[202] + " " + troglodytes->getQuantityTXT(false) + " " + troglodytes->type->namePl;
 	}
 	}
 	else
 	else
 	{
 	{
@@ -3453,7 +3455,7 @@ void CGTeleport::onHeroVisit( const CGHeroInstance * h ) const
 				if (!h->hasBonusOfType(Bonus::WHIRLPOOL_PROTECTION))
 				if (!h->hasBonusOfType(Bonus::WHIRLPOOL_PROTECTION))
 				{
 				{
 					CCreatureSet army = h->getArmy();
 					CCreatureSet army = h->getArmy();
-					if (army.Slots().size() > 1 || army.Slots().begin()->second.count > 1)
+					if (army.Slots().size() > 1 || army.Slots().begin()->second->count > 1)
 					{ //we can't remove last unit
 					{ //we can't remove last unit
 						int targetstack = army.Slots().begin()->first; //slot numbers may vary
 						int targetstack = army.Slots().begin()->first; //slot numbers may vary
 						for(TSlots::const_reverse_iterator i = army.Slots().rbegin(); i != army.Slots().rend(); i++)
 						for(TSlots::const_reverse_iterator i = army.Slots().rbegin(); i != army.Slots().rend(); i++)
@@ -3463,18 +3465,17 @@ void CGTeleport::onHeroVisit( const CGHeroInstance * h ) const
 								targetstack = (i->first);
 								targetstack = (i->first);
 							}
 							}
 						}
 						}
-						CCreatureSet ourArmy;
-						ourArmy.addStack (targetstack, army.getStack(targetstack));
-						TQuantity tq = (double)(ourArmy.getAmount(targetstack))*0.5;
-						amax (tq, 1);
+						std::vector<CStackBasicDescriptor> cresToTake;
+						cresToTake.push_back(CStackBasicDescriptor(army.getStack(targetstack)));
+						cresToTake[0].count * 0.5;
+						amax (cresToTake[0].count, 1);
 
 
-						ourArmy.setStackCount (targetstack, tq);
 						InfoWindow iw;
 						InfoWindow iw;
 						iw.player = h->tempOwner;
 						iw.player = h->tempOwner;
 						iw.text.addTxt (MetaString::ADVOB_TXT, 168);
 						iw.text.addTxt (MetaString::ADVOB_TXT, 168);
-						iw.components.push_back (Component(ourArmy.getStack(targetstack)));
+						iw.components.push_back (Component(cresToTake[0]));
 						cb->showInfoDialog(&iw);
 						cb->showInfoDialog(&iw);
-					    cb->takeCreatures (h->id, ourArmy.Slots());
+					    cb->takeCreatures (h->id, cresToTake);
 					}
 					}
 				}
 				}
 			}
 			}
@@ -3931,16 +3932,17 @@ bool CQuest::checkQuest (const CGHeroInstance * h) const
 			break;
 			break;
 		case MISSION_ARMY:
 		case MISSION_ARMY:
 			{
 			{
-				TSlots::const_iterator it, cre;
+				std::vector<CStackBasicDescriptor>::const_iterator cre;
+				TSlots::const_iterator it;
 				ui32 count;
 				ui32 count;
 				for (cre = m6creatures.begin(); cre != m6creatures.end(); ++cre)
 				for (cre = m6creatures.begin(); cre != m6creatures.end(); ++cre)
 				{
 				{
 					for (count = 0, it = h->Slots().begin(); it !=  h->Slots().end(); ++it)
 					for (count = 0, it = h->Slots().begin(); it !=  h->Slots().end(); ++it)
 					{
 					{
-						if (it->second.type == cre->second.type)
-							count += it->second.count;
+						if (it->second->type == cre->type)
+							count += it->second->count;
 					}
 					}
-					if (count < cre->second.count) //not enough creatures of this kind
+					if (count < cre->count) //not enough creatures of this kind
 						return false;
 						return false;
 				}
 				}
 			}
 			}
@@ -4010,7 +4012,7 @@ const std::string & CGSeerHut::getHoverText() const
 		switch (missionType)
 		switch (missionType)
 		{
 		{
 			case MISSION_LEVEL:
 			case MISSION_LEVEL:
-				ms.addReplacement (m13489val);
+				ms.addReplacement(m13489val);
 				break;
 				break;
 			case MISSION_PRIMARY_STAT:
 			case MISSION_PRIMARY_STAT:
 			{
 			{
@@ -4020,8 +4022,8 @@ const std::string & CGSeerHut::getHoverText() const
 					if (m2stats[i])
 					if (m2stats[i])
 					{
 					{
 						loot << "%d %s";
 						loot << "%d %s";
-						loot.addReplacement (m2stats[i]);
-						loot.addReplacement (VLC->generaltexth->primarySkillNames[i]);
+						loot.addReplacement(m2stats[i]);
+						loot.addReplacement(VLC->generaltexth->primarySkillNames[i]);
 					}		
 					}		
 				}
 				}
 				ms.addReplacement(loot.buildList());
 				ms.addReplacement(loot.buildList());
@@ -4044,7 +4046,7 @@ const std::string & CGSeerHut::getHoverText() const
 					for (std::vector<ui16>::const_iterator it = m5arts.begin(); it != m5arts.end(); ++it)
 					for (std::vector<ui16>::const_iterator it = m5arts.begin(); it != m5arts.end(); ++it)
 					{
 					{
 						loot << "%s";
 						loot << "%s";
-						loot.addReplacement (MetaString::ART_NAMES, *it);
+						loot.addReplacement(MetaString::ART_NAMES, *it);
 					}
 					}
 					ms.addReplacement(loot.buildList());
 					ms.addReplacement(loot.buildList());
 				}
 				}
@@ -4052,12 +4054,12 @@ const std::string & CGSeerHut::getHoverText() const
 			case MISSION_ARMY:
 			case MISSION_ARMY:
 				{
 				{
 					MetaString loot;
 					MetaString loot;
-					for (TSlots::const_iterator it = m6creatures.begin(); it != m6creatures.end(); ++it)
+					for (std::vector<CStackBasicDescriptor>::const_iterator it = m6creatures.begin(); it != m6creatures.end(); ++it)
 					{
 					{
 						loot << "%s";
 						loot << "%s";
-						loot.addReplacement(it->second);
+						loot.addReplacement(*it);
 					}
 					}
-					ms.addReplacement	(loot.buildList());
+					ms.addReplacement(loot.buildList());
 				}
 				}
 				break;
 				break;
 			case MISSION_RESOURCES:
 			case MISSION_RESOURCES:
@@ -4068,15 +4070,15 @@ const std::string & CGSeerHut::getHoverText() const
 						if (m7resources[i])
 						if (m7resources[i])
 						{
 						{
 							loot << "%d %s";
 							loot << "%d %s";
-							loot.addReplacement (m7resources[i]);
-							loot.addReplacement (MetaString::RES_NAMES, i);
+							loot.addReplacement(m7resources[i]);
+							loot.addReplacement(MetaString::RES_NAMES, i);
 						}
 						}
 					}
 					}
-					ms.addReplacement (loot.buildList());
+					ms.addReplacement(loot.buildList());
 				}
 				}
 				break;
 				break;
 			case MISSION_PLAYER:
 			case MISSION_PLAYER:
-				ms.addReplacement (VLC->generaltexth->colors[m13489val]);
+				ms.addReplacement(VLC->generaltexth->colors[m13489val]);
 				break;
 				break;
 			default:
 			default:
 				break;
 				break;
@@ -4133,12 +4135,12 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
 						{
 						{
 							iw.components.push_back (Component (Component::PRIM_SKILL, i, m2stats[i], 0));
 							iw.components.push_back (Component (Component::PRIM_SKILL, i, m2stats[i], 0));
 							loot << "%d %s";
 							loot << "%d %s";
-							loot.addReplacement (m2stats[i]);
-							loot.addReplacement (VLC->generaltexth->primarySkillNames[i]);
+							loot.addReplacement(m2stats[i]);
+							loot.addReplacement(VLC->generaltexth->primarySkillNames[i]);
 						}		
 						}		
 					}
 					}
 					if (!isCustom)
 					if (!isCustom)
-						iw.text.addReplacement (loot.buildList());
+						iw.text.addReplacement(loot.buildList());
 				}
 				}
 					break;
 					break;
 				case MISSION_KILL_HERO:
 				case MISSION_KILL_HERO:
@@ -4161,7 +4163,7 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
 							iw.text.addReplacement(stack);
 							iw.text.addReplacement(stack);
 							if (std::count(firstVisitText.begin(), firstVisitText.end(), '%') == 2) //say where is placed monster
 							if (std::count(firstVisitText.begin(), firstVisitText.end(), '%') == 2) //say where is placed monster
 							{
 							{
-								iw.text.addReplacement (VLC->generaltexth->arraytxt[147+checkDirection()]);
+								iw.text.addReplacement(VLC->generaltexth->arraytxt[147+checkDirection()]);
 							}
 							}
 						}
 						}
 					}
 					}
@@ -4173,7 +4175,7 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
 					{
 					{
 						iw.components.push_back (Component (Component::ARTIFACT, *it, 0, 0));
 						iw.components.push_back (Component (Component::ARTIFACT, *it, 0, 0));
 						loot << "%s";
 						loot << "%s";
-						loot.addReplacement (MetaString::ART_NAMES, *it);
+						loot.addReplacement(MetaString::ART_NAMES, *it);
 					}
 					}
 					if (!isCustom)
 					if (!isCustom)
 						iw.text.addReplacement	(loot.buildList());
 						iw.text.addReplacement	(loot.buildList());
@@ -4182,11 +4184,11 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
 				case MISSION_ARMY:
 				case MISSION_ARMY:
 				{
 				{
 					MetaString loot;
 					MetaString loot;
-					for (TSlots::const_iterator it = m6creatures.begin(); it != m6creatures.end(); ++it)
+					for (std::vector<CStackBasicDescriptor>::const_iterator it = m6creatures.begin(); it != m6creatures.end(); ++it)
 					{
 					{
-						iw.components.push_back(Component(it->second));
+						iw.components.push_back(Component(*it));
 						loot << "%s";
 						loot << "%s";
-						loot.addReplacement(it->second);
+						loot.addReplacement(*it);
 					}
 					}
 					if (!isCustom)
 					if (!isCustom)
 						iw.text.addReplacement	(loot.buildList());
 						iw.text.addReplacement	(loot.buildList());
@@ -4201,8 +4203,8 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
 						{
 						{
 							iw.components.push_back (Component (Component::RESOURCE, i, m7resources[i], 0));
 							iw.components.push_back (Component (Component::RESOURCE, i, m7resources[i], 0));
 							loot << "%d %s";
 							loot << "%d %s";
-							loot.addReplacement (m7resources[i]);
-							loot.addReplacement (MetaString::RES_NAMES, i);
+							loot.addReplacement(m7resources[i]);
+							loot.addReplacement(MetaString::RES_NAMES, i);
 						}
 						}
 					}
 					}
 					if (!isCustom)
 					if (!isCustom)
@@ -4244,12 +4246,12 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
 							if (m2stats[i])
 							if (m2stats[i])
 							{
 							{
 								loot << "%d %s";
 								loot << "%d %s";
-								loot.addReplacement (m2stats[i]);
-								loot.addReplacement (VLC->generaltexth->primarySkillNames[i]);
+								loot.addReplacement(m2stats[i]);
+								loot.addReplacement(VLC->generaltexth->primarySkillNames[i]);
 							}
 							}
 						}
 						}
 						if (!isCustom)
 						if (!isCustom)
-							bd.text.addReplacement (loot.buildList());
+							bd.text.addReplacement(loot.buildList());
 					}
 					}
 					break;
 					break;
 				case CQuest::MISSION_ART:
 				case CQuest::MISSION_ART:
@@ -4258,22 +4260,22 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
 					for (std::vector<ui16>::const_iterator it = m5arts.begin(); it != m5arts.end(); ++it)
 					for (std::vector<ui16>::const_iterator it = m5arts.begin(); it != m5arts.end(); ++it)
 					{
 					{
 						loot << "%s";
 						loot << "%s";
-						loot.addReplacement (MetaString::ART_NAMES, *it);
+						loot.addReplacement(MetaString::ART_NAMES, *it);
 					}
 					}
 					if (!isCustom)
 					if (!isCustom)
-						bd.text.addReplacement (loot.buildList());
+						bd.text.addReplacement(loot.buildList());
 				}
 				}
 					break;
 					break;
 				case CQuest::MISSION_ARMY:
 				case CQuest::MISSION_ARMY:
 				{
 				{
 					MetaString loot;
 					MetaString loot;
-					for (TSlots::const_iterator it = m6creatures.begin(); it != m6creatures.end(); ++it)
+					for (std::vector<CStackBasicDescriptor>::const_iterator it = m6creatures.begin(); it != m6creatures.end(); ++it)
 					{
 					{
 						loot << "%s";
 						loot << "%s";
-						loot.addReplacement(it->second);
+						loot.addReplacement(*it);
 					}
 					}
 					if (!isCustom)
 					if (!isCustom)
-						bd.text.addReplacement	(loot.buildList());
+						bd.text.addReplacement(loot.buildList());
 				}
 				}
 					break;
 					break;
 				case CQuest::MISSION_RESOURCES:
 				case CQuest::MISSION_RESOURCES:
@@ -4284,12 +4286,12 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
 						if (m7resources[i])
 						if (m7resources[i])
 						{
 						{
 							loot << "%d %s";
 							loot << "%d %s";
-							loot.addReplacement (m7resources[i]);
-							loot.addReplacement (MetaString::RES_NAMES, i);
+							loot.addReplacement(m7resources[i]);
+							loot.addReplacement(MetaString::RES_NAMES, i);
 						}
 						}
 					}
 					}
 					if (!isCustom)
 					if (!isCustom)
-						bd.text.addReplacement (loot.buildList());
+						bd.text.addReplacement(loot.buildList());
 				}
 				}
 					break;
 					break;
 				case MISSION_KILL_HERO:
 				case MISSION_KILL_HERO:
@@ -4306,13 +4308,13 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
 						bd.text.addReplacement(cb->gameState()->map->monsters[m13489val]->getArmy()[0]);
 						bd.text.addReplacement(cb->gameState()->map->monsters[m13489val]->getArmy()[0]);
 						if (std::count(firstVisitText.begin(), firstVisitText.end(), '%') == 2) //say where is placed monster
 						if (std::count(firstVisitText.begin(), firstVisitText.end(), '%') == 2) //say where is placed monster
 						{
 						{
-							bd.text.addReplacement (VLC->generaltexth->arraytxt[147+checkDirection()]);
+							bd.text.addReplacement(VLC->generaltexth->arraytxt[147+checkDirection()]);
 						}
 						}
 					}
 					}
 				}
 				}
 				case MISSION_PLAYER:
 				case MISSION_PLAYER:
 					if (!isCustom)
 					if (!isCustom)
-						bd.text.addReplacement	(VLC->generaltexth->colors[m13489val]);
+						bd.text.addReplacement(VLC->generaltexth->colors[m13489val]);
 					break;
 					break;
 			}
 			}
 			
 			
@@ -4662,7 +4664,7 @@ void CGBonusingObject::onHeroVisit( const CGHeroInstance * h ) const
 		CCreatureSet creatures;
 		CCreatureSet creatures;
 		for (TSlots::const_iterator i = h->Slots().begin(); i != h->Slots().end(); ++i)
 		for (TSlots::const_iterator i = h->Slots().begin(); i != h->Slots().end(); ++i)
 		{
 		{
-			if(i->second.type->idNumber == 10)
+			if(i->second->type->idNumber == 10)
 				creatures.slots.insert(*i);
 				creatures.slots.insert(*i);
 		}
 		}
 		if (creatures.slots.size())
 		if (creatures.slots.size())
@@ -5014,18 +5016,18 @@ void CGPandoraBox::giveContents( const CGHeroInstance *h, bool afterBattle ) con
 		CCreatureSet ourArmy = creatures;
 		CCreatureSet ourArmy = creatures;
 		for(TSlots::const_iterator i = ourArmy.Slots().begin(); i != ourArmy.Slots().end(); i++)
 		for(TSlots::const_iterator i = ourArmy.Slots().begin(); i != ourArmy.Slots().end(); i++)
 		{ //build list of joined creatures
 		{ //build list of joined creatures
-			iw.components.push_back(Component(i->second));
+			iw.components.push_back(Component(*i->second));
 			loot << "%s";
 			loot << "%s";
-			loot.addReplacement(i->second);
+			loot.addReplacement(*i->second);
 		}
 		}
 
 
-		if (ourArmy.Slots().size() == 1 && ourArmy.Slots().begin()->second.count == 1)
+		if (ourArmy.Slots().size() == 1 && ourArmy.Slots().begin()->second->count == 1)
 			iw.text.addTxt (MetaString::ADVOB_TXT, 185);
 			iw.text.addTxt (MetaString::ADVOB_TXT, 185);
 		else
 		else
 			iw.text.addTxt (MetaString::ADVOB_TXT, 186);
 			iw.text.addTxt (MetaString::ADVOB_TXT, 186);
 
 
-		iw.text.addReplacement (loot.buildList());
-		iw.text.addReplacement (h->name);
+		iw.text.addReplacement(loot.buildList());
+		iw.text.addReplacement(h->name);
 
 
 		cb->showInfoDialog(&iw);
 		cb->showInfoDialog(&iw);
 		cb->giveCreatures (id, h, ourArmy, true);
 		cb->giveCreatures (id, h, ourArmy, true);
@@ -5409,7 +5411,7 @@ void CGOnceVisitable::onHeroVisit( const CGHeroInstance * h ) const
 			if (ID == 22) //Corpse
 			if (ID == 22) //Corpse
 			{
 			{
 				iw.text << "%s";
 				iw.text << "%s";
-				iw.text.addReplacement (MetaString::ART_NAMES, bonusType);
+				iw.text.addReplacement(MetaString::ART_NAMES, bonusType);
 			}
 			}
 			break;
 			break;
 		case 2: //res
 		case 2: //res
@@ -5748,7 +5750,7 @@ void CBank::onHeroVisit (const CGHeroInstance * h) const
 		bd.soundID = soundBase::DANGER;
 		bd.soundID = soundBase::DANGER;
 		bd.text << VLC->generaltexth->advobtxt[banktext];
 		bd.text << VLC->generaltexth->advobtxt[banktext];
 		if (ID == 16)
 		if (ID == 16)
-			bd.text.addReplacement (VLC->objh->creBanksNames[index]);
+			bd.text.addReplacement(VLC->objh->creBanksNames[index]);
 		cb->showBlockingDialog (&bd, boost::bind (&CBank::fightGuards, this, h, _1));
 		cb->showBlockingDialog (&bd, boost::bind (&CBank::fightGuards, this, h, _1));
 	}
 	}
 	else
 	else
@@ -5773,7 +5775,7 @@ void CBank::onHeroVisit (const CGHeroInstance * h) const
 		else
 		else
 		{
 		{
 			iw.text << VLC->generaltexth->advobtxt[33];
 			iw.text << VLC->generaltexth->advobtxt[33];
-			iw.text.addReplacement (VLC->objh->creBanksNames[index]);
+			iw.text.addReplacement(VLC->objh->creBanksNames[index]);
 		}
 		}
 		cb->showInfoDialog(&iw);
 		cb->showInfoDialog(&iw);
 	}
 	}
@@ -5853,8 +5855,8 @@ void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) cons
 				{
 				{
 					iw.components.push_back (Component (Component::RESOURCE, it, bc->resources[it], 0));
 					iw.components.push_back (Component (Component::RESOURCE, it, bc->resources[it], 0));
 					loot << "%d %s";
 					loot << "%d %s";
-					loot.addReplacement (iw.components.back().val);
-					loot.addReplacement (MetaString::RES_NAMES, iw.components.back().subtype);
+					loot.addReplacement(iw.components.back().val);
+					loot.addReplacement(MetaString::RES_NAMES, iw.components.back().subtype);
 					cb->giveResource (h->getOwner(), it, bc->resources[it]);
 					cb->giveResource (h->getOwner(), it, bc->resources[it]);
 				}		
 				}		
 			}
 			}
@@ -5864,7 +5866,7 @@ void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) cons
 		{
 		{
 			iw.components.push_back (Component (Component::ARTIFACT, *it, 0, 0));
 			iw.components.push_back (Component (Component::ARTIFACT, *it, 0, 0));
 			loot << "%s";
 			loot << "%s";
-			loot.addReplacement (MetaString::ART_NAMES, *it);
+			loot.addReplacement(MetaString::ART_NAMES, *it);
 			cb->giveHeroArtifact (*it, h->id ,-2);
 			cb->giveHeroArtifact (*it, h->id ,-2);
 		}
 		}
 		//display loot
 		//display loot
@@ -5873,8 +5875,8 @@ void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) cons
 			if (textID == 34)
 			if (textID == 34)
 			{
 			{
 				iw.text.addTxt(MetaString::ADVOB_TXT, 34);//Heaving defeated %s, you discover %s
 				iw.text.addTxt(MetaString::ADVOB_TXT, 34);//Heaving defeated %s, you discover %s
-				iw.text.addReplacement (MetaString::CRE_PL_NAMES, result->casualties[1].begin()->first);
-				iw.text.addReplacement (loot.buildList());
+				iw.text.addReplacement(MetaString::CRE_PL_NAMES, result->casualties[1].begin()->first);
+				iw.text.addReplacement(loot.buildList());
 			}
 			}
 			else
 			else
 				iw.text.addTxt (MetaString::ADVOB_TXT, textID);
 				iw.text.addTxt (MetaString::ADVOB_TXT, textID);
@@ -5893,20 +5895,20 @@ void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) cons
 		}
 		}
 		for (TSlots::const_iterator i = ourArmy.Slots().begin(); i != ourArmy.Slots().end(); i++)
 		for (TSlots::const_iterator i = ourArmy.Slots().begin(); i != ourArmy.Slots().end(); i++)
 		{
 		{
-			iw.components.push_back(Component(i->second));
+			iw.components.push_back(Component(*i->second));
 			loot << "%s";
 			loot << "%s";
-			loot.addReplacement (i->second);
+			loot.addReplacement(*i->second);
 		}
 		}
 
 
 		if (ourArmy.Slots().size())
 		if (ourArmy.Slots().size())
 		{
 		{
-			if (ourArmy.Slots().size() == 1 && ourArmy.Slots().begin()->second.count == 1)
+			if (ourArmy.Slots().size() == 1 && ourArmy.Slots().begin()->second->count == 1)
 				iw.text.addTxt (MetaString::ADVOB_TXT, 185);
 				iw.text.addTxt (MetaString::ADVOB_TXT, 185);
 			else
 			else
 				iw.text.addTxt (MetaString::ADVOB_TXT, 186);
 				iw.text.addTxt (MetaString::ADVOB_TXT, 186);
 
 
-			iw.text.addReplacement (loot.buildList());
-			iw.text.addReplacement (h->name);
+			iw.text.addReplacement(loot.buildList());
+			iw.text.addReplacement(h->name);
 			cb->showInfoDialog(&iw);
 			cb->showInfoDialog(&iw);
 			cb->giveCreatures (id, h, ourArmy, false);
 			cb->giveCreatures (id, h, ourArmy, false);
 		}
 		}
@@ -6164,11 +6166,11 @@ void CGSirens::onHeroVisit( const CGHeroInstance * h ) const
 		sg.garrs[h->id] = h->getArmy();
 		sg.garrs[h->id] = h->getArmy();
 		for (TSlots::const_iterator i = h->Slots().begin(); i != h->Slots().end(); i++)
 		for (TSlots::const_iterator i = h->Slots().begin(); i != h->Slots().end(); i++)
 		{
 		{
-			int drown = (int)(i->second.count * 0.3);
+			int drown = (int)(i->second->count * 0.3);
 			if(drown)
 			if(drown)
 			{
 			{
-				sg.garrs[h->id].setStackCount(i->first, i->second.count - drown);
-				xp += drown * i->second.type->valOfBonuses(Bonus::STACK_HEALTH);
+				sg.garrs[h->id].setStackCount(i->first, i->second->count - drown);
+				xp += drown * i->second->type->valOfBonuses(Bonus::STACK_HEALTH);
 			}
 			}
 		}
 		}
 
 
@@ -6528,14 +6530,15 @@ void CGLighthouse::giveBonusTo( ui8 player ) const
 
 
 void CArmedInstance::setArmy(const CCreatureSet &src)
 void CArmedInstance::setArmy(const CCreatureSet &src)
 {
 {
-	slots.clear();
-
-	for(TSlots::const_iterator i = src.Slots().begin(); i != src.Slots().end(); i++)
-	{
-		CStackInstance &inserted = slots[i->first];
-		inserted = i->second;
-		inserted.armyObj = this;
-	}
+	assert(0);
+// 	slots.clear();
+// 
+// 	for(TSlots::const_iterator i = src.Slots().begin(); i != src.Slots().end(); i++)
+// 	{
+// 		CStackInstance &inserted = slots[i->first];
+// 		inserted = i->second;
+// 		inserted.setArmyObj(this);
+// 	}
 }
 }
 
 
 CCreatureSet& CArmedInstance::getArmy() const
 CCreatureSet& CArmedInstance::getArmy() const
@@ -6549,17 +6552,18 @@ void CArmedInstance::randomizeArmy(int type)
 	int max = VLC->creh->creatures.size();
 	int max = VLC->creh->creatures.size();
 	for (TSlots::iterator j = slots.begin(); j != slots.end();j++)
 	for (TSlots::iterator j = slots.begin(); j != slots.end();j++)
 	{
 	{
-		if(j->second.idRand > max)
+		int randID = j->second->idRand;
+		if(randID > max)
 		{
 		{
-			if(j->second.idRand % 2)
-				j->second.setType(VLC->townh->towns[type].basicCreatures[(j->second.idRand-197) / 2 -1]);
+			if(randID % 2)
+				j->second->setType(VLC->townh->towns[type].basicCreatures[(randID-197) / 2 -1]);
 			else
 			else
-				j->second.setType(VLC->townh->towns[type].upgradedCreatures[(j->second.idRand-197) / 2 -1]);
+				j->second->setType(VLC->townh->towns[type].upgradedCreatures[(randID-197) / 2 -1]);
 
 
-			j->second.idRand = -1;
+			randID = -1;
 		}
 		}
 
 
-		assert(j->second.armyObj == this);
+		assert(j->second->armyObj == this);
 	}
 	}
 	return;
 	return;
 }
 }

+ 3 - 3
hch/CObjectHandler.h

@@ -62,7 +62,7 @@ public:
 	ui32 m13489val;
 	ui32 m13489val;
 	std::vector<ui32> m2stats;
 	std::vector<ui32> m2stats;
 	std::vector<ui16> m5arts; //artifacts id
 	std::vector<ui16> m5arts; //artifacts id
-	TSlots m6creatures; //pair[cre id, cre count], CreatureSet info irrelevant
+	std::vector<CStackBasicDescriptor> m6creatures; //pair[cre id, cre count], CreatureSet info irrelevant
 	std::vector<ui32> m7resources;
 	std::vector<ui32> m7resources;
 
 
 	std::string firstVisitText, nextVisitText, completedText;
 	std::string firstVisitText, nextVisitText, completedText;
@@ -349,8 +349,8 @@ public:
 	int getTotalStrength() const;
 	int getTotalStrength() const;
 	ui8 getSpellSchoolLevel(const CSpell * spell, int *outSelectedSchool = NULL) const; //returns level on which given spell would be cast by this hero (0 - none, 1 - basic etc); optionally returns number of selected school by arg - 0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic,
 	ui8 getSpellSchoolLevel(const CSpell * spell, int *outSelectedSchool = NULL) const; //returns level on which given spell would be cast by this hero (0 - none, 1 - basic etc); optionally returns number of selected school by arg - 0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic,
 	bool canCastThisSpell(const CSpell * spell) const; //determines if this hero can cast given spell; takes into account existing spell in spellbook, existing spellbook and artifact bonuses
 	bool canCastThisSpell(const CSpell * spell) const; //determines if this hero can cast given spell; takes into account existing spell in spellbook, existing spellbook and artifact bonuses
-	CStackInstance calculateNecromancy (const BattleResult &battleResult) const;
-	void showNecromancyDialog(const CStackInstance &raisedStack) const;
+	CStackBasicDescriptor calculateNecromancy (const BattleResult &battleResult) const;
+	void showNecromancyDialog(const CStackBasicDescriptor &raisedStack) const;
 
 
 	//////////////////////////////////////////////////////////////////////////
 	//////////////////////////////////////////////////////////////////////////
 
 

+ 87 - 37
lib/CCreatureSet.cpp

@@ -8,11 +8,11 @@
 #include "CGameState.h"
 #include "CGameState.h"
 #include "../hch/CGeneralTextHandler.h"
 #include "../hch/CGeneralTextHandler.h"
 
 
-const CStackInstance CCreatureSet::operator[](TSlot slot) const
+const CStackInstance &CCreatureSet::operator[](TSlot slot) const
 {
 {
 	TSlots::const_iterator i = slots.find(slot);
 	TSlots::const_iterator i = slots.find(slot);
 	if (i != slots.end())
 	if (i != slots.end())
-		return i->second;
+		return *i->second;
 	else
 	else
 		throw std::string("That slot is empty!");
 		throw std::string("That slot is empty!");
 }
 }
@@ -21,28 +21,39 @@ const CCreature* CCreatureSet::getCreature(TSlot slot) const /*workaround of map
 {
 {
 	TSlots::const_iterator i = slots.find(slot);
 	TSlots::const_iterator i = slots.find(slot);
 	if (i != slots.end())
 	if (i != slots.end())
-		return i->second.type;
+		return i->second->type;
 	else
 	else
 		return NULL;
 		return NULL;
 }
 }
 
 
 bool CCreatureSet::setCreature(TSlot slot, TCreature type, TQuantity quantity) /*slots 0 to 6 */
 bool CCreatureSet::setCreature(TSlot slot, TCreature type, TQuantity quantity) /*slots 0 to 6 */
 {
 {
-	slots[slot] = CStackInstance(type, quantity);  //brutal force
-	if (quantity == 0)
-		slots.erase(slot);
-
-	if (slots.size() > ARMY_SIZE) 
+	if(slot > 6 || slot < 0)
+	{
+		tlog1 << "Cannot set slot " << slot << std::endl;
 		return false;
 		return false;
-	else 
-		return true;
+	}
+	if(!quantity)
+	{
+		tlog2 << "Using set creature to delete stack?\n";
+		eraseStack(slot);
+	}
+
+	if(vstd::contains(slots, slot)) //remove old creature
+	{
+		eraseStack(slot);
+	}
+
+	CStackInstance *stack = new CStackInstance(type, quantity);
+	stack->armyObj = castToArmyObj(); //brutal force
+	slots[slot] = stack;
 }
 }
 
 
 TSlot CCreatureSet::getSlotFor(TCreature creature, ui32 slotsAmount/*=7*/) const /*returns -1 if no slot available */
 TSlot CCreatureSet::getSlotFor(TCreature creature, ui32 slotsAmount/*=7*/) const /*returns -1 if no slot available */
 {
 {
 	for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i)
 	for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i)
 	{
 	{
-		if(i->second.type->idNumber == creature)
+		if(i->second->type->idNumber == creature)
 		{
 		{
 			return i->first; //if there is already such creature we return its slot id
 			return i->first; //if there is already such creature we return its slot id
 		}
 		}
@@ -61,7 +72,7 @@ int CCreatureSet::getAmount(TSlot slot) const
 {
 {
 	TSlots::const_iterator i = slots.find(slot);
 	TSlots::const_iterator i = slots.find(slot);
 	if (i != slots.end())
 	if (i != slots.end())
-		return i->second.count;
+		return i->second->count;
 	else
 	else
 		return 0; //TODO? consider issuing a warning
 		return 0; //TODO? consider issuing a warning
 }
 }
@@ -71,10 +82,10 @@ bool CCreatureSet::mergableStacks(std::pair<TSlot, TSlot> &out, TSlot preferable
 	//try to match creature to our preferred stack
 	//try to match creature to our preferred stack
 	if(preferable >= 0  &&  vstd::contains(slots, preferable))
 	if(preferable >= 0  &&  vstd::contains(slots, preferable))
 	{
 	{
-		const CCreature *cr = slots.find(preferable)->second.type;
+		const CCreature *cr = slots.find(preferable)->second->type;
 		for(TSlots::const_iterator j=slots.begin(); j!=slots.end(); ++j)
 		for(TSlots::const_iterator j=slots.begin(); j!=slots.end(); ++j)
 		{
 		{
-			if(cr == j->second.type && j->first != preferable)
+			if(cr == j->second->type && j->first != preferable)
 			{
 			{
 				out.first = preferable;
 				out.first = preferable;
 				out.second = j->first;
 				out.second = j->first;
@@ -87,7 +98,7 @@ bool CCreatureSet::mergableStacks(std::pair<TSlot, TSlot> &out, TSlot preferable
 	{
 	{
 		for(TSlots::const_iterator j=slots.begin(); j!=slots.end(); ++j)
 		for(TSlots::const_iterator j=slots.begin(); j!=slots.end(); ++j)
 		{
 		{
-			if(i->second.type == j->second.type  &&  i->first != j->first)
+			if(i->second->type == j->second->type  &&  i->first != j->first)
 			{
 			{
 				out.first = i->first;
 				out.first = i->first;
 				out.second = j->first;
 				out.second = j->first;
@@ -102,7 +113,7 @@ void CCreatureSet::sweep()
 {
 {
 	for(TSlots::iterator i=slots.begin(); i!=slots.end(); ++i)
 	for(TSlots::iterator i=slots.begin(); i!=slots.end(); ++i)
 	{
 	{
-		if(!i->second.count)
+		if(!i->second->count)
 		{
 		{
 			slots.erase(i);
 			slots.erase(i);
 			sweep();
 			sweep();
@@ -113,33 +124,42 @@ void CCreatureSet::sweep()
 
 
 void CCreatureSet::addToSlot(TSlot slot, TCreature cre, TQuantity count, bool allowMerging/* = true*/)
 void CCreatureSet::addToSlot(TSlot slot, TCreature cre, TQuantity count, bool allowMerging/* = true*/)
 {
 {
-	assert(slot >= 0);
 	const CCreature *c = VLC->creh->creatures[cre];
 	const CCreature *c = VLC->creh->creatures[cre];
-	assert(!vstd::contains(slots, slot) || (slots[slot].type == c && allowMerging)); //that slot was empty or contained same type creature
-	slots[slot].type = c;
-	slots[slot].count += count;
 
 
-	//TODO
-	const CArmedInstance *armedObj = dynamic_cast<const CArmedInstance *>(this);
-	if(armedObj && !slots[slot].armyObj)
-		slots[slot].armyObj = armedObj;
+	if(!vstd::contains(slots, slot))
+	{
+		setCreature(slot, cre, count);
+	}
+	else if(slots[slot]->type == c && allowMerging); //that slot was empty or contained same type creature
+	{
+		setStackCount(slot, slots[slot]->count + count);
+	}
 }
 }
 
 
-void CCreatureSet::addToSlot(TSlot slot, const CStackInstance &stack, bool allowMerging/* = true*/)
+void CCreatureSet::addToSlot(TSlot slot, CStackInstance *stack, bool allowMerging/* = true*/)
 {
 {
-	assert(stack.type == VLC->creh->creatures[stack.type->idNumber]);
-	addToSlot(slot, stack.type->idNumber, stack.count, allowMerging	);
+	assert(stack->type == VLC->creh->creatures[stack->type->idNumber]);
+
+	if(!vstd::contains(slots, slot))
+	{
+		slots[slot] = stack;
+		stack->setArmyObj(castToArmyObj());
+	}
+	else
+	{
+		addToSlot(slot, stack->type->idNumber, stack->count, allowMerging);
+	}
 }
 }
 
 
 bool CCreatureSet::validTypes(bool allowUnrandomized /*= false*/) const
 bool CCreatureSet::validTypes(bool allowUnrandomized /*= false*/) const
 {
 {
 	for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i)
 	for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i)
 	{
 	{
-		bool isRand = (i->second.idRand != -1);
+		bool isRand = (i->second->idRand != -1);
 		if(!isRand)
 		if(!isRand)
 		{
 		{
-			assert(i->second.type);
-			assert(i->second.type == VLC->creh->creatures[i->second.type->idNumber]);
+			assert(i->second->type);
+			assert(i->second->type == VLC->creh->creatures[i->second->type->idNumber]);
 		}
 		}
 		else
 		else
 			assert(allowUnrandomized);
 			assert(allowUnrandomized);
@@ -161,7 +181,7 @@ int CCreatureSet::getArmyStrength() const
 {
 {
 	int ret = 0;
 	int ret = 0;
 	for(TSlots::const_iterator i = slots.begin(); i != slots.end(); i++)
 	for(TSlots::const_iterator i = slots.begin(); i != slots.end(); i++)
-		ret += i->second.type->AIValue * i->second.count;
+		ret += i->second->type->AIValue * i->second->count;
 	return ret;
 	return ret;
 }
 }
 
 
@@ -179,7 +199,7 @@ int CCreatureSet::stacksCount() const
 	return slots.size();
 	return slots.size();
 }
 }
 
 
-void CCreatureSet::addStack(TSlot slot, const CStackInstance &stack)
+void CCreatureSet::addStack(TSlot slot, CStackInstance *stack)
 {
 {
 	addToSlot(slot, stack, false);
 	addToSlot(slot, stack, false);
 }
 }
@@ -193,7 +213,7 @@ void CCreatureSet::setStackCount(TSlot slot, TQuantity count)
 {
 {
 	assert(vstd::contains(slots, slot));
 	assert(vstd::contains(slots, slot));
 	assert(count > 0);
 	assert(count > 0);
-	slots[slot].count = count;
+	slots[slot]->count = count;
 }
 }
 
 
 void CCreatureSet::clear()
 void CCreatureSet::clear()
@@ -204,7 +224,7 @@ void CCreatureSet::clear()
 const CStackInstance& CCreatureSet::getStack(TSlot slot) const
 const CStackInstance& CCreatureSet::getStack(TSlot slot) const
 {
 {
 	assert(vstd::contains(slots, slot));
 	assert(vstd::contains(slots, slot));
-	return slots.find(slot)->second;
+	return *slots.find(slot)->second;
 }
 }
 
 
 void CCreatureSet::eraseStack(TSlot slot)
 void CCreatureSet::eraseStack(TSlot slot)
@@ -219,7 +239,7 @@ bool CCreatureSet::contains(const CStackInstance *stack) const
 		return false;
 		return false;
 
 
 	for(TSlots::const_iterator i = slots.begin(); i != slots.end(); ++i)
 	for(TSlots::const_iterator i = slots.begin(); i != slots.end(); ++i)
-		if(&i->second == stack)
+		if(i->second == stack)
 			return true;
 			return true;
 
 
 	return false;
 	return false;
@@ -231,12 +251,17 @@ TSlot CCreatureSet::findStack(const CStackInstance *stack) const
 		return -1;
 		return -1;
 
 
 	for(TSlots::const_iterator i = slots.begin(); i != slots.end(); ++i)
 	for(TSlots::const_iterator i = slots.begin(); i != slots.end(); ++i)
-		if(&i->second == stack)
+		if(i->second == stack)
 			return i->first;
 			return i->first;
 
 
 	return -1;
 	return -1;
 }
 }
 
 
+CArmedInstance * CCreatureSet::castToArmyObj()
+{
+	return dynamic_cast<CArmedInstance *>(this);
+}
+
 CStackInstance::CStackInstance()
 CStackInstance::CStackInstance()
 {
 {
 	init();
 	init();
@@ -246,8 +271,8 @@ CStackInstance::CStackInstance(TCreature id, TQuantity Count, const CArmedInstan
 {
 {
 	init();
 	init();
 	setType(id);
 	setType(id);
+	setArmyObj(ArmyObj);
 	count = Count;
 	count = Count;
-	armyObj = ArmyObj;
 }
 }
 
 
 CStackInstance::CStackInstance(const CCreature *cre, TQuantity Count)
 CStackInstance::CStackInstance(const CCreature *cre, TQuantity Count)
@@ -274,9 +299,23 @@ int CStackInstance::getQuantityID() const
 
 
 void CStackInstance::setType(int creID)
 void CStackInstance::setType(int creID)
 {
 {
+	if(type)
+		detachFrom(const_cast<CCreature*>(type));
+
 	type = VLC->creh->creatures[creID];
 	type = VLC->creh->creatures[creID];
+
+	attachTo(const_cast<CCreature*>(type));
 }
 }
 
 
+void CStackInstance::setArmyObj(const CArmedInstance *ArmyObj)
+{
+	if(armyObj)
+		detachFrom(const_cast<CArmedInstance*>(armyObj));
+
+	armyObj = ArmyObj;
+
+	attachTo(const_cast<CArmedInstance*>(armyObj));
+}
 // void CStackInstance::getParents(TCNodes &out, const CBonusSystemNode *source /*= NULL*/) const
 // void CStackInstance::getParents(TCNodes &out, const CBonusSystemNode *source /*= NULL*/) const
 // {
 // {
 // 	out.insert(type);
 // 	out.insert(type);
@@ -293,4 +332,15 @@ void CStackInstance::setType(int creID)
 std::string CStackInstance::getQuantityTXT(bool capitalized /*= true*/) const
 std::string CStackInstance::getQuantityTXT(bool capitalized /*= true*/) const
 {
 {
 	return VLC->generaltexth->arraytxt[174 + getQuantityID()*3 + 2 - capitalized];
 	return VLC->generaltexth->arraytxt[174 + getQuantityID()*3 + 2 - capitalized];
+}
+
+CStackBasicDescriptor::CStackBasicDescriptor()
+{
+	type = NULL;
+	count = -1;
+}
+
+CStackBasicDescriptor::CStackBasicDescriptor(TCreature id, TQuantity Count)
+	: type (VLC->creh->creatures[id]), count(Count)
+{
 }
 }

+ 25 - 9
lib/CCreatureSet.h

@@ -16,22 +16,35 @@ typedef ui32 TCreature; //creature id
 
 
 const int ARMY_SIZE = 7;
 const int ARMY_SIZE = 7;
 
 
+class DLL_EXPORT CStackBasicDescriptor
+{
+public:
+	const CCreature *type;
+	TQuantity count;
 
 
-class DLL_EXPORT CStackInstance : public CBonusSystemNode
+	CStackBasicDescriptor();
+	CStackBasicDescriptor(TCreature id, TQuantity Count);
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & type & count;
+	}
+};
+
+class DLL_EXPORT CStackInstance : public CBonusSystemNode, public CStackBasicDescriptor
 {
 {
 public:
 public:
 	int idRand; //hlp variable used during loading game -> "id" placeholder for randomization
 	int idRand; //hlp variable used during loading game -> "id" placeholder for randomization
 
 
 	const CArmedInstance *armyObj; //stack must be part of some army, army must be part of some object
 	const CArmedInstance *armyObj; //stack must be part of some army, army must be part of some object
-	const CCreature *type;
-	TQuantity count;
 	ui32 experience; //TODO: handle
 	ui32 experience; //TODO: handle
 	//TODO: stack artifacts
 	//TODO: stack artifacts
 
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 	{
 		h & static_cast<CBonusSystemNode&>(*this);
 		h & static_cast<CBonusSystemNode&>(*this);
-		h & armyObj & type & count & experience;
+		h & static_cast<CStackBasicDescriptor&>(*this);
+		h & armyObj & experience;
 	}
 	}
 
 
 	//overrides CBonusSystemNode
 	//overrides CBonusSystemNode
@@ -44,26 +57,27 @@ public:
 	CStackInstance(TCreature id, TQuantity count, const CArmedInstance *ArmyObj = NULL);
 	CStackInstance(TCreature id, TQuantity count, const CArmedInstance *ArmyObj = NULL);
 	CStackInstance(const CCreature *cre, TQuantity count);
 	CStackInstance(const CCreature *cre, TQuantity count);
 	void setType(int creID);
 	void setType(int creID);
+	void setArmyObj(const CArmedInstance *ArmyObj);
 };
 };
 
 
 
 
-typedef std::map<TSlot, CStackInstance> TSlots;
+typedef std::map<TSlot, CStackInstance*> TSlots;
 
 
 
 
 
 
 class DLL_EXPORT CCreatureSet //seven combined creatures
 class DLL_EXPORT CCreatureSet //seven combined creatures
 {
 {
 public:
 public:
-	TSlots slots; //slots[slot_id]=> pair(creature_id,creature_quantity)
+	TSlots slots; //slots[slot_id]->> pair(creature_id,creature_quantity)
 	ui8 formation; //false - wide, true - tight
 	ui8 formation; //false - wide, true - tight
 
 
-	const CStackInstance operator[](TSlot slot) const; 
+	const CStackInstance &operator[](TSlot slot) const; 
 
 
 	const TSlots &Slots() const {return slots;}
 	const TSlots &Slots() const {return slots;}
 
 
 	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, TCreature cre, TQuantity count, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature
-	void addToSlot(TSlot slot, const CStackInstance &stack, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature
-	void addStack(TSlot slot, const CStackInstance &stack); //adds new stack to the army, slot must be empty
+	void addToSlot(TSlot slot, CStackInstance *stack, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature
+	void addStack(TSlot slot, CStackInstance *stack); //adds new stack to the army, slot must be empty
 	bool setCreature (TSlot slot, TCreature type, TQuantity quantity); //slots 0 to 6, if quantity=0, erases stack
 	bool setCreature (TSlot slot, TCreature type, TQuantity quantity); //slots 0 to 6, if quantity=0, erases stack
 	void clear();
 	void clear();
 	void setFormation(bool tight);
 	void setFormation(bool tight);
@@ -86,6 +100,8 @@ public:
 	
 	
 	bool contains(const CStackInstance *stack) const;
 	bool contains(const CStackInstance *stack) const;
 
 
+	CArmedInstance *castToArmyObj();
+
 	template <typename Handler> void serialize(Handler &h, const int version)
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 	{
 		h & slots & formation;
 		h & slots & formation;

+ 62 - 21
lib/CGameState.cpp

@@ -322,15 +322,21 @@ DLL_EXPORT std::string MetaString::buildList () const
 	return lista;
 	return lista;
 }
 }
 
 
-void MetaString::addReplacement(const CStackInstance &stack)
+
+void  MetaString::addCreReplacement(TCreature id, TQuantity count) //adds sing or plural name;
+{
+	assert(count);
+	if (count == 1)
+		addReplacement (CRE_SING_NAMES, id);
+	else
+		addReplacement (CRE_PL_NAMES, id);
+}
+
+void MetaString::addReplacement(const CStackBasicDescriptor &stack)
 {
 {
 	assert(stack.count); //valid count
 	assert(stack.count); //valid count
 	assert(stack.type); //valid type
 	assert(stack.type); //valid type
-
-	if (stack.count == 1)
-		addReplacement (CRE_SING_NAMES, stack.type->idNumber);
-	else
-		addReplacement (CRE_PL_NAMES, stack.type->idNumber);
+	addReplacement(stack.type->idNumber, stack.count);
 }
 }
 
 
 static CGObjectInstance * createObject(int id, int subid, int3 pos, int owner)
 static CGObjectInstance * createObject(int id, int subid, int3 pos, int owner)
@@ -691,18 +697,49 @@ CStack::CStack(const CStackInstance *Base, int O, int I, bool AO, int S)
 	: base(Base), ID(I), owner(O), slot(S), attackerOwned(AO), position(-1),   
 	: base(Base), ID(I), owner(O), slot(S), attackerOwned(AO), position(-1),   
 	counterAttacks(1)
 	counterAttacks(1)
 {
 {
+	assert(base);
+	type = base->type;
 	count = baseAmount = base->count;
 	count = baseAmount = base->count;
-	firstHPleft = valOfBonuses(Bonus::STACK_HEALTH);
-	shots = getCreature()->shots;
-	counterAttacks += valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
+}
 
 
-	//alive state indication
-	state.insert(ALIVE);
+CStack::CStack()
+{
+	init();
 }
 }
 
 
-CStack::CStack() : base(NULL), ID(-1), baseAmount(-1), firstHPleft(-1), owner(255), slot(255), attackerOwned(true), position(-1), counterAttacks(1)
+CStack::CStack(const CStackBasicDescriptor *stack, int O, int I, bool AO, int S)
+	: ID(I), owner(O), slot(S), attackerOwned(AO), position(-1), counterAttacks(1)
 {
 {
+	type = stack->type;
+	count = baseAmount = stack->count;
+}
 
 
+void CStack::init()
+{
+	base = NULL;
+	type = NULL;
+	ID = -1;
+	count = baseAmount = -1;
+	firstHPleft = -1;
+	owner = 255;
+	slot = 255;
+	attackerOwned = false;
+	position = -1;
+	counterAttacks = -1;
+}
+
+void CStack::postInit()
+{
+	assert(type);
+	assert(parents.size());
+
+	firstHPleft = valOfBonuses(Bonus::STACK_HEALTH);
+	shots = getCreature()->shots;
+	counterAttacks = 1 + valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
+	state.insert(ALIVE);  //alive state indication
+
+
+	assert(firstHPleft > 0);
 }
 }
 
 
 ui32 CStack::Speed( int turn /*= 0*/ ) const
 ui32 CStack::Speed( int turn /*= 0*/ ) const
@@ -1403,17 +1440,14 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
 					break;
 					break;
 				case 1: //monster
 				case 1: //monster
 					{
 					{
-						CCreatureSet newArmy = hero->getArmy();
 						for(int i=0; i<ARMY_SIZE; i++)
 						for(int i=0; i<ARMY_SIZE; i++)
 						{
 						{
-							if(newArmy.slotEmpty(i))
+							if(hero->slotEmpty(i))
 							{
 							{
-								newArmy.addToSlot(i, CStackInstance(curBonus.info2, curBonus.info3));
+								hero->addToSlot(i, curBonus.info2, curBonus.info3);
 								break;
 								break;
 							}
 							}
 						}
 						}
-
-						hero->setArmy(newArmy);
 					}
 					}
 					break;
 					break;
 				case 3: //artifact
 				case 3: //artifact
@@ -3447,6 +3481,13 @@ CStack * BattleInfo::generateNewStack(const CStackInstance &base, int stackID, b
 	return ret;
 	return ret;
 }
 }
 
 
+CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor &base, int stackID, bool attackerOwned, int slot, int position) const
+{
+	CStack * ret = new CStack(&base, attackerOwned ? side1 : side2, stackID, attackerOwned, slot);
+	ret->position = position;
+	return ret;
+}
+
 ui32 BattleInfo::getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const
 ui32 BattleInfo::getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const
 {
 {
 	ui32 ret = caster->getSpellCost(sp);
 	ui32 ret = caster->getSpellCost(sp);
@@ -3713,8 +3754,8 @@ int CGameState::victoryCheck( ui8 player ) const
 						&&  (ai = dynamic_cast<const CArmedInstance*>(map->objects[i]))) //contains army
 						&&  (ai = dynamic_cast<const CArmedInstance*>(map->objects[i]))) //contains army
 					{
 					{
 						for(TSlots::const_iterator i=ai->Slots().begin(); i!=ai->Slots().end(); ++i) //iterate through army
 						for(TSlots::const_iterator i=ai->Slots().begin(); i!=ai->Slots().end(); ++i) //iterate through army
-							if(i->second.type->idNumber == map->victoryCondition.ID) //it's searched creature
-								total += i->second.count;
+							if(i->second->type->idNumber == map->victoryCondition.ID) //it's searched creature
+								total += i->second->count;
 					}
 					}
 				}
 				}
 
 
@@ -4006,7 +4047,7 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
 			{
 			{
 				for(TSlots::const_iterator it = g->second.heroes[b]->Slots().begin(); it != g->second.heroes[b]->Slots().end(); ++it)
 				for(TSlots::const_iterator it = g->second.heroes[b]->Slots().begin(); it != g->second.heroes[b]->Slots().end(); ++it)
 				{
 				{
-					int toCmp = it->second.type->idNumber; //ID of creature we should compare with the best one
+					int toCmp = it->second->type->idNumber; //ID of creature we should compare with the best one
 					if(bestCre == -1 || VLC->creh->creatures[bestCre]->AIValue < VLC->creh->creatures[toCmp]->AIValue)
 					if(bestCre == -1 || VLC->creh->creatures[bestCre]->AIValue < VLC->creh->creatures[toCmp]->AIValue)
 					{
 					{
 						bestCre = toCmp;
 						bestCre = toCmp;
@@ -4552,7 +4593,7 @@ void InfoAboutHero::initFromHero( const CGHeroInstance *h, bool detailed )
 		//hide info about hero stacks counts using descriptives names ids
 		//hide info about hero stacks counts using descriptives names ids
 		for(TSlots::const_iterator i = army.Slots().begin(); i != army.Slots().end(); ++i)
 		for(TSlots::const_iterator i = army.Slots().begin(); i != army.Slots().end(); ++i)
 		{
 		{
-			army.setStackCount(i->first, i->second.getQuantityID()+1);
+			army.setStackCount(i->first, i->second->getQuantityID()+1);
 		}
 		}
 	}
 	}
 }
 }

+ 9 - 3
lib/CGameState.h

@@ -237,6 +237,7 @@ struct DLL_EXPORT BattleInfo : public CBonusSystemNode
 	std::set<CStack*> getAttackedCreatures(const CSpell * s, int skillLevel, ui8 attackerOwner, int destinationTile); //calculates stack affected by given spell
 	std::set<CStack*> getAttackedCreatures(const CSpell * s, int skillLevel, ui8 attackerOwner, int destinationTile); //calculates stack affected by given spell
 	static int calculateSpellDuration(const CSpell * spell, const CGHeroInstance * caster, int usedSpellPower);
 	static int calculateSpellDuration(const CSpell * spell, const CGHeroInstance * caster, int usedSpellPower);
 	CStack * generateNewStack(const CStackInstance &base, int stackID, bool attackerOwned, int slot, int position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
 	CStack * generateNewStack(const CStackInstance &base, int stackID, bool attackerOwned, int slot, int position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
+	CStack * generateNewStack(const CStackBasicDescriptor &base, int stackID, bool attackerOwned, int slot, int position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
 	ui32 getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell
 	ui32 getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell
 	int hexToWallPart(int hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
 	int hexToWallPart(int hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
 	int lineToWallHex(int line) const; //returns hex with wall in given line
 	int lineToWallHex(int line) const; //returns hex with wall in given line
@@ -250,13 +251,12 @@ struct DLL_EXPORT BattleInfo : public CBonusSystemNode
 	si8 canTeleportTo(int stackID, int destHex, int telportLevel); //determines if given stack can teleport to given place
 	si8 canTeleportTo(int stackID, int destHex, int telportLevel); //determines if given stack can teleport to given place
 };
 };
 
 
-class DLL_EXPORT CStack : public CBonusSystemNode
+class DLL_EXPORT CStack : public CBonusSystemNode, public CStackBasicDescriptor
 { 
 { 
 public:
 public:
 	const CStackInstance *base;
 	const CStackInstance *base;
 
 
 	ui32 ID; //unique ID of stack
 	ui32 ID; //unique ID of stack
-	ui32 count;
 	ui32 baseAmount;
 	ui32 baseAmount;
 	ui32 firstHPleft; //HP of first creature in stack
 	ui32 firstHPleft; //HP of first creature in stack
 	ui8 owner, slot;  //owner - player colour (255 for neutrals), slot - position in garrison (may be 255 for neutrals/called creatures)
 	ui8 owner, slot;  //owner - player colour (255 for neutrals), slot - position in garrison (may be 255 for neutrals/called creatures)
@@ -267,10 +267,14 @@ public:
 
 
 	std::set<ECombatInfo> state;
 	std::set<ECombatInfo> state;
 	//overrides
 	//overrides
-	const CCreature* getCreature() const {return base->type;}
+	const CCreature* getCreature() const {return type;}
 
 
 	CStack(const CStackInstance *base, int O, int I, bool AO, int S); //c-tor
 	CStack(const CStackInstance *base, int O, int I, bool AO, int S); //c-tor
+	CStack(const CStackBasicDescriptor *stack, int O, int I, bool AO, int S = 255); //c-tor
 	CStack(); //c-tor
 	CStack(); //c-tor
+
+	void init(); //set initial (invalid) values
+	void postInit(); //used to finish initialization when inheriting creature parameters is working
 	const Bonus * getEffect(ui16 id, int turn = 0) const; //effect id (SP)
 	const Bonus * getEffect(ui16 id, int turn = 0) const; //effect id (SP)
 	ui8 howManyEffectsSet(ui16 id) const; //returns amount of effects with given id set for this stack
 	ui8 howManyEffectsSet(ui16 id) const; //returns amount of effects with given id set for this stack
 	bool willMove(int turn = 0) const; //if stack has remaining move this turn
 	bool willMove(int turn = 0) const; //if stack has remaining move this turn
@@ -314,6 +318,8 @@ public:
 			base = &army->getStack(slot);
 			base = &army->getStack(slot);
 		}
 		}
 
 
+		h & static_cast<CBonusSystemNode&>(*this);
+		h & static_cast<CStackBasicDescriptor&>(*this);
 		h & ID & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks
 		h & ID & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks
 			& shots & count;
 			& shots & count;
 	}
 	}

+ 34 - 3
lib/HeroBonus.cpp

@@ -303,14 +303,28 @@ CBonusSystemNode::~CBonusSystemNode()
 
 
 }
 }
 
 
-void CBonusSystemNode::attachTo(const CBonusSystemNode *parent)
+void CBonusSystemNode::attachTo(CBonusSystemNode *parent)
 {
 {
+	assert(!vstd::contains(parents, parent));
+	parents.push_back(parent);
+	BOOST_FOREACH(Bonus *b, exportedBonuses)
+		propagateBonus(b);
 
 
+	if(parent->weActAsBonusSourceOnly())
+	{
+
+	}
+
+	parent->newChildAttached(this);
 }
 }
 
 
-void CBonusSystemNode::detachFrom(const CBonusSystemNode *parent)
+void CBonusSystemNode::detachFrom(CBonusSystemNode *parent)
 {
 {
+	assert(vstd::contains(parents, parent));
+	parents -= parent;
+	 //unpropagate bonus
 
 
+	parent->childDetached(this);
 }
 }
 
 
 void CBonusSystemNode::popBonuses(const CSelector &s)
 void CBonusSystemNode::popBonuses(const CSelector &s)
@@ -334,7 +348,7 @@ void CBonusSystemNode::popBonuses(const CSelector &s)
 void CBonusSystemNode::addNewBonus(Bonus *b)
 void CBonusSystemNode::addNewBonus(Bonus *b)
 {
 {
 	exportedBonuses.push_back(b);
 	exportedBonuses.push_back(b);
-	whereToPropagate(b)->bonuses.push_back(b);
+	propagateBonus(b);
 }
 }
 
 
 void CBonusSystemNode::removeBonus(Bonus *b)
 void CBonusSystemNode::removeBonus(Bonus *b)
@@ -376,6 +390,23 @@ TNodesVector & CBonusSystemNode::nodesOnWhichWePropagate()
 	return weActAsBonusSourceOnly() ? children : parents;
 	return weActAsBonusSourceOnly() ? children : parents;
 }
 }
 
 
+void CBonusSystemNode::propagateBonus(Bonus * b)
+{
+	whereToPropagate(b)->bonuses.push_back(b);
+}
+
+void CBonusSystemNode::newChildAttached(CBonusSystemNode *child)
+{
+	assert(!vstd::contains(children, child));
+	children.push_back(child);
+}
+
+void CBonusSystemNode::childDetached(CBonusSystemNode *child)
+{
+	assert(vstd::contains(children, child));
+	children -= child;
+}
+
 int NBonus::valOf(const CBonusSystemNode *obj, Bonus::BonusType type, int subtype /*= -1*/)
 int NBonus::valOf(const CBonusSystemNode *obj, Bonus::BonusType type, int subtype /*= -1*/)
 {
 {
 	if(obj)
 	if(obj)

+ 6 - 2
lib/HeroBonus.h

@@ -408,9 +408,13 @@ public:
 	void getParents(TNodes &out);  //retrieves list of parent nodes (nodes to inherit bonuses from), source is the prinary asker
 	void getParents(TNodes &out);  //retrieves list of parent nodes (nodes to inherit bonuses from), source is the prinary asker
 	Bonus *getBonus(const CSelector &selector);
 	Bonus *getBonus(const CSelector &selector);
 
 
-	void attachTo(const CBonusSystemNode *parent);
-	void detachFrom(const CBonusSystemNode *parent);
+	void attachTo(CBonusSystemNode *parent);
+	void detachFrom(CBonusSystemNode *parent);
 	void addNewBonus(Bonus *b); //b will be deleted with destruction of node
 	void addNewBonus(Bonus *b); //b will be deleted with destruction of node
+
+	void newChildAttached(CBonusSystemNode *child);
+	void childDetached(CBonusSystemNode *child);
+	void propagateBonus(Bonus * b);
 	//void addNewBonus(const Bonus &b); //b will copied
 	//void addNewBonus(const Bonus &b); //b will copied
 	void removeBonus(Bonus *b);
 	void removeBonus(Bonus *b);
 
 

+ 1 - 0
lib/IGameCallback.h

@@ -88,6 +88,7 @@ public:
 	virtual void giveResource(int player, int which, int val)=0;
 	virtual void giveResource(int player, int which, int val)=0;
 	virtual void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet creatures, bool remove) =0;
 	virtual void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet creatures, bool remove) =0;
 	virtual void takeCreatures (int objid, TSlots creatures) =0;
 	virtual void takeCreatures (int objid, TSlots creatures) =0;
+	virtual void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures) =0;
 	virtual void changeCreatureType (int objid, TSlot slot, TCreature creature) =0;
 	virtual void changeCreatureType (int objid, TSlot slot, TCreature creature) =0;
 	virtual void showCompInfo(ShowInInfobox * comp)=0;
 	virtual void showCompInfo(ShowInInfobox * comp)=0;
 	virtual void heroVisitCastle(int obj, int heroID)=0;
 	virtual void heroVisitCastle(int obj, int heroID)=0;

+ 3 - 2
lib/NetPacks.h

@@ -135,7 +135,8 @@ public:
 		message.push_back(TREPLACE_PLUSNUMBER);
 		message.push_back(TREPLACE_PLUSNUMBER);
 		numbers.push_back(txt);
 		numbers.push_back(txt);
 	}
 	}
-	DLL_EXPORT void addReplacement(const CStackInstance &stack); //adds sing or plural name;
+	DLL_EXPORT void addCreReplacement(TCreature id, TQuantity count); //adds sing or plural name;
+	DLL_EXPORT void addReplacement(const CStackBasicDescriptor &stack); //adds sing or plural name;
 	DLL_EXPORT std::string buildList () const;
 	DLL_EXPORT std::string buildList () const;
 	void clear()
 	void clear()
 	{
 	{
@@ -760,7 +761,7 @@ struct Component : public CPack //2002 helper for object scrips informations
 	{
 	{
 		type = 2002;
 		type = 2002;
 	}
 	}
-	DLL_EXPORT explicit Component(const CStackInstance &stack);
+	DLL_EXPORT explicit Component(const CStackBasicDescriptor &stack);
 	Component(ui16 Type, ui16 Subtype, si32 Val, si16 When)
 	Component(ui16 Type, ui16 Subtype, si32 Val, si16 When)
 		:id(Type),subtype(Subtype),val(Val),when(When)
 		:id(Type),subtype(Subtype),val(Val),when(When)
 	{
 	{

+ 6 - 3
lib/NetPacksLib.cpp

@@ -542,9 +542,9 @@ DLL_EXPORT void NewObject::applyGs( CGameState *gs )
 	case 54: //probably more options will be needed
 	case 54: //probably more options will be needed
 		o = new CGCreature();
 		o = new CGCreature();
 		{
 		{
-			CStackInstance hlp;
+			//CStackInstance hlp;
 			CGCreature *cre = static_cast<CGCreature*>(o);
 			CGCreature *cre = static_cast<CGCreature*>(o);
-			cre->slots[0] = hlp;
+			//cre->slots[0] = hlp;
 			cre->notGrowingTeam = cre->neverFlees = 0;
 			cre->notGrowingTeam = cre->neverFlees = 0;
 			cre->character = 2;
 			cre->character = 2;
 			cre->gainedArtifact = -1;
 			cre->gainedArtifact = -1;
@@ -748,6 +748,9 @@ DLL_EXPORT void BattleStart::applyGs( CGameState *gs )
 {
 {
 	gs->curB = info;
 	gs->curB = info;
 	info->belligerents[0]->battle = info->belligerents[1]->battle = info;
 	info->belligerents[0]->battle = info->belligerents[1]->battle = info;
+
+	BOOST_FOREACH(CStack *s, info->stacks)
+		s->attachTo(const_cast<CStackInstance*>(s->base));
 }
 }
 
 
 DLL_EXPORT void BattleNextRound::applyGs( CGameState *gs )
 DLL_EXPORT void BattleNextRound::applyGs( CGameState *gs )
@@ -1198,7 +1201,7 @@ DLL_EXPORT void SetSelection::applyGs( CGameState *gs )
 	gs->getPlayer(player)->currentSelection = id;
 	gs->getPlayer(player)->currentSelection = id;
 }
 }
 
 
-DLL_EXPORT Component::Component(const CStackInstance &stack)
+DLL_EXPORT Component::Component(const CStackBasicDescriptor &stack)
 	:id(CREATURE), subtype(stack.type->idNumber), val(stack.count), when(0)
 	:id(CREATURE), subtype(stack.type->idNumber), val(stack.count), when(0)
 {
 {
 
 

+ 22 - 23
lib/map.cpp

@@ -82,13 +82,12 @@ static unsigned char reverse(unsigned char arg)
 	return ret;
 	return ret;
 }
 }
 
 
-static CCreatureSet readCreatureSet(const unsigned char * bufor, int &i, int number, bool version) //version==true for >RoE maps
+void readCreatureSet(CCreatureSet *out, const unsigned char * bufor, int &i, int number, bool version) //version==true for >RoE maps
 {
 {
 	const int bytesPerCre = version ? 4 : 3,
 	const int bytesPerCre = version ? 4 : 3,
 		idBytes = version ? 2 : 1,
 		idBytes = version ? 2 : 1,
 		maxID = version ? 0xffff : 0xff;
 		maxID = version ? 0xffff : 0xff;
 
 
-	CCreatureSet ret;
 	for(int ir=0;ir < number; ir++)
 	for(int ir=0;ir < number; ir++)
 	{
 	{
 		int creID = readNormalNr(bufor,i+ir*bytesPerCre, idBytes);
 		int creID = readNormalNr(bufor,i+ir*bytesPerCre, idBytes);
@@ -96,24 +95,24 @@ static CCreatureSet readCreatureSet(const unsigned char * bufor, int &i, int num
 		if(creID == maxID) //empty slot
 		if(creID == maxID) //empty slot
 			continue;
 			continue;
 
 
-		CStackInstance hlp;
-		hlp.count = count;
+		CStackInstance *hlp = new CStackInstance();
+		hlp->count = count;
 
 
 		if(creID > maxID - 0xf)
 		if(creID > maxID - 0xf)
 		{
 		{
 			creID = maxID + 1 - creID + VLC->creh->creatures.size();//this will happen when random object has random army
 			creID = maxID + 1 - creID + VLC->creh->creatures.size();//this will happen when random object has random army
-			hlp.idRand = creID;
+			hlp->idRand = creID;
 		}
 		}
 		else
 		else
-			hlp.setType(creID);
+			hlp->setType(creID);
 
 
-		ret.slots[ir] = hlp;
+		out->addStack(ir, hlp);
 	}
 	}
 	i+=number*bytesPerCre;
 	i+=number*bytesPerCre;
 	
 	
-	ret.validTypes(true);
-	return ret;
+	out->validTypes(true);
 }
 }
+
 CMapHeader::CMapHeader(const unsigned char *map)
 CMapHeader::CMapHeader(const unsigned char *map)
 {
 {
 	int i=0;
 	int i=0;
@@ -654,7 +653,7 @@ void Mapa::loadTown( CGObjectInstance * &nobj, const unsigned char * bufor, int
 	if(readChar(bufor,i)) //has name
 	if(readChar(bufor,i)) //has name
 		nt->name = readString(bufor,i);
 		nt->name = readString(bufor,i);
 	if(readChar(bufor,i))//true if garrison isn't empty
 	if(readChar(bufor,i))//true if garrison isn't empty
-		nt->setArmy(readCreatureSet(bufor, i, 7, version > RoE));
+		readCreatureSet(nt, bufor, i, 7, version > RoE);
 	nt->formation = bufor[i]; ++i;
 	nt->formation = bufor[i]; ++i;
 	if(readChar(bufor,i)) //custom buildings info
 	if(readChar(bufor,i)) //custom buildings info
 	{
 	{
@@ -846,7 +845,7 @@ void Mapa::loadHero( CGObjectInstance * &nobj, const unsigned char * bufor, int
 		}
 		}
 	}
 	}
 	if(readChar(bufor,i))//true if hero has nonstandard garrison
 	if(readChar(bufor,i))//true if hero has nonstandard garrison
-		nhi->setArmy(readCreatureSet(bufor, i, 7, version > RoE));
+		readCreatureSet(nhi, bufor, i, 7, version > RoE);
 
 
 	nhi->formation =bufor[i]; ++i; //formation
 	nhi->formation =bufor[i]; ++i; //formation
 	bool artSet = bufor[i]; ++i; //true if artifact set is not default (hero has some artifacts)
 	bool artSet = bufor[i]; ++i; //true if artifact set is not default (hero has some artifacts)
@@ -1329,7 +1328,7 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
 					}
 					}
 					if(bufor[i++])
 					if(bufor[i++])
 					{
 					{
-						evnt->setArmy(readCreatureSet(bufor, i, 7, version > RoE)); 
+						readCreatureSet(evnt, bufor, i, 7, version > RoE); 
 					}
 					}
 					i+=4;
 					i+=4;
 				}
 				}
@@ -1373,7 +1372,7 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
 				}
 				}
 
 
 				int gcre = readNormalNr(bufor,i, 1); ++i; //number of gained creatures
 				int gcre = readNormalNr(bufor,i, 1); ++i; //number of gained creatures
-				evnt->creatures = readCreatureSet(bufor,i,gcre,(version>RoE));
+				readCreatureSet(&evnt->creatures, bufor,i,gcre,(version>RoE));
 
 
 				i+=8;
 				i+=8;
 				evnt->availableFor = readNormalNr(bufor,i, 1); ++i;
 				evnt->availableFor = readNormalNr(bufor,i, 1); ++i;
@@ -1441,8 +1440,8 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
 					monsters[cre->identifier] = cre;
 					monsters[cre->identifier] = cre;
 				}
 				}
 
 
-				CStackInstance hlp;
-				hlp.count =  readNormalNr(bufor,i, 2); i+=2;
+				CStackInstance *hlp = new CStackInstance();
+				hlp->count =  readNormalNr(bufor,i, 2); i+=2;
 				//type will be set during initialization
 				//type will be set during initialization
 				cre->slots[0] = hlp;
 				cre->slots[0] = hlp;
 
 
@@ -1535,7 +1534,7 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
 				nobj = gar;
 				nobj = gar;
 				nobj->setOwner(bufor[i++]);
 				nobj->setOwner(bufor[i++]);
 				i+=3;
 				i+=3;
-				gar->setArmy(readCreatureSet(bufor, i, 7, version > RoE));
+				readCreatureSet(gar, bufor, i, 7, version > RoE);
 				if(version > RoE)
 				if(version > RoE)
 				{
 				{
 					gar->removableUnits = bufor[i]; ++i;
 					gar->removableUnits = bufor[i]; ++i;
@@ -1559,7 +1558,7 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
 					bool areGuards = bufor[i]; ++i;
 					bool areGuards = bufor[i]; ++i;
 					if(areGuards)
 					if(areGuards)
 					{
 					{
-						art->setArmy(readCreatureSet(bufor, i, 7, version > RoE));
+						readCreatureSet(art, bufor, i, 7, version > RoE);
 					}
 					}
 					i+=4;
 					i+=4;
 				}
 				}
@@ -1581,7 +1580,7 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
 					res->message = readString(bufor,i);
 					res->message = readString(bufor,i);
 					if(bufor[i++])
 					if(bufor[i++])
 					{
 					{
-						res->setArmy(readCreatureSet(bufor, i, 7, version > RoE));
+						readCreatureSet(res, bufor, i, 7, version > RoE);
 					}
 					}
 					i+=4;
 					i+=4;
 				}
 				}
@@ -1635,7 +1634,7 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
 					box->message = readString(bufor,i);
 					box->message = readString(bufor,i);
 					if(bufor[i++])
 					if(bufor[i++])
 					{
 					{
-						box->setArmy(readCreatureSet(bufor, i, 7, version > RoE));
+						readCreatureSet(box, bufor, i, 7, version > RoE);
 					}
 					}
 					i+=4;
 					i+=4;
 				}
 				}
@@ -1684,7 +1683,7 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
 					box->spells.push_back(readNormalNr(bufor,i, 1)); ++i;
 					box->spells.push_back(readNormalNr(bufor,i, 1)); ++i;
 				}
 				}
 				int gcre = readNormalNr(bufor,i, 1); ++i; //number of gained creatures
 				int gcre = readNormalNr(bufor,i, 1); ++i; //number of gained creatures
-				box->creatures = readCreatureSet(bufor,i,gcre,(version>RoE));
+				readCreatureSet(&box->creatures, bufor,i,gcre,(version>RoE));
 				i+=8;
 				i+=8;
 				break;
 				break;
 			}
 			}
@@ -2015,11 +2014,11 @@ void Mapa::loadQuest(CQuest * guard, const unsigned char * bufor, int & i)
 	case 6:
 	case 6:
 		{
 		{
 			int typeNumber = bufor[i]; ++i;
 			int typeNumber = bufor[i]; ++i;
+			guard->m6creatures.resize(typeNumber);
 			for(int hh=0; hh<typeNumber; ++hh)
 			for(int hh=0; hh<typeNumber; ++hh)
 			{
 			{
-				ui32 creType = readNormalNr(bufor,i, 2); i+=2;
-				ui32 creNumb = readNormalNr(bufor,i, 2); i+=2;
-				guard->m6creatures[hh] = CStackInstance(creType,creNumb);
+				guard->m6creatures[hh].type = VLC->creh->creatures[readNormalNr(bufor,i, 2)]; i+=2;
+				guard->m6creatures[hh].count = readNormalNr(bufor,i, 2); i+=2;
 			}
 			}
 			break;
 			break;
 		}
 		}

+ 55 - 49
server/CGameHandler.cpp

@@ -635,7 +635,7 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
 
 
 	if (winnerHero) 
 	if (winnerHero) 
 	{
 	{
-		CStackInstance raisedStack = winnerHero->calculateNecromancy(*battleResult.data);
+		CStackBasicDescriptor raisedStack = winnerHero->calculateNecromancy(*battleResult.data);
 
 
 		// Give raised units to winner and show dialog, if any were raised.
 		// Give raised units to winner and show dialog, if any were raised.
 		if (raisedStack.type) 
 		if (raisedStack.type) 
@@ -646,12 +646,12 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
 			{
 			{
 				SetGarrisons sg;
 				SetGarrisons sg;
 				sg.garrs[winnerHero->id] = winnerHero->getArmy();
 				sg.garrs[winnerHero->id] = winnerHero->getArmy();
-				sg.garrs[winnerHero->id].addToSlot(slot, raisedStack);
+				sg.garrs[winnerHero->id].addToSlot(slot, raisedStack.type->idNumber, raisedStack.count);
 
 
 // 				if (vstd::contains(winnerHero->slots, slot)) // Add to existing stack.
 // 				if (vstd::contains(winnerHero->slots, slot)) // Add to existing stack.
-// 					sg.garrs[winnerHero->id].slots[slot].count += raisedStack.count;
+// 					sg.garrs[winnerHero->id].slots[slot]->count += raisedStack.count;
 // 				else // Create a new stack.
 // 				else // Create a new stack.
-// 					sg.garrs[winnerHero->id].slots[slot] = raisedStack;
+// 					sg.garrs[winnerHero->id].slots[slot]->= raisedStack;
 				winnerHero->showNecromancyDialog(raisedStack);
 				winnerHero->showNecromancyDialog(raisedStack);
 				sendAndApply(&sg);
 				sendAndApply(&sg);
 			}
 			}
@@ -1478,7 +1478,7 @@ void CGameHandler::setupBattle(BattleInfo * curB, int3 tile, const CArmedInstanc
 		else
 		else
 			pos = attackerLoose[army1->stacksCount()-1][k];
 			pos = attackerLoose[army1->stacksCount()-1][k];
 
 
-		CStack * stack = curB->generateNewStack(i->second, stacks.size(), true, i->first, pos);
+		CStack * stack = curB->generateNewStack(*i->second, stacks.size(), true, i->first, pos);
 		stacks.push_back(stack);
 		stacks.push_back(stack);
 	}
 	}
 	
 	
@@ -1493,7 +1493,7 @@ void CGameHandler::setupBattle(BattleInfo * curB, int3 tile, const CArmedInstanc
 		else
 		else
 			pos = defenderLoose[army2->stacksCount()-1][k];
 			pos = defenderLoose[army2->stacksCount()-1][k];
 
 
-		CStack * stack = curB->generateNewStack(i->second, stacks.size(), false, i->first, pos);
+		CStack * stack = curB->generateNewStack(*i->second, stacks.size(), false, i->first, pos);
 		stacks.push_back(stack);
 		stacks.push_back(stack);
 	}
 	}
 
 
@@ -1514,17 +1514,17 @@ void CGameHandler::setupBattle(BattleInfo * curB, int3 tile, const CArmedInstanc
 	{
 	{
 		if(hero1->getArt(13)) //ballista
 		if(hero1->getArt(13)) //ballista
 		{
 		{
-			CStack * stack = curB->generateNewStack(CStackInstance(146, 1, hero1), stacks.size(), true, 255, 52);
+			CStack * stack = curB->generateNewStack(CStackBasicDescriptor(146, 1), stacks.size(), true, 255, 52);
 			stacks.push_back(stack);
 			stacks.push_back(stack);
 		}
 		}
 		if(hero1->getArt(14)) //ammo cart
 		if(hero1->getArt(14)) //ammo cart
 		{
 		{
-			CStack * stack = curB->generateNewStack(CStackInstance(148, 1, hero1), stacks.size(), true, 255, 18);
+			CStack * stack = curB->generateNewStack(CStackBasicDescriptor(148, 1), stacks.size(), true, 255, 18);
 			stacks.push_back(stack);
 			stacks.push_back(stack);
 		}
 		}
 		if(hero1->getArt(15)) //first aid tent
 		if(hero1->getArt(15)) //first aid tent
 		{
 		{
-			CStack * stack = curB->generateNewStack(CStackInstance(147, 1, hero1), stacks.size(), true, 255, 154);
+			CStack * stack = curB->generateNewStack(CStackBasicDescriptor(147, 1), stacks.size(), true, 255, 154);
 			stacks.push_back(stack);
 			stacks.push_back(stack);
 		}
 		}
 	}
 	}
@@ -1533,23 +1533,23 @@ void CGameHandler::setupBattle(BattleInfo * curB, int3 tile, const CArmedInstanc
 		//defending hero shouldn't receive ballista (bug #551)
 		//defending hero shouldn't receive ballista (bug #551)
 		if(hero2->getArt(13) && !town) //ballista
 		if(hero2->getArt(13) && !town) //ballista
 		{
 		{
-			CStack * stack = curB->generateNewStack(CStackInstance(146, 1, hero2),  stacks.size(), false, 255, 66);
+			CStack * stack = curB->generateNewStack(CStackBasicDescriptor(146, 1),  stacks.size(), false, 255, 66);
 			stacks.push_back(stack);
 			stacks.push_back(stack);
 		}
 		}
 		if(hero2->getArt(14)) //ammo cart
 		if(hero2->getArt(14)) //ammo cart
 		{
 		{
-			CStack * stack = curB->generateNewStack(CStackInstance(148, 1, hero1), stacks.size(), false, 255, 32);
+			CStack * stack = curB->generateNewStack(CStackBasicDescriptor(148, 1), stacks.size(), false, 255, 32);
 			stacks.push_back(stack);
 			stacks.push_back(stack);
 		}
 		}
 		if(hero2->getArt(15)) //first aid tent
 		if(hero2->getArt(15)) //first aid tent
 		{
 		{
-			CStack * stack = curB->generateNewStack(CStackInstance(147, 1, hero2), stacks.size(), false, 255, 168);
+			CStack * stack = curB->generateNewStack(CStackBasicDescriptor(147, 1), stacks.size(), false, 255, 168);
 			stacks.push_back(stack);
 			stacks.push_back(stack);
 		}
 		}
 	}
 	}
 	if(town && hero1 && town->hasFort()) //catapult
 	if(town && hero1 && town->hasFort()) //catapult
 	{
 	{
-		CStack * stack = curB->generateNewStack(CStackInstance(145, 1, hero1), stacks.size(), true, 255, 120);
+		CStack * stack = curB->generateNewStack(CStackBasicDescriptor(145, 1), stacks.size(), true, 255, 120);
 		stacks.push_back(stack);
 		stacks.push_back(stack);
 	}
 	}
 	//war machines added
 	//war machines added
@@ -1559,14 +1559,14 @@ void CGameHandler::setupBattle(BattleInfo * curB, int3 tile, const CArmedInstanc
 		
 		
 	case 3: //castle
 	case 3: //castle
 		{//lower tower / upper tower
 		{//lower tower / upper tower
-			CStack * stack = curB->generateNewStack(CStackInstance(149, 1, hero2), stacks.size(), false, 255, -4);
+			CStack * stack = curB->generateNewStack(CStackBasicDescriptor(149, 1), stacks.size(), false, 255, -4);
 			stacks.push_back(stack);
 			stacks.push_back(stack);
-			stack = curB->generateNewStack(CStackInstance(149, 1, hero2), stacks.size(), false, 255, -3);
+			stack = curB->generateNewStack(CStackBasicDescriptor(149, 1), stacks.size(), false, 255, -3);
 			stacks.push_back(stack);
 			stacks.push_back(stack);
 		}
 		}
 	case 2: //citadel
 	case 2: //citadel
 		{//main tower
 		{//main tower
-			CStack * stack = curB->generateNewStack(CStackInstance(149, 1, hero2), stacks.size(), false, 255, -2);
+			CStack * stack = curB->generateNewStack(CStackBasicDescriptor(149, 1), stacks.size(), false, 255, -2);
 			stacks.push_back(stack);
 			stacks.push_back(stack);
 		}
 		}
 	}
 	}
@@ -2108,7 +2108,7 @@ void CGameHandler::giveCreatures (int objid, const CGHeroInstance * h, CCreature
 	std::set<int> takenSlots;
 	std::set<int> takenSlots;
 	for (TSlots::const_iterator it = creatures.Slots().begin(); it != creatures.Slots().end(); it++)
 	for (TSlots::const_iterator it = creatures.Slots().begin(); it != creatures.Slots().end(); it++)
 	{
 	{
-		int slot = heroArmy.getSlotFor(it->second.type->idNumber);
+		int slot = heroArmy.getSlotFor(it->second->type->idNumber);
 		if (slot >= 0)
 		if (slot >= 0)
 		{
 		{
 			heroArmy.addToSlot(slot, it->second); 	//move all matching creatures to hero's army
 			heroArmy.addToSlot(slot, it->second); 	//move all matching creatures to hero's army
@@ -2144,18 +2144,24 @@ void CGameHandler::takeCreatures (int objid, TSlots creatures) //probably we cou
 	CCreatureSet newArmy = obj->getArmy();
 	CCreatureSet newArmy = obj->getArmy();
 	while (creatures.size())
 	while (creatures.size())
 	{
 	{
-		int slot = newArmy.getSlotFor(creatures.begin()->second.type->idNumber);
+		int slot = newArmy.getSlotFor(creatures.begin()->second->type->idNumber);
 		if (slot < 0)
 		if (slot < 0)
 			break;
 			break;
-		newArmy.slots[slot].count -= creatures.begin()->second.count;
+		newArmy.slots[slot]->count -= creatures.begin()->second->count;
 		if (newArmy.getStack(slot).count < 1)
 		if (newArmy.getStack(slot).count < 1)
 			newArmy.eraseStack(slot);
 			newArmy.eraseStack(slot);
-		creatures.erase (creatures.begin());
+		creatures.erase(creatures.begin());
 	}
 	}
 	SetGarrisons sg;
 	SetGarrisons sg;
 	sg.garrs[objid] = newArmy;
 	sg.garrs[objid] = newArmy;
 	sendAndApply(&sg);
 	sendAndApply(&sg);
 }
 }
+
+void CGameHandler::takeCreatures(int objid, std::vector<CStackBasicDescriptor> creatures)
+{
+
+}
+
 void CGameHandler::showCompInfo(ShowInInfobox * comp)
 void CGameHandler::showCompInfo(ShowInInfobox * comp)
 {
 {
 	sendToAllClients(comp);
 	sendToAllClients(comp);
@@ -2629,28 +2635,28 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
 
 
 	if(what==1) //swap
 	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.slots[p1]->count) //why 254??
+		  || ((s2->tempOwner != player && s2->tempOwner != 254) && S2.slots[p2]->count))
 		{
 		{
 			complain("Can't take troops from another player!");
 			complain("Can't take troops from another player!");
 			return false;
 			return false;
 		}
 		}
 		
 		
-		std::swap(S1.slots[p1],S2.slots[p2]); //swap slots
+		std::swap(S1.slots[p1], S2.slots[p2]); //swap slots
 
 
 		//if one of them is empty, remove entry
 		//if one of them is empty, remove entry
-		if(!S1.slots[p1].count)
+		if(!S1.slots[p1]->count)
 			S1.slots.erase(p1);
 			S1.slots.erase(p1);
-		if(!S2.slots[p2].count)
+		if(!S2.slots[p2]->count)
 			S2.slots.erase(p2);
 			S2.slots.erase(p2);
 	}
 	}
 	else if(what==2)//merge
 	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.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!"))
 			return false; 
 			return false; 
 
 
-		S2.slots[p2].count += S1.slots[p1].count;
+		S2.slots[p2]->count += S1.slots[p1]->count;
 		S1.slots.erase(p1);
 		S1.slots.erase(p1);
 	}
 	}
 	else if(what==3) //split
 	else if(what==3) //split
@@ -2665,37 +2671,37 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
 
 
 		if(vstd::contains(S2.slots,p2))	 //dest. slot not free - it must be "rebalancing"...
 		if(vstd::contains(S2.slots,p2))	 //dest. slot not free - it must be "rebalancing"...
 		{
 		{
-			int total = S1.slots[p1].count + S2.slots[p2].count;
+			int total = S1.slots[p1]->count + S2.slots[p2]->count;
 			if( (total < val   &&   complain("Cannot split that stack, not enough creatures!"))
 			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.slots[p2]->type != S1.slots[p1]->type && complain("Cannot rebalance different creatures stacks!"))
 			)
 			)
 			{
 			{
 				return false; 
 				return false; 
 			}
 			}
 			
 			
-			S2.slots[p2].count = val;
-			S1.slots[p1].count = total - val;
+			S2.slots[p2]->count = val;
+			S1.slots[p1]->count = total - val;
 		}
 		}
 		else //split one stack to the two
 		else //split one stack to the two
 		{
 		{
-			if(S1.slots[p1].count < val)//not enough creatures
+			if(S1.slots[p1]->count < val)//not enough creatures
 			{
 			{
 				complain("Cannot split that stack, not enough creatures!");
 				complain("Cannot split that stack, not enough creatures!");
 				return false; 
 				return false; 
 			}
 			}
-			S2.slots[p2].type = S1.slots[p1].type;
-			S2.slots[p2].count = val;
-			S1.slots[p1].count -= val;
+			S2.slots[p2]->type = S1.slots[p1]->type;
+			S2.slots[p2]->count = val;
+			S1.slots[p1]->count -= val;
 		}
 		}
 
 
-		if ( (s1->tempOwner != player && S1.slots[p1].count < s1->getArmy().getAmount(p1) )
-		  || (s2->tempOwner != player && S2.slots[p2].count < s2->getArmy().getAmount(p2) ) )
+		if ( (s1->tempOwner != player && S1.slots[p1]->count < s1->getArmy().getAmount(p1) )
+		  || (s2->tempOwner != player && S2.slots[p2]->count < s2->getArmy().getAmount(p2) ) )
 		{
 		{
 			complain("Can't move troops of another player!");
 			complain("Can't move troops of another player!");
 			return false;
 			return false;
 		}
 		}
 
 
-		if(!S1.slots[p1].count) //if we've moved all creatures
+		if(!S1.slots[p1]->count) //if we've moved all creatures
 			S1.slots.erase(p1);
 			S1.slots.erase(p1);
 	}
 	}
 	if((s1->needsLastStack() && !S1.stacksCount()) //it's not allowed to take last stack from hero army!
 	if((s1->needsLastStack() && !S1.stacksCount()) //it's not allowed to take last stack from hero army!
@@ -2990,7 +2996,7 @@ bool CGameHandler::upgradeCreature( ui32 objid, ui8 pos, ui32 upgID )
 	CArmedInstance *obj = static_cast<CArmedInstance*>(gs->map->objects[objid]);
 	CArmedInstance *obj = static_cast<CArmedInstance*>(gs->map->objects[objid]);
 	UpgradeInfo ui = gs->getUpgradeInfo(obj->getStack(pos));
 	UpgradeInfo ui = gs->getUpgradeInfo(obj->getStack(pos));
 	int player = obj->tempOwner;
 	int player = obj->tempOwner;
-	int crQuantity = obj->slots[pos].count;
+	int crQuantity = obj->slots[pos]->count;
 	int newIDpos= vstd::findPos(ui.newID, upgID);//get position of new id in UpgradeInfo
 	int newIDpos= vstd::findPos(ui.newID, upgID);//get position of new id in UpgradeInfo
 
 
 	//check if upgrade is possible
 	//check if upgrade is possible
@@ -3023,7 +3029,7 @@ bool CGameHandler::upgradeCreature( ui32 objid, ui8 pos, ui32 upgID )
 	//upgrade creature
 	//upgrade creature
 	SetGarrisons sg;
 	SetGarrisons sg;
 	sg.garrs[objid] = obj->getArmy();
 	sg.garrs[objid] = obj->getArmy();
-	sg.garrs[objid].slots[pos].setType(upgID);
+	sg.garrs[objid].slots[pos]->setType(upgID);
 	sendAndApply(&sg);	
 	sendAndApply(&sg);	
 	return true;
 	return true;
 }
 }
@@ -3035,7 +3041,7 @@ void CGameHandler::changeCreatureType (int objid, TSlot slot, TCreature creature
 	{
 	{
 		SetGarrisons sg;
 		SetGarrisons sg;
 		sg.garrs[objid] = obj->getArmy();
 		sg.garrs[objid] = obj->getArmy();
-		sg.garrs[objid].slots[slot].setType(creature);
+		sg.garrs[objid].slots[slot]->setType(creature);
 		sendAndApply(&sg);
 		sendAndApply(&sg);
 	}
 	}
 	else
 	else
@@ -3050,7 +3056,7 @@ bool CGameHandler::garrisonSwap( si32 tid )
 		CCreatureSet csn = town->visitingHero->getArmy(), cso = town->getArmy();
 		CCreatureSet csn = town->visitingHero->getArmy(), cso = town->getArmy();
 		while(!cso.slots.empty())//while there are unmoved creatures
 		while(!cso.slots.empty())//while there are unmoved creatures
 		{
 		{
-			int pos = csn.getSlotFor(cso.slots.begin()->second.type->idNumber);
+			int pos = csn.getSlotFor(cso.slots.begin()->second->type->idNumber);
 			if(pos<0)
 			if(pos<0)
 			{
 			{
 				//try to merge two other stacks to make place
 				//try to merge two other stacks to make place
@@ -3058,7 +3064,7 @@ bool CGameHandler::garrisonSwap( si32 tid )
 				if(csn.mergableStacks(toMerge, cso.slots.begin()->first))
 				if(csn.mergableStacks(toMerge, cso.slots.begin()->first))
 				{
 				{
 					//merge
 					//merge
-					csn.slots[toMerge.second].count += csn.slots[toMerge.first].count;
+					csn.slots[toMerge.second]->count += csn.slots[toMerge.first]->count;
 					csn.slots[toMerge.first] = cso.slots.begin()->second;
 					csn.slots[toMerge.first] = cso.slots.begin()->second;
 				}
 				}
 				else
 				else
@@ -3069,12 +3075,12 @@ bool CGameHandler::garrisonSwap( si32 tid )
 			}
 			}
 			else if(csn.slots.find(pos) != csn.slots.end()) //add creatures to the existing stack
 			else if(csn.slots.find(pos) != csn.slots.end()) //add creatures to the existing stack
 			{
 			{
-				csn.slots[pos].count += cso.slots.begin()->second.count;
+				csn.slots[pos]->count += cso.slots.begin()->second->count;
 			}
 			}
 			else //move stack on the free pos
 			else //move stack on the free pos
 			{
 			{
-				csn.slots[pos].type = cso.slots.begin()->second.type;
-				csn.slots[pos].count = cso.slots.begin()->second.count;
+				csn.slots[pos]->type = cso.slots.begin()->second->type;
+				csn.slots[pos]->count = cso.slots.begin()->second->count;
 			}
 			}
 			cso.slots.erase(cso.slots.begin());
 			cso.slots.erase(cso.slots.begin());
 		}
 		}
@@ -4060,7 +4066,7 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message )
 		newArmy = hero->getArmy();
 		newArmy = hero->getArmy();
 		for(int i=0; i<ARMY_SIZE; i++)
 		for(int i=0; i<ARMY_SIZE; i++)
 			if(newArmy.slotEmpty(i))
 			if(newArmy.slotEmpty(i))
-				newArmy.addToSlot(i, CStackInstance(13,5));
+				newArmy.addToSlot(i, 13, 5);
 		sendAndApply(&sg);
 		sendAndApply(&sg);
 	}
 	}
 	else if(message == "vcmiangband") //gives 10 black knight into each slot
 	else if(message == "vcmiangband") //gives 10 black knight into each slot
@@ -4074,7 +4080,7 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message )
 		newArmy = hero->getArmy();
 		newArmy = hero->getArmy();
 		for(int i=0; i<ARMY_SIZE; i++)
 		for(int i=0; i<ARMY_SIZE; i++)
 			if(newArmy.slotEmpty(i))
 			if(newArmy.slotEmpty(i))
-				newArmy.addToSlot(i, CStackInstance(66,10));
+				newArmy.addToSlot(i, 66, 10);
 		sendAndApply(&sg);
 		sendAndApply(&sg);
 	}
 	}
 	else if(message == "vcminoldor") //all war machines
 	else if(message == "vcminoldor") //all war machines

+ 1 - 0
server/CGameHandler.h

@@ -137,6 +137,7 @@ public:
 	void giveResource(int player, int which, int val);
 	void giveResource(int player, int which, int val);
 	void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet creatures, bool remove);
 	void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet creatures, bool remove);
 	void takeCreatures (int objid, TSlots creatures);
 	void takeCreatures (int objid, TSlots creatures);
+	void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures);
 	void changeCreatureType (int objid, TSlot slot, TCreature creature);
 	void changeCreatureType (int objid, TSlot slot, TCreature creature);
 	void showCompInfo(ShowInInfobox * comp);
 	void showCompInfo(ShowInInfobox * comp);
 	void heroVisitCastle(int obj, int heroID);
 	void heroVisitCastle(int obj, int heroID);