瀏覽代碼

Support for creature weeks and Deity of Fire is now complete.

DjWarmonger 15 年之前
父節點
當前提交
c7f8f0a967
共有 8 個文件被更改,包括 121 次插入87 次删除
  1. 7 4
      client/CCastleInterface.cpp
  2. 1 0
      hch/CCreatureHandler.cpp
  3. 2 3
      hch/CObjectHandler.cpp
  4. 3 0
      lib/CGameState.cpp
  5. 2 1
      lib/HeroBonus.cpp
  6. 10 5
      lib/NetPacks.h
  7. 59 48
      lib/NetPacksLib.cpp
  8. 37 26
      server/CGameHandler.cpp

+ 7 - 4
client/CCastleInterface.cpp

@@ -1142,8 +1142,7 @@ void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState)
 		int summ=0, cnt=0;
 		std::string descr=CGI->generaltexth->allTexts[589];//Growth of creature is number
 		boost::algorithm::replace_first(descr,"%s",CGI->creh->creatures[crid]->nameSing);
-		boost::algorithm::replace_first(descr,"%d", boost::lexical_cast<std::string>(
-			ci->town->creatureGrowth(level)));
+		boost::algorithm::replace_first(descr,"%d", boost::lexical_cast<std::string>(ci->town->creatureGrowth(level)));
 
 		descr +="\n"+CGI->generaltexth->allTexts[590];
 		summ = CGI->creh->creatures[crid]->growth;
@@ -1157,6 +1156,9 @@ void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState)
 			else if ( bld.find(8)!=bld.end())//else if citadel+50% to basic
 				summ+=AddToString(CGI->buildh->buildings[ci->town->subID][8]->Name()+" %+d",descr,summ/2);
 
+			summ+=AddToString(CGI->generaltexth->allTexts[63] + " %+d",descr,
+				summ * CGI->creh->creatures[crid]->valOfBonuses(Bonus::CREATURE_GROWTH_PERCENT)/100);
+
 			if(ci->town->town->hordeLvl[0]==level)//horde, x to summ
 			if((bld.find(18)!=bld.end()) || (bld.find(19)!=bld.end()))
 				summ+=AddToString(CGI->buildh->buildings[ci->town->subID][18]->Name()+" %+d",descr,
@@ -1187,11 +1189,12 @@ void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState)
 				};
 				ch = ci->town->visitingHero;
 			};
-
-			//TODO player bonuses
+			//TODO: player bonuses
 
 			if(bld.find(26)!=bld.end()) //grail - +50% to ALL growth
 				summ+=AddToString(CGI->buildh->buildings[ci->town->subID][26]->Name()+" %+d",descr,summ/2);
+
+			summ+=AddToString(CGI->generaltexth->allTexts[63] + " %+d",descr, CGI->creh->creatures[crid]->valOfBonuses(Bonus::CREATURE_GROWTH));
 		}
 
 		CInfoPopup *mess = new CInfoPopup();//creating popup

+ 1 - 0
hch/CCreatureHandler.cpp

@@ -121,6 +121,7 @@ si32 CCreature::maxAmount(const std::vector<si32> &res) const //how many creatur
 CCreature::CCreature()
 {
 	doubleWide = false;
+	nodeType = CBonusSystemNode::CREATURE;
 }
 
 ui32 CCreature::getMinDamage() const

+ 2 - 3
hch/CObjectHandler.cpp

@@ -1960,11 +1960,10 @@ int CGTownInstance::creatureGrowth(const int & level) const
 		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
+	//spcecial week unaffected by grail (bug in original game?)
+	ret += VLC->creh->creatures[creid]->valOfBonuses(Bonus::CREATURE_GROWTH);
 	return ret;//check CCastleInterface.cpp->CCastleInterface::CCreaInfo::clickRight if this one will be modified
 }
 int CGTownInstance::dailyIncome() const

+ 3 - 0
lib/CGameState.cpp

@@ -269,6 +269,9 @@ DLL_EXPORT void MetaString::toString(std::string &dst) const
 		case TREPLACE_NUMBER:
 			dst.replace (dst.find("%d"), 2, boost::lexical_cast<std::string>(numbers[nums++]));
 			break;
+		case TREPLACE_PLUSNUMBER:
+			dst.replace (dst.find("%+d"), 3, '+' + boost::lexical_cast<std::string>(numbers[nums++]));
+			break;
 		default:
 			tlog1 << "MetaString processing error!\n";
 			break;

+ 2 - 1
lib/HeroBonus.cpp

@@ -493,7 +493,8 @@ bool CCreatureTypeLimiter::limit(const Bonus &b, const CBonusSystemNode &node) c
 		}
 			break;
 		default:
-			return false; //don't delete it if it's other type of node
+			//return false; //don't delete it if it's other type of node
+			return true;
 	}
 }
 CCreatureTypeLimiter::CCreatureTypeLimiter(const CCreature &Creature, ui8 IncludeUpgrades /*= true*/)

+ 10 - 5
lib/NetPacks.h

@@ -73,7 +73,7 @@ struct Query : public CPackForClient
 struct MetaString : public CPack //2001 helper for object scrips
 {
 private:
-	enum EMessage {TEXACT_STRING, TLOCAL_STRING, TNUMBER, TREPLACE_ESTRING, TREPLACE_LSTRING, TREPLACE_NUMBER};
+	enum EMessage {TEXACT_STRING, TLOCAL_STRING, TNUMBER, TREPLACE_ESTRING, TREPLACE_LSTRING, TREPLACE_NUMBER, TREPLACE_PLUSNUMBER};
 public:
 	enum {GENERAL_TXT=1, XTRAINFO_TXT, OBJ_NAMES, RES_NAMES, ART_NAMES, ARRAY_TXT, CRE_PL_NAMES, CREGENS, MINE_NAMES, 
 		MINE_EVNTS, ADVOB_TXT, ART_EVNTS, SPELL_NAME, SEC_SKILL_NAME, CRE_SING_NAMES, CREGENS4, COLOR, ART_DESCR};
@@ -126,6 +126,11 @@ public:
 		message.push_back(TREPLACE_NUMBER);
 		numbers.push_back(txt);
 	}
+	void addReplacement2(int txt)
+	{
+		message.push_back(TREPLACE_PLUSNUMBER);
+		numbers.push_back(txt);
+	}
 	DLL_EXPORT void addReplacement(const CStackInstance &stack); //adds sing or plural name;
 	DLL_EXPORT std::string buildList () const;
 	void clear()
@@ -690,7 +695,7 @@ struct SetAvailableArtifacts  : public CPackForClient //519
 
 struct NewTurn : public CPackForClient //101
 {
-	enum weekType {NORMAL, DOUBLE_GROWTH, BONUS_GROWTH, PLAGUE, CUSTOM, NO_ACTION, NONE};
+	enum weekType {NORMAL, DOUBLE_GROWTH, BONUS_GROWTH, DEITYOFFIRE, PLAGUE, CUSTOM, NO_ACTION, NONE};
 
 	DLL_EXPORT void applyGs(CGameState *gs);
 
@@ -710,14 +715,14 @@ struct NewTurn : public CPackForClient //101
 	std::vector<SetAvailableCreatures> cres;//creatures to be placed in towns
 	ui32 day;
 	bool resetBuilded;
-	weekType specialWeek;
-	TQuantity creatureid; //for creature weeks
+	ui8 specialWeek; //weekType
+	TCreature creatureid; //for creature weeks
 
 	NewTurn(){type = 101;};
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & heroes & cres & res & day & resetBuilded;
+		h & heroes & cres & res & day & resetBuilded & specialWeek & creatureid;
 	}
 }; 
 

+ 59 - 48
lib/NetPacksLib.cpp

@@ -625,62 +625,74 @@ DLL_EXPORT void NewTurn::applyGs( CGameState *gs )
 	BOOST_FOREACH(SetAvailableCreatures h, cres) //set available creatures in towns
 		h.applyGs(gs);
 
-	if(resetBuilded) //reset amount of structures set in this turn in towns
-		BOOST_FOREACH(CGTownInstance* t, gs->map->towns)
-		t->builded = 0;
-
-	BOOST_FOREACH(CGHeroInstance *h, gs->map->heroes)
-		h->bonuses.remove_if(Bonus::OneDay);
-
-	if(gs->getDate(1) == 1 && specialWeek != NO_ACTION) //new week, Monday that is
+	if (specialWeek != NO_ACTION) //first pack applied, reset all effects and aplly new
 	{
 		BOOST_FOREACH(CGHeroInstance *h, gs->map->heroes)
-			h->bonuses.remove_if(Bonus::OneWeek);
-
-		gs->globalEffects.bonuses.remove_if(Bonus::OneWeek);
+			h->bonuses.remove_if(Bonus::OneDay);
 
-		Bonus b;
-		b.duration = Bonus::ONE_WEEK;
-		b.source = Bonus::SPECIAL_WEEK;
-		b.effectRange = Bonus::NO_LIMIT;
-		switch (specialWeek)
+		if(resetBuilded) //reset amount of structures set in this turn in towns
 		{
-			case DOUBLE_GROWTH:
-				b.val = 100;
-				b.type = Bonus::CREATURE_GROWTH_PERCENT;
-				b.limiter = new CCreatureTypeLimiter(*VLC->creh->creatures[creatureid], false);
-				b.valType = Bonus::BASE_NUMBER; //certainly not intuitive
-				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::BASE_NUMBER;
-				break;
-			default:
-				b.val = 0;
+			BOOST_FOREACH(CGTownInstance* t, gs->map->towns)
+				t->builded = 0;
+		}
+		if(gs->getDate(1)) //new week, Monday that is
+		{
+			for( std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
+				i->second.bonuses.remove_if(Bonus::OneWeek);
+			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::BASE_NUMBER; //certainly not intuitive
+					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 DEITYOFFIRE:
+					b.val = 15;
+					b.type = Bonus::CREATURE_GROWTH;
+					b.limiter = new CCreatureTypeLimiter(*VLC->creh->creatures[42], true);
+					b.valType = Bonus::BASE_NUMBER;
+					break;
+				case PLAGUE:
+					b.val = -100; //no basic creatures
+					b.type = Bonus::CREATURE_GROWTH_PERCENT;
+					b.valType = Bonus::BASE_NUMBER;
+					break;
+				default:
+					b.val = 0;
 
+			}
+			if (b.val)
+				gs->globalEffects.bonuses.push_back(b);
 		}
-		if (b.val)
-			gs->globalEffects.bonuses.push_back(b);
 	}
-
-	//count days without town
-	for( std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
+	else //second pack is applied
 	{
-		if(i->second.towns.size() || gs->day == 1)
-			i->second.daysWithoutCastle = 0;
-		else
-			i->second.daysWithoutCastle++;
+		//count days without town
+		for( std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
+		{
+			if(i->second.towns.size() || gs->day == 1)
+				i->second.daysWithoutCastle = 0;
+			else
+				i->second.daysWithoutCastle++;
 
-		i->second.bonuses.remove_if(Bonus::OneDay);
-		if(gs->getDate(1) == 1) //new week
-			i->second.bonuses.remove_if(Bonus::OneWeek);
+			i->second.bonuses.remove_if(Bonus::OneDay);
+		}
 	}
 }
 
@@ -705,7 +717,6 @@ DLL_EXPORT void SetObjectProperty::applyGs( CGameState *gs )
 				gs->getPlayer(val)->towns.push_back(t);
 		}
 	}
-
 	
 	obj->setProperty(what,val);
 }

+ 37 - 26
server/CGameHandler.cpp

@@ -999,6 +999,7 @@ void CGameHandler::newTurn()
 {
 	tlog5 << "Turn " << gs->day+1 << std::endl;
 	NewTurn n;
+	n.creatureid = -1;
 	n.day = gs->day + 1;
 	n.resetBuilded = true;
 	bool newmonth = false;
@@ -1013,32 +1014,14 @@ void CGameHandler::newTurn()
 		if(getDate(4) == 28) //new month
 		{
 			newmonth = true;
-			if (monthType < 60) //double growth
+			if (monthType < 40) //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
+
+				std::pair<int,int> newMonster(54, VLC->creh->pickRandomMonster(boost::ref(rand)));
 				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)
+			else if (monthType < 90)
 				n.specialWeek = NewTurn::NORMAL;
 			else
 				n.specialWeek = NewTurn::PLAGUE;
@@ -1046,12 +1029,14 @@ void CGameHandler::newTurn()
 		else //it's a week, but not full month
 		{
 			newmonth = false;
-			if (monthType < 20)
+			if (monthType < 25)
 			{
 				n.specialWeek = NewTurn::BONUS_GROWTH; //+5
 				std::pair<int,int> newMonster (54, VLC->creh->pickRandomMonster(boost::ref(rand)));
 				monsterid = newMonster.second;
 			}
+			else
+				n.specialWeek = NewTurn::NORMAL;
 		}
 	}
 
@@ -1173,7 +1158,7 @@ void CGameHandler::newTurn()
 					{
 						if (getDate(0) > 1)
 						{
-							n.specialWeek = NewTurn::DOUBLE_GROWTH;
+							n.specialWeek = NewTurn::DEITYOFFIRE; //spawn familiars on new month
 							n.creatureid = 42; //familiar
 						}
 					}
@@ -1199,6 +1184,26 @@ void CGameHandler::newTurn()
 
 	if (gs->getDate(1)==1) //first day of week, day has already been changed
 	{
+		if (getDate(4) == 1 && (n.specialWeek == NewTurn::DOUBLE_GROWTH || n.specialWeek == NewTurn::DEITYOFFIRE))
+		{ //spawn wandering monsters
+			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);
+			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 = 54; //creature
+				no.subID= n.creatureid;
+				no.pos = *tile;
+				sendAndApply(&no);
+				tiles.erase(tile); //not use it again
+			}
+		}
+
 		NewTurn n2; //just to handle  creature growths after bonuses are applied
 		n2.specialWeek = NewTurn::NO_ACTION;
 		n2.day = gs->day;
@@ -1228,7 +1233,6 @@ void CGameHandler::newTurn()
 		if (gs->getDate(0) > 1)
 		{
 			InfoWindow iw; //new week info
-			int msgid;
 			switch (n.specialWeek)
 			{
 				case NewTurn::DOUBLE_GROWTH:
@@ -1244,11 +1248,18 @@ void CGameHandler::newTurn()
 					iw.text.addReplacement(MetaString::CRE_SING_NAMES, n.creatureid);
 					iw.text.addReplacement(MetaString::CRE_SING_NAMES, n.creatureid);
 					break;
+				case NewTurn::DEITYOFFIRE:
+					iw.text.addTxt(MetaString::ARRAY_TXT, 135);
+					iw.text.addReplacement(MetaString::CRE_SING_NAMES, 42); //%s imp
+					iw.text.addReplacement(MetaString::CRE_SING_NAMES, 42); //%s imp
+					iw.text.addReplacement2(15);							//%+d 15
+					iw.text.addReplacement(MetaString::CRE_SING_NAMES, 43); //%s familiar
+					iw.text.addReplacement2(15);							//%+d 15
+					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;