소스 검색

7 days without castle loss condition. Minor fixes.

Michał W. Urbańczyk 15 년 전
부모
커밋
49e56e3749
6개의 변경된 파일81개의 추가작업 그리고 13개의 파일을 삭제
  1. 1 1
      client/NetPacksClient.cpp
  2. 6 0
      lib/CGameState.cpp
  3. 2 2
      lib/NetPacks.h
  4. 9 0
      lib/NetPacksLib.cpp
  5. 62 9
      server/CGameHandler.cpp
  6. 1 1
      server/CGameHandler.h

+ 1 - 1
client/NetPacksClient.cpp

@@ -152,7 +152,7 @@ void RemoveObject::applyFirstCl( CClient *cl )
 
 void RemoveObject::applyCl( CClient *cl )
 {
-	if(cl->pathInfo->hero)
+	if(cl->pathInfo->hero && cl->pathInfo->hero->id != id)
 		GS(cl)->calculatePaths(cl->pathInfo->hero, *cl->pathInfo);
 }
 

+ 6 - 0
lib/CGameState.cpp

@@ -217,6 +217,9 @@ void MetaString::getLocalString(const std::pair<ui8,ui32> &txt, std::string &dst
 		case SEC_SKILL_NAME:
 			vec = &VLC->generaltexth->skillName;
 			break;
+		case COLOR:
+			vec = &VLC->generaltexth->capColors;
+			break;
 		}
 		dst = (*vec)[ser];
 	}
@@ -3224,6 +3227,9 @@ int CGameState::lossCheck( ui8 player ) const
 		}
 	}
 
+	if(!p->towns.size() && p->daysWithoutCastle >= 7)
+		return 2;
+
 	return false;
 }
 

+ 2 - 2
lib/NetPacks.h

@@ -73,7 +73,7 @@ private:
 	enum EMessage {TEXACT_STRING, TLOCAL_STRING, TNUMBER, TREPLACE_ESTRING, TREPLACE_LSTRING, TREPLACE_NUMBER};
 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};
+		MINE_EVNTS, ADVOB_TXT, ART_EVNTS, SPELL_NAME, SEC_SKILL_NAME, CRE_SING_NAMES, CREGENS4, COLOR};
 
 	std::vector<ui8> message; //vector of EMessage
 
@@ -631,7 +631,7 @@ struct NewTurn : public CPackForClient //101
 
 struct Component : public CPack //2002 helper for object scrips informations
 {
-	enum {PRIM_SKILL, SEC_SKILL, RESOURCE, CREATURE, ARTIFACT, EXPERIENCE, SPELL, MORALE=8, LUCK, HERO};
+	enum {PRIM_SKILL, SEC_SKILL, RESOURCE, CREATURE, ARTIFACT, EXPERIENCE, SPELL, MORALE=8, LUCK, HERO, FLAG};
 	ui16 id, subtype; //id uses ^^^ enums, when id==EXPPERIENCE subtype==0 means exp points and subtype==1 levels)
 	si32 val; // + give; - take
 	si16 when; // 0 - now; +x - within x days; -x - per x days

+ 9 - 0
lib/NetPacksLib.cpp

@@ -575,6 +575,15 @@ DLL_EXPORT void NewTurn::applyGs( CGameState *gs )
 	if(gs->getDate(1) == 7) //new week
 		BOOST_FOREACH(CGHeroInstance *h, gs->map->heroes)
 			h->bonuses.remove_if(HeroBonus::OneWeek);
+
+	//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++;
+	}
 }
 
 DLL_EXPORT void SetObjectProperty::applyGs( CGameState *gs )

+ 62 - 9
server/CGameHandler.cpp

@@ -912,6 +912,38 @@ void CGameHandler::newTurn()
 			gs->map->objects[i]->newTurn();
 
 	winLoseHandle(0xff);
+
+	//warn players without town
+	if(gs->day)
+	{
+		for (std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
+		{
+			if(i->second.status || i->second.towns.size() || i->second.color >= PLAYER_LIMIT)
+				continue;
+
+			InfoWindow iw;
+			iw.player = i->first;
+			iw.components.push_back(Component(Component::FLAG,i->first,0,0));
+
+			if(!i->second.daysWithoutCastle)
+			{
+				iw.text.addTxt(MetaString::GENERAL_TXT,6); //%s, you have lost your last town.  If you do not conquer another town in the next week, you will be eliminated.
+				iw.text.addReplacement(MetaString::COLOR, i->first);
+			}
+			else if(i->second.daysWithoutCastle == 6)
+			{
+				iw.text.addTxt(MetaString::ARRAY_TXT,129); //%s, this is your last day to capture a town or you will be banished from this land.
+				iw.text.addReplacement(MetaString::COLOR, i->first);
+			}
+			else
+			{
+				iw.text.addTxt(MetaString::ARRAY_TXT,128); //%s, you only have %d days left to capture a town or you will be banished from this land.
+				iw.text.addReplacement(MetaString::COLOR, i->first);
+				iw.text.addReplacement(7 - i->second.daysWithoutCastle);
+			}
+			sendAndApply(&iw);
+		}
+	}
 }
 void CGameHandler::run(bool resume)
 {	
@@ -1583,10 +1615,18 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
 }
 void CGameHandler::setOwner(int objid, ui8 owner)
 {
+	ui8 oldOwner = getOwner(objid);
 	SetObjectProperty sop(objid,1,owner);
 	sendAndApply(&sop);
 
-	winLoseHandle(1<<owner);
+	winLoseHandle(1<<owner | 1<<oldOwner);
+	if(owner < PLAYER_LIMIT && getTown(objid) && !gs->getPlayer(owner)->towns.size()) //player lost last town
+	{
+		InfoWindow iw;
+		iw.player = oldOwner;
+		iw.text.addTxt(MetaString::GENERAL_TXT, 6); //%s, you have lost your last town.  If you do not conquer another town in the next week, you will be eliminated.
+		sendAndApply(&iw);
+	}
 }
 void CGameHandler::setHoverName(int objid, MetaString* name)
 {
@@ -2877,7 +2917,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
 			break;
 		}
 	}
-	if(ba.stackNumber == gs->curB->activeStack)
+	if(ba.stackNumber == gs->curB->activeStack  ||  battleResult.get()) //active stack has moved or battle has finished
 		battleMadeAction.setn(true);
 	return ok;
 }
@@ -3522,7 +3562,7 @@ void CGameHandler::checkLossVictory( ui8 player )
 		return;
 
 	InfoWindow iw;
-	getLossVicMessage(player, vic ? vic < 0 : loss < 0, vic, iw);
+	getLossVicMessage(player, vic ? vic : loss , vic, iw);
 	sendAndApply(&iw);
 
 	PlayerEndsGame peg;
@@ -3530,7 +3570,7 @@ void CGameHandler::checkLossVictory( ui8 player )
 	peg.victory = vic;
 	sendAndApply(&peg);
 
-	if(vic) //one player won -> all enemies lost  //TODO: allies
+	if(vic > 0) //one player won -> all enemies lost  //TODO: allies
 	{
 		iw.text.localStrings.front().second++; //message about losing because enemy won first is just after victory message
 
@@ -3549,18 +3589,25 @@ void CGameHandler::checkLossVictory( ui8 player )
 	}
 	else //player lost -> all his objects become unflagged (neutral)
 	{
-		for (std::vector<CGObjectInstance*>::const_iterator i = gs->map->objects.begin(); i != gs->map->objects.end(); i++)
+		std::vector<CGHeroInstance*> hlp = p->heroes;
+		for (std::vector<CGHeroInstance*>::const_iterator i = hlp.begin(); i != hlp.end(); i++) //eliminate heroes
+			removeObject((*i)->id);
+
+		for (std::vector<CGObjectInstance*>::const_iterator i = gs->map->objects.begin(); i != gs->map->objects.end(); i++) //unflag objs
 		{
 			if(*i  &&  (*i)->tempOwner == player)
 				setOwner((**i).id,NEUTRAL_PLAYER);
 		}
+
+		//eliminating one player may cause victory of anoother:
+		winLoseHandle(ALL_PLAYERS & ~(1<<player));
 	}
 
 	if(vic)
 		end2 = true;
 }
 
-void CGameHandler::getLossVicMessage( ui8 player, bool standard, bool victory, InfoWindow &out ) const
+void CGameHandler::getLossVicMessage( ui8 player, ui8 standard, bool victory, InfoWindow &out ) const
 {
 	const PlayerState *p = gs->getPlayer(player);
 // 	if(!p->human)
@@ -3570,7 +3617,7 @@ void CGameHandler::getLossVicMessage( ui8 player, bool standard, bool victory, I
 
 	if(victory)
 	{
-		if(!standard) //not std loss
+		if(standard < 0) //not std loss
 		{
 			switch(gs->map->victoryCondition.condition)
 			{
@@ -3626,12 +3673,12 @@ void CGameHandler::getLossVicMessage( ui8 player, bool standard, bool victory, I
 		}
 		else
 		{
-
+			out.text.addTxt(MetaString::GENERAL_TXT, 659); //Congratulations! You have reached your destination, precious cargo intact, and can claim victory!
 		}
 	}
 	else
 	{
-		if(!standard) //not std loss
+		if(standard < 0) //not std loss
 		{
 			switch(gs->map->lossCondition.typeOfLossCon)
 			{
@@ -3656,6 +3703,12 @@ void CGameHandler::getLossVicMessage( ui8 player, bool standard, bool victory, I
 				break;
 			}
 		}
+		else if(standard == 2)
+		{
+			out.text.addTxt(MetaString::GENERAL_TXT, 7);//%s, your heroes abandon you, and you are banished from this land.
+			out.text.addReplacement(MetaString::COLOR, player);
+			out.components.push_back(Component(Component::FLAG,player,0,0));
+		}
 		else //lost all towns and heroes
 		{
 			out.text.addTxt(MetaString::GENERAL_TXT, 660); //All your forces have been defeated, and you are banished from this land!

+ 1 - 1
server/CGameHandler.h

@@ -91,7 +91,7 @@ public:
 	void startBattle(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function<void(BattleResult*)> cb, const CGTownInstance *town = NULL); //use hero=NULL for no hero
 	void checkLossVictory(ui8 player);
 	void winLoseHandle(ui8 players=255); //players: bit field - colours of players to be checked; default: all
-	void getLossVicMessage(ui8 player, bool standard, bool victory, InfoWindow &out) const;
+	void getLossVicMessage(ui8 player, ui8 standard, bool victory, InfoWindow &out) const;
 
 	////used only in endBattle - don't touch elsewhere
 	boost::function<void(BattleResult*)> * battleEndCallback;