浏览代码

Next part of creature weeks code.

DjWarmonger 15 年之前
父节点
当前提交
630dc7f7f2
共有 10 个文件被更改,包括 262 次插入129 次删除
  1. 5 1
      hch/CCreatureHandler.cpp
  2. 6 3
      hch/CCreatureHandler.h
  3. 16 9
      hch/CObjectHandler.cpp
  4. 1 0
      lib/CGameState.cpp
  5. 65 6
      lib/HeroBonus.cpp
  6. 5 3
      lib/HeroBonus.h
  7. 2 1
      lib/NetPacks.h
  8. 33 1
      lib/NetPacksLib.cpp
  9. 128 104
      server/CGameHandler.cpp
  10. 1 1
      server/CGameHandler.h

+ 5 - 1
hch/CCreatureHandler.cpp

@@ -11,6 +11,7 @@
 #include <boost/algorithm/string/find.hpp>
 #include <boost/algorithm/string/replace.hpp>
 #include "../lib/VCMI_Lib.h"
+#include "../lib/CGameState.h"
 
 using namespace boost::assign;
 extern CLodHandler * bitmaph;
@@ -136,7 +137,10 @@ void CCreature::addBonus(int val, int type, int subtype /*= -1*/)
 	Bonus added(Bonus::PERMANENT, type, Bonus::CREATURE_ABILITY, val, idNumber, subtype, Bonus::BASE_NUMBER);
 	bonuses.push_back(added);
 }
-
+void CCreature::getParents(TNodes &out, const CBonusSystemNode *root /*= NULL*/) const
+{
+	out.insert(VLC->creh->globalEffects);
+}
 bool CCreature::isMyUpgrade(const CCreature *anotherCre) const
 {
 	//TODO upgrade of upgrade?

+ 6 - 3
hch/CCreatureHandler.h

@@ -8,6 +8,7 @@
 
 #include "CSoundBase.h"
 #include "../lib/HeroBonus.h"
+#include "../lib/CGameState.h"
 
 /*
  * CCreatureHandler.h, part of VCMI engine
@@ -21,6 +22,7 @@
 
 class CLodHandler;
 class CCreatureHandler;
+class CCreature;
 
 class DLL_EXPORT CCreature : public CBonusSystemNode
 {
@@ -60,7 +62,7 @@ public:
 	ui32 getMaxDamage() const;
 
 	void addBonus(int val, int type, int subtype = -1);
-
+	void getParents(TNodes &out, const CBonusSystemNode *root /*= NULL*/) const;
 
 	template<typename RanGen>
 	int getRandomAmount(RanGen &ranGen)
@@ -95,8 +97,9 @@ public:
 
 
 class DLL_EXPORT CCreatureHandler
-{
+{	
 public:
+	CBonusSystemNode *globalEffects;
 	std::set<int> notUsedMonsters;
 	std::vector<CCreature*> creatures; //creature ID -> creature info
 	std::map<int,std::vector<CCreature*> > levelCreatures; //level -> list of creatures
@@ -123,7 +126,7 @@ public:
 	{
 		//TODO: should be optimized, not all these informations needs to be serialized (same for ccreature)
 		h & notUsedMonsters & creatures & nameToID & idToProjectile & idToProjectileSpin & factionToTurretCreature;
-		h & levelCreatures;		
+		h & levelCreatures & globalEffects;		
 	}
 };
 

+ 16 - 9
hch/CObjectHandler.cpp

@@ -1736,10 +1736,12 @@ void CGDwelling::newTurn() const
 	{
 		if(creatures[i].second.size())
 		{
+			CCreature *cre = VLC->creh->creatures[creatures[i].second[0]];
+			TQuantity amount = cre->growth * (1 + cre->valOfBonuses(Bonus::CREATURE_GROWTH_PERCENT)/100) + cre->valOfBonuses(Bonus::CREATURE_GROWTH);
 			if(false /*accumulate creatures*/)
-				sac.creatures[i].first += VLC->creh->creatures[creatures[i].second[0]]->growth;
+				sac.creatures[i].first += amount;
 			else
-				sac.creatures[i].first = VLC->creh->creatures[creatures[i].second[0]]->growth;
+				sac.creatures[i].first = amount;
 			change = true;
 		}
 	}
@@ -1923,8 +1925,9 @@ int CGTownInstance::creatureGrowth(const int & level) const
 {
 	if (level<0 || level >=CREATURES_PER_TOWN)
 		return 0;
+	TCreature creid = town->basicCreatures[level];
 		
-	int ret = VLC->creh->creatures[town->basicCreatures[level]]->growth;
+	int ret = VLC->creh->creatures[creid]->growth;
 	switch(fortLevel())
 	{
 	case 3:
@@ -1932,29 +1935,33 @@ int CGTownInstance::creatureGrowth(const int & level) const
 	case 2:
 		ret*=(1.5); break;
 	}
+	ret *= (1 + VLC->creh->creatures[creid]->valOfBonuses(Bonus::CREATURE_GROWTH_PERCENT)/100); // double growth or plague
 	if(tempOwner != NEUTRAL_PLAYER)
 	{
 		ret *= (1 + cb->gameState()->players[tempOwner].valOfBonuses(Bonus::CREATURE_GROWTH_PERCENT)/100); //Statue of Legion
 		for (std::vector<CGDwelling*>::const_iterator it = cb->gameState()->players[tempOwner].dwellings.begin(); it != cb->gameState()->players[tempOwner].dwellings.end(); ++it)
 		{ //+1 for each dwelling
-			if (VLC->creh->creatures[town->basicCreatures[level]]->idNumber == (*it)->creatures[0].second[0])
+			if (VLC->creh->creatures[creid]->idNumber == (*it)->creatures[0].second[0])
 				++ret;
 		}
 	}
 	if(getHordeLevel(0)==level)
 		if((builtBuildings.find(18)!=builtBuildings.end()) || (builtBuildings.find(19)!=builtBuildings.end()))
-			ret+=VLC->creh->creatures[town->basicCreatures[level]]->hordeGrowth;
+			ret+=VLC->creh->creatures[creid]->hordeGrowth;
 	if(getHordeLevel(1)==level)
 		if((builtBuildings.find(24)!=builtBuildings.end()) || (builtBuildings.find(25)!=builtBuildings.end()))
-			ret+=VLC->creh->creatures[town->basicCreatures[level]]->hordeGrowth;
+			ret+=VLC->creh->creatures[creid]->hordeGrowth;
 
 	//support for legs of legion etc.
 	if(garrisonHero)
 		ret += garrisonHero->valOfBonuses(Bonus::CREATURE_GROWTH, level);
 	if(visitingHero)
 		ret += visitingHero->valOfBonuses(Bonus::CREATURE_GROWTH, level);
+	//spcecial week
+	ret += VLC->creh->creatures[creid]->valOfBonuses(Bonus::CREATURE_GROWTH);
 	if(builtBuildings.find(26)!=builtBuildings.end()) //grail - +50% to ALL growth
 		ret*=1.5;
+	amax(ret, 1); //even plague week gives at least one creature
 	return ret;//check CCastleInterface.cpp->CCastleInterface::CCreaInfo::clickRight if this one will be modified
 }
 int CGTownInstance::dailyIncome() const
@@ -6518,11 +6525,11 @@ void CArmedInstance::randomizeArmy(int type)
 void CArmedInstance::getParents(TCNodes &out, const CBonusSystemNode *root /*= NULL*/) const
 {
 	const PlayerState *p = cb->getPlayerState(tempOwner);
-	if(!p) //occurs when initializing starting hero and heroes from the pool, also for neutral armed objects
-		out.insert(&cb->gameState()->globalEffects);
-	else
+	if(p)
 		out.insert(p); //hero always inherits bonuses from player
 
+	out.insert(&cb->gameState()->globalEffects); //global effect are always active I believe
+
 	if(battle)
 		out.insert(battle);
 }

+ 1 - 0
lib/CGameState.cpp

@@ -1202,6 +1202,7 @@ CGameState::~CGameState()
 
 void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
 {
+	VLC->creh->globalEffects = &globalEffects;
 	struct HLP
 	{
 		//it's assumed that given hero should receive the bonus

+ 65 - 6
lib/HeroBonus.cpp

@@ -64,6 +64,54 @@ int DLL_EXPORT BonusList::totalValue() const
 		return valFirst;
 }
 
+int DLL_EXPORT BonusList::valPercent(Bonus::BonusType type, const CSelector &selector, int val) const
+{
+	int base = val;
+	int percentToBase = 0;
+	int percentToAll = 0;
+	int additive = 0;
+	int indepMax = 0;
+	bool hasIndepMax = false;
+
+	for(const_iterator i = begin(); i != end(); i++)
+	{
+		switch(i->valType)
+		{
+		case Bonus::BASE_NUMBER:
+			base += i->val;
+			break;
+		case Bonus::PERCENT_TO_ALL:
+			percentToAll += i->val;
+			break;
+		case Bonus::PERCENT_TO_BASE:
+			percentToBase += i->val;
+			break;
+		case Bonus::ADDITIVE_VALUE:
+			additive += i->val;
+			break;
+		case Bonus::INDEPENDENT_MAX:
+			if (!indepMax)
+			{
+				indepMax = i->val;
+				hasIndepMax = true;
+			}
+			else
+			{
+				amax(indepMax, i->val);
+			}
+
+			break;
+		}
+	}
+	int modifiedBase = base + (base * percentToBase) / 100;
+	modifiedBase += additive;
+	int valFirst = (modifiedBase * (100 + percentToAll)) / 100;
+	if (hasIndepMax)
+		return std::max(valFirst, indepMax);
+	else
+		return valFirst;
+}
+
 const DLL_EXPORT Bonus * BonusList::getFirst(const CSelector &selector) const
 {
 	for (const_iterator i = begin(); i != end(); i++)
@@ -482,12 +530,23 @@ bool ILimiter::limit(const Bonus &b, const CBonusSystemNode &node) const /*retur
 
 bool CCreatureTypeLimiter::limit(const Bonus &b, const CBonusSystemNode &node) const
 {
-	if(node.nodeType != CBonusSystemNode::STACK)
-		return true;
-
-	const CCreature *c = (static_cast<const CStackInstance *>(&node))->type;
-
-	return c != creature   &&   (!includeUpgrades || !creature->isMyUpgrade(c)); //drop bonus if it's not our creature and (we dont check upgrades or its not our upgrade)
+	switch (node.nodeType)
+	{	
+		case CBonusSystemNode::STACK:
+		{
+			const CCreature *c = (static_cast<const CStackInstance *>(&node))->type;
+			return c != creature   &&   (!includeUpgrades || !creature->isMyUpgrade(c));
+		}	//drop bonus if it's not our creature and (we dont check upgrades or its not our upgrade)
+			break;
+		case CBonusSystemNode::CREATURE:
+		{
+			const CCreature *c = (static_cast<const CCreature *>(&node));
+			return c != creature   &&   (!includeUpgrades || !creature->isMyUpgrade(c));
+		}
+			break;
+		default:
+			return true;
+	}
 }
 CCreatureTypeLimiter::CCreatureTypeLimiter(const CCreature &Creature, ui8 IncludeUpgrades /*= true*/)
 	:creature(&Creature), includeUpgrades(IncludeUpgrades)

+ 5 - 3
lib/HeroBonus.h

@@ -69,7 +69,7 @@ namespace PrimarySkill
 	BONUS_NAME(WATER_SPELLS) \
 	BONUS_NAME(EARTH_SPELLS) \
 	BONUS_NAME(GENERATE_RESOURCE) /*daily value, uses subtype (resource type)*/  \
-	BONUS_NAME(CREATURE_GROWTH) /*for legion artifacts: value - week growth bonus, subtype - monster level*/  \
+	BONUS_NAME(CREATURE_GROWTH) /*for legion artifacts: value - week growth bonus, subtype - monster level if aplicable*/  \
 	BONUS_NAME(WHIRLPOOL_PROTECTION) /*hero won't lose army when teleporting through whirlpool*/  \
 	BONUS_NAME(SPELL) /*hero knows spell, val - skill level (0 - 3), subtype - spell id*/  \
 	BONUS_NAME(SPELLS_OF_LEVEL) /*hero knows all spells of given level, val - skill level; subtype - level*/  \
@@ -192,7 +192,8 @@ struct DLL_EXPORT Bonus
 		SECONDARY_SKILL,
 		HERO_SPECIAL,
 		ARMY,
-		CAMPAIGN_BONUS
+		CAMPAIGN_BONUS,
+		SPECIAL_WEEK
 	};
 
 	enum LimitEffect
@@ -298,6 +299,7 @@ class BonusList : public std::list<Bonus>
 {
 public:
 	int DLL_EXPORT totalValue() const; //subtype -> subtype of bonus, if -1 then any
+	int DLL_EXPORT valPercent(Bonus::BonusType type, const CSelector &selector, int val) const;
 	void DLL_EXPORT getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *source = NULL) const;
 	void DLL_EXPORT getBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *source = NULL) const;
 	void DLL_EXPORT getModifiersWDescr(TModDescr &out) const;
@@ -379,7 +381,7 @@ public:
 
 	enum ENodeTypes
 	{
-		UNKNOWN, STACK, SPECIALITY, ARTIFACT
+		UNKNOWN, STACK, SPECIALITY, ARTIFACT, CREATURE
 	};
 };
 

+ 2 - 1
lib/NetPacks.h

@@ -690,7 +690,7 @@ struct SetAvailableArtifacts  : public CPackForClient //519
 
 struct NewTurn : public CPackForClient //101
 {
-	enum weekType {NORMAL, DOUBLE_GROWTH, BONUS_GROWTH, PLAGUE, CUSTOM};
+	enum weekType {NORMAL, DOUBLE_GROWTH, BONUS_GROWTH, PLAGUE, CUSTOM, NO_ACTION, NONE};
 
 	DLL_EXPORT void applyGs(CGameState *gs);
 
@@ -711,6 +711,7 @@ struct NewTurn : public CPackForClient //101
 	ui32 day;
 	bool resetBuilded;
 	weekType specialWeek;
+	TQuantity creatureid; //for creature weeks
 
 	NewTurn(){type = 101;};
 

+ 33 - 1
lib/NetPacksLib.cpp

@@ -632,10 +632,42 @@ DLL_EXPORT void NewTurn::applyGs( CGameState *gs )
 	BOOST_FOREACH(CGHeroInstance *h, gs->map->heroes)
 		h->bonuses.remove_if(Bonus::OneDay);
 
-	if(gs->getDate(1) == 1) //new week, Monday that is
+	if(gs->getDate(1) == 1 && specialWeek != NO_ACTION) //new week, Monday that is
 	{
 		BOOST_FOREACH(CGHeroInstance *h, gs->map->heroes)
 			h->bonuses.remove_if(Bonus::OneWeek);
+
+		gs->globalEffects.bonuses.remove_if(Bonus::OneWeek);
+
+		Bonus b;
+		b.duration = Bonus::ONE_WEEK;
+		b.source = Bonus::SPECIAL_WEEK;
+		b.effectRange = Bonus::NO_LIMIT;
+		switch (specialWeek)
+		{
+			case DOUBLE_GROWTH:
+				b.val = 100;
+				b.type = Bonus::CREATURE_GROWTH_PERCENT;
+				b.limiter = new CCreatureTypeLimiter(*VLC->creh->creatures[creatureid], false);
+				b.valType = Bonus::PERCENT_TO_ALL;
+				break;
+			case BONUS_GROWTH:
+				b.val = 5;
+				b.type = Bonus::CREATURE_GROWTH;
+				b.limiter = new CCreatureTypeLimiter(*VLC->creh->creatures[creatureid], false);
+				b.valType = Bonus::BASE_NUMBER;
+				break;
+			case PLAGUE:
+				b.val = -50;
+				b.type = Bonus::CREATURE_GROWTH_PERCENT;
+				b.valType = Bonus::PERCENT_TO_ALL;
+				break;
+			default:
+				b.val = 0;
+
+		}
+		if (b.val)
+			gs->globalEffects.bonuses.push_back(b);
 	}
 
 	//count days without town

+ 128 - 104
server/CGameHandler.cpp

@@ -965,7 +965,7 @@ static bool evntCmp(const CMapEvent *a, const CMapEvent *b)
 	return *a < *b;
 }
 
-void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=false)
+void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=false, bool clear = false)
 {// bool forced = true - if creature should be replaced, if false - only if no creature was set
 
 	if (forced || town->creatures[CREATURES_PER_TOWN].second.empty())//we need to change creature
@@ -986,7 +986,10 @@ void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=fa
 			ui32 creapos = rand()%dwellings[dwellpos]->creatures.size();//for multi-creature dwellings like Golem Factory
 			ui32 creature = dwellings[dwellpos]->creatures[creapos].second[0];
 			
-			ssi.creatures[CREATURES_PER_TOWN].first = VLC->creh->creatures[creature]->growth;
+			if (clear)
+				ssi.creatures[CREATURES_PER_TOWN].first = std::max((ui32)1, (VLC->creh->creatures[creature]->growth)/2);
+			else
+				ssi.creatures[CREATURES_PER_TOWN].first = VLC->creh->creatures[creature]->growth;
 			ssi.creatures[CREATURES_PER_TOWN].second.push_back(creature);
 			sendAndApply(&ssi);
 		}
@@ -998,10 +1001,60 @@ void CGameHandler::newTurn()
 	NewTurn n;
 	n.day = gs->day + 1;
 	n.resetBuilded = true;
+	bool newmonth = false;
 	
 	std::map<ui8, si32> hadGold;//starting gold - for buildings like dwarven treasury
 	srand(time(NULL));
 
+	if (getDate(1) == 7 && getDate(0)>1) //new week (day numbers are confusing, as day was not yet switched)
+	{
+		int monsterid;
+		int monthType = rand()%100;
+		if(getDate(4) == 28) //new month
+		{
+			newmonth = true;
+			if (monthType < 100) //double growth
+			{
+				//spawn wandering monsters
+				n.specialWeek = NewTurn::DOUBLE_GROWTH;
+				std::vector<int3>::iterator tile;
+				std::vector<int3> tiles;
+				getFreeTiles(tiles);
+				ui32 amount = (tiles.size()) >> 6;
+				std::random_shuffle(tiles.begin(), tiles.end(), p_myrandom);
+
+				//std::pair<int,int> newMonster(54, VLC->creh->pickRandomMonster(boost::ref(rand)));
+				std::pair<int,int> newMonster(54, 1); //pikeman
+				n.creatureid = newMonster.second;
+				for (int i = 0; i < amount; ++i)
+				{
+					tile = tiles.begin();
+					TerrainTile *tinfo = &gs->map->terrain[tile->x][tile->y][tile->z];
+					NewObject no;
+					no.ID = newMonster.first;
+					no.subID= newMonster.second;
+					no.pos = *tile;
+					sendAndApply(&no);
+					tiles.erase(tile); //not use it again
+				}
+			}
+			else if (monthType < 98)
+				n.specialWeek = NewTurn::NORMAL;
+			else
+				n.specialWeek = NewTurn::PLAGUE;
+		}
+		else //it's a week, but not full month
+		{
+			newmonth = false;
+			if (monthType < 20)
+			{
+				n.specialWeek = NewTurn::BONUS_GROWTH; //+5
+				std::pair<int,int> newMonster (54, VLC->creh->pickRandomMonster(boost::ref(rand)));
+				monsterid = newMonster.second;
+			}
+		}
+	}
+
 	std::map<ui32,CGHeroInstance *> pool = gs->hpool.heroesPool;
 
 	for ( std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
@@ -1060,24 +1113,12 @@ void CGameHandler::newTurn()
 			
 			if(gs->day) //not first day
 			{
-				switch(h->getSecSkillLevel(13)) //handle estates - give gold
-				{
-				case 1: //basic
-					n.res[i->first][6] += 125;
-					break;
-				case 2: //advanced
-					n.res[i->first][6] += 250;
-					break;
-				case 3: //expert
-					n.res[i->first][6] += 500;
-					break;
-				}
+				n.res[i->first][6] += h->valOfBonuses(Selector::typeSybtype(Bonus::SECONDARY_SKILL, 13)); //estates
+
 				for (int k = 0; k < RESOURCE_QUANTITY; k++)
 				{
 					n.res[i->first][k] += h->valOfBonuses(Bonus::GENERATE_RESOURCE, k);
 				}
-				//TODO player bonuses
-
 			}
 		}
 		//n.res.push_back(r);
@@ -1088,24 +1129,10 @@ void CGameHandler::newTurn()
 		if(gs->getDate(1)==7) //first day of week
 		{
 			if ((*j)->subID == 5 && vstd::contains((*j)->builtBuildings, 22))
-				setPortalDwelling(*j, true);//set creatures for Portal of Summoning
-			
+				setPortalDwelling(*j, true, (n.specialWeek == NewTurn::PLAGUE ? true : false)); //set creatures for Portal of Summoning
+
 			if  ((**j).subID == 1 && gs->getDate(0) && player < PLAYER_LIMIT && vstd::contains((**j).builtBuildings, 22))//dwarven treasury
 					n.res[player][6] += hadGold[player]/10; //give 10% of starting gold
-		
-			SetAvailableCreatures sac;
-			sac.tid = (**j).id;
-			sac.creatures = (**j).creatures;
-			for(int k=0;k<CREATURES_PER_TOWN;k++) //creature growths
-			{
-				if((**j).creatureDwelling(k))//there is dwelling (k-level)
-				{
-					sac.creatures[k].first += (**j).creatureGrowth(k);
-					if(!gs->getDate(0)) //first day of game: use only basic growths
-						amin(sac.creatures[k].first, VLC->creh->creatures[(*j)->town->basicCreatures[k]]->growth);
-				}
-			}
-			n.cres.push_back(sac);
 		}
 		if(gs->day  &&  player < PLAYER_LIMIT)//not the first day and town not neutral
 		{
@@ -1126,13 +1153,29 @@ void CGameHandler::newTurn()
 			n.res[player][6] += (**j).dailyIncome();
 		}
 		handleTownEvents(*j, n);
-		if ((**j).subID == 2 && vstd::contains((**j).builtBuildings, 26)) // Skyship, probably easier to handle same as Veil of darkness
-		{ //do it every new day after veils apply
-			FoWChange fw;
-			fw.mode = 1;
-			fw.player = player;
-			getAllTiles(fw.tiles, player, -1, 0);
-			sendAndApply (&fw);
+		if (vstd::contains((**j).builtBuildings, 26)) 
+		{
+			switch ((**j).subID)
+			{
+				case 2: // Skyship, probably easier to handle same as Veil of darkness
+					{ //do it every new day after veils apply
+						FoWChange fw;
+						fw.mode = 1;
+						fw.player = player;
+						getAllTiles(fw.tiles, player, -1, 0);
+						sendAndApply (&fw);
+					}
+					break;
+				case 3: //Deity of Fire
+					{
+						if (getDate(0) > 1)
+						{
+							n.specialWeek = NewTurn::DOUBLE_GROWTH;
+							n.creatureid = 42; //familiar
+						}
+					}
+					break;
+			}
 		}
 		if ((**j).hasBonusOfType (Bonus::DARKNESS))
 		{
@@ -1148,84 +1191,65 @@ void CGameHandler::newTurn()
 		pickAllowedArtsSet(saa.arts);
 		sendAndApply(&saa);
 	}
-	if (getDate(1) == 7 && getDate(0)>1) //new week (day numbers are confusing, as day was not yet switched)
+
+	sendAndApply(&n);
+
+	if (gs->getDate(1)==1) //first day of week, day has already been changed
 	{
-		int monsterid;
-		bool newmonth;
-		int monthType = rand()%100;
-		if(getDate(4) == 28) //new month
+		NewTurn n2; //just to handle  creature growths after bonuses are applied
+		n2.specialWeek = NewTurn::NO_ACTION;
+		n2.day = gs->day;
+
+		for(std::vector<CGTownInstance *>::iterator j = gs->map->towns.begin(); j!=gs->map->towns.end(); j++)//handle towns
 		{
-			newmonth = true;
-			if (monthType < 60) //double growth
+			ui8 player = (*j)->tempOwner;
+			SetAvailableCreatures sac;
+			sac.tid = (**j).id;
+			sac.creatures = (**j).creatures;
+			for (int k=0; k < CREATURES_PER_TOWN; k++) //creature growths
 			{
-				//spawn wandering monsters
-				n.specialWeek = NewTurn::DOUBLE_GROWTH;
-				std::vector<int3>::iterator tile;
-				std::vector<int3> tiles;
-				getFreeTiles(tiles);
-				ui32 amount = (tiles.size()) >> 6;
-				std::random_shuffle(tiles.begin(), tiles.end(), p_myrandom);
-
-				std::pair<int,int> newMonster(54, VLC->creh->pickRandomMonster(boost::ref(rand)));
-				monsterid = newMonster.second;
-				for (int i = 0; i < amount; ++i)
+				if((**j).creatureDwelling(k))//there is dwelling (k-level)
 				{
-					tile = tiles.begin();
-					TerrainTile *tinfo = &gs->map->terrain[tile->x][tile->y][tile->z];
-					NewObject no;
-					no.ID = newMonster.first;
-					no.subID= newMonster.second;
-					no.pos = *tile;
-					sendAndApply(&no);
-					tiles.erase(tile); //not use it again
+					sac.creatures[k].first += (**j).creatureGrowth(k);
+					if(gs->getDate(0) == 1) //first day of game: use only basic growths
+						amin(sac.creatures[k].first, VLC->creh->creatures[(*j)->town->basicCreatures[k]]->growth);
 				}
 			}
-			else if (monthType < 98)
-				n.specialWeek = NewTurn::NORMAL;
-			else
-				n.specialWeek = NewTurn::PLAGUE;
+			n2.cres.push_back(sac);
 		}
-		else //it's a week, but not full month
+		if (gs->getDate(0) > 1)
 		{
-			newmonth = false;
-			if (monthType < 20)
+			InfoWindow iw; //new week info
+			int msgid;
+			switch (n.specialWeek)
 			{
-				n.specialWeek = NewTurn::BONUS_GROWTH; //+5
-				std::pair<int,int> newMonster (54, VLC->creh->pickRandomMonster(boost::ref(rand)));
-				monsterid = newMonster.second;
+				case NewTurn::DOUBLE_GROWTH:
+					iw.text.addTxt(MetaString::ARRAY_TXT, 131);
+					iw.text.addReplacement(MetaString::CRE_SING_NAMES, n.creatureid);
+					iw.text.addReplacement(MetaString::CRE_SING_NAMES, n.creatureid);
+					break;
+				case NewTurn::PLAGUE:
+					iw.text.addTxt(MetaString::ARRAY_TXT, 132);
+					break;
+				case NewTurn::BONUS_GROWTH:
+					iw.text.addTxt(MetaString::ARRAY_TXT, 134);
+					iw.text.addReplacement(MetaString::CRE_SING_NAMES, n.creatureid);
+					iw.text.addReplacement(MetaString::CRE_SING_NAMES, n.creatureid);
+					break;
+				default:
+					iw.text.addTxt(MetaString::ARRAY_TXT, (newmonth ? 130 : 133));
+					iw.text.addReplacement(MetaString::ARRAY_TXT, 43 + rand()%15);
 			}
-		}
 
-		InfoWindow iw;
-		int msgid;
-		switch (n.specialWeek)
-		{
-			case NewTurn::DOUBLE_GROWTH:
-				iw.text.addTxt(MetaString::ARRAY_TXT, 131);
-				iw.text.addReplacement(MetaString::CRE_SING_NAMES, monsterid);
-				iw.text.addReplacement(MetaString::CRE_SING_NAMES, monsterid);
-				break;
-			case NewTurn::PLAGUE:
-				iw.text.addTxt(MetaString::ARRAY_TXT, 132);
-				break;
-			case NewTurn::BONUS_GROWTH:
-				iw.text.addTxt(MetaString::ARRAY_TXT, 134);
-				iw.text.addReplacement(MetaString::CRE_SING_NAMES, monsterid);
-				iw.text.addReplacement(MetaString::CRE_SING_NAMES, monsterid);
-				break;
-			default:
-				iw.text.addTxt(MetaString::ARRAY_TXT, (newmonth ? 130 : 133));
-				iw.text.addReplacement(MetaString::ARRAY_TXT, 43 + rand()%15);
+			for (std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end(); i++)
+			{
+				iw.player = i->first;
+				sendAndApply(&iw);
+			}
 		}
 
-		for (std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end(); i++)
-		{
-			iw.player = i->first;
-			sendAndApply(&iw);
-		}
+		sendAndApply(&n2);
 	}
-
-	sendAndApply(&n);
 	tlog5 << "Info about turn " << n.day << "has been sent!" << std::endl;
 	handleTimeEvents();
 	//call objects
@@ -2020,7 +2044,7 @@ void CGameHandler::setOwner(int objid, ui8 owner)
 	{
 		const CGTownInstance * town = getTown(objid);
 		if (town->subID == 5 && vstd::contains(town->builtBuildings, 22))
-			setPortalDwelling(town);
+			setPortalDwelling(town, true, false);
 		
 		if (!gs->getPlayer(owner)->towns.size())//player lost last town
 		{

+ 1 - 1
server/CGameHandler.h

@@ -159,7 +159,7 @@ public:
 	void changeObjPos(int objid, int3 newPos, ui8 flags);
 	void useScholarSkill(si32 hero1, si32 hero2);
 	void heroExchange(si32 hero1, si32 hero2);
-	void setPortalDwelling(const CGTownInstance * town, bool forced);
+	void setPortalDwelling(const CGTownInstance * town, bool forced, bool clear);
 	//////////////////////////////////////////////////////////////////////////
 
 	void init(StartInfo *si, int Seed);