Bläddra i källkod

Fixed #771, #772 and #787.
Some minor changes and fixes.

Michał W. Urbańczyk 14 år sedan
förälder
incheckning
3152e6d540

+ 0 - 7
AI/GeniusAI/CGeniusAI.cpp

@@ -1268,13 +1268,6 @@ void CGeniusAI::battleStart(const CCreatureSet *army1, const CCreatureSet *army2
 	m_battleLogic = new BattleAI::CBattleLogic(m_cb, army1, army2, tile, hero1,
     hero2, side);
 
-	if(m_cb->battleGetTacticDist())
-	{
-		m_cb->waitTillRealize = false;
-		BattleAction endt = BattleAction::makeEndOFTacticPhase(m_cb->battleGetMySide());
-		m_cb->battleMakeTacticAction(&endt);
-		m_cb->waitTillRealize = true;
-	}
 	DbgBox("** CGeniusAI::battleStart **");
 }
 

+ 9 - 12
CCallback.cpp

@@ -183,26 +183,23 @@ int CBattleCallback::battleMakeAction(BattleAction* action)
 	return 0;
 }
 
-template <typename T>
-void CBattleCallback::sendRequest(const T* request)
+void CBattleCallback::sendRequest(const CPack* request)
 {
 
-	//TODO? should be part of CClient but it would have to be very tricky cause template/serialization issues
+	//TODO should be part of CClient (client owns connection, not CB)
+	//but it would have to be very tricky cause template/serialization issues
 	if(waitTillRealize)
-		cl->waitingRequest.set(typeList.getTypeID<T>());
+		cl->waitingRequest.set(typeList.getTypeID(request));
 
-	{
-		boost::unique_lock<boost::mutex> lock(*cl->serv->wmx);
-		*cl->serv << request;
-	}
+	cl->serv->sendPack(*request);
 
 	if(waitTillRealize)
 	{
 		if(unlockGsWhenWaiting)
-			gs->mx->unlock_shared();
+			getGsMutex().unlock_shared();
 		cl->waitingRequest.waitWhileTrue();
 		if(unlockGsWhenWaiting)
-			gs->mx->lock_shared();
+			getGsMutex().lock_shared();
 	}
 }
 
@@ -246,7 +243,7 @@ void CCallback::setSelection(const CArmedInstance * obj)
 	SetSelection ss;
 	ss.player = player;
 	ss.id = obj->id;
-	sendRequest(&ss);
+	sendRequest(&(CPackForClient&)ss);
 
 	if(obj->ID == HEROI_TYPE)
 	{
@@ -287,7 +284,7 @@ void CCallback::save( const std::string &fname )
 void CCallback::sendMessage(const std::string &mess)
 {
 	PlayerMessage pm(player, mess);
-	sendRequest(&pm);
+	sendRequest(&(CPackForClient&)pm);
 }
 
 void CCallback::buildBoat( const IShipyard *obj )

+ 1 - 1
CCallback.h

@@ -89,7 +89,7 @@ private:
 
 
 protected:
-	template <typename T> void sendRequest(const T*request);
+	void sendRequest(const CPack *request);
 	CClient *cl;
 	//virtual bool hasAccess(int playerId) const;
 

+ 5 - 5
client/CBattleInterface.cpp

@@ -3830,11 +3830,14 @@ void CBattleInterface::startAction(const BattleAction* action)
 {
 	if(action->actionType == BattleAction::END_TACTIC_PHASE)
 	{
+		SDL_FreeSurface(menu);
 		menu = BitmapHandler::loadBitmap("CBAR.bmp");
+
 		graphics->blueToPlayersAdv(menu, curInt->playerID);
+		bDefence->block(false);
+		bWait->block(false);
 		if(active)
 		{
-			tacticsMode = false;
 			if(btactEnd && btactNext) //if the other side had tactics, there are no buttons
 			{
 				btactEnd->deactivate();
@@ -3932,10 +3935,7 @@ void CBattleInterface::waitForAnims()
 void CBattleInterface::bEndTacticPhase()
 {
 	btactEnd->block(true);
-	bDefence->block(false);
-	bWait->block(false);
-	BattleAction endt = BattleAction::makeEndOFTacticPhase(curInt->cb->battleGetMySide());
-	curInt->cb->battleMakeTacticAction(&endt);
+	tacticsMode = false;
 }
 
 static bool immobile(const CStack *s)

+ 6 - 0
client/CPlayerInterface.cpp

@@ -892,6 +892,12 @@ void CPlayerInterface::battleAttack(const BattleAttack *ba)
 	}
 }
 
+void CPlayerInterface::yourTacticPhase(int distance)
+{
+	while(battleInt->tacticsMode)
+		boost::this_thread::sleep(boost::posix_time::millisec(1));
+}
+
 void CPlayerInterface::showComp(SComponent comp)
 {
 	boost::unique_lock<boost::recursive_mutex> un(*pim);

+ 1 - 0
client/CPlayerInterface.h

@@ -230,6 +230,7 @@ public:
 	void battleObstaclesRemoved(const std::set<si32> & removedObstacles) OVERRIDE; //called when a certain set  of obstacles is removed from batlefield; IDs of them are given
 	void battleCatapultAttacked(const CatapultAttack & ca) OVERRIDE; //called when catapult makes an attack
 	void battleStacksRemoved(const BattleStacksRemoved & bsr) OVERRIDE; //called when certain stack is completely removed from battlefield
+	void yourTacticPhase(int distance) OVERRIDE;
 
 	//-------------//
 	void showArtifactAssemblyDialog(ui32 artifactID, ui32 assembleTo, bool assemble, CFunctionList<void()> onYes, CFunctionList<void()> onNo);

+ 3 - 3
client/CPreGame.cpp

@@ -2042,7 +2042,7 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry( OptionsTab *owner, PlayerSet
 		for(int i = 0; i < 6; i++)
 			btns[i] = NULL;
 
-	selectButtons(false);
+	selectButtons();
 
 	assert(SEL->current && SEL->current->mapHeader);
 	const PlayerInfo &p = SEL->current->mapHeader->players[s.color];
@@ -2080,12 +2080,12 @@ void OptionsTab::PlayerOptionsEntry::showAll( SDL_Surface * to )
 	printAtMiddleWBLoc(CGI->generaltexth->arraytxt[206+whoCanPlay], 28, 34, FONT_TINY, 8, zwykly, to);
 }
 
-void OptionsTab::PlayerOptionsEntry::selectButtons(bool onlyHero)
+void OptionsTab::PlayerOptionsEntry::selectButtons()
 {
 	if(!btns[0])
 		return;
 
-	if( (!onlyHero  &&  pi.defaultCastle() != -1) //fixed tow
+	if( (pi.defaultCastle() != -1) //fixed tow
 		|| (SEL->isGuest() && s.color != playerColor)) //or not our player
 	{
 		btns[0]->disable();

+ 1 - 1
client/CPreGame.h

@@ -184,7 +184,7 @@ public:
 		enum {HUMAN_OR_CPU, HUMAN, CPU} whoCanPlay;
 		
 		PlayerOptionsEntry(OptionsTab *owner, PlayerSettings &S);
-		void selectButtons(bool onlyHero = true); //hides unavailable buttons
+		void selectButtons(); //hides unavailable buttons
 		void showAll(SDL_Surface * to);
 	};
 

+ 18 - 1
client/Client.cpp

@@ -523,7 +523,8 @@ void CClient::handlePack( CPack * pack )
 }
 
 void CClient::updatePaths()
-{	
+{
+	//TODO? lazy evaluation? paths now can get recalculated multiple times upon various game events
 	const CGHeroInstance *h = getSelectedHero();
 	if (h)//if we have selected hero...
 		calculatePaths(h);
@@ -594,6 +595,11 @@ void CClient::battleStarted(const BattleInfo * info)
 		battleints[info->sides[1]]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 1);
 	if(vstd::contains(battleints,254))
 		battleints[254]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 1);
+
+	if(info->tacticDistance && vstd::contains(battleints,info->sides[info->tacticsSide]))
+	{
+		boost::thread hlp = boost::thread(&CClient::commenceTacticPhaseForInt, this, battleints[info->sides[info->tacticsSide]]);
+	}
 }
 
 void CClient::loadNeutralBattleAI()
@@ -624,6 +630,17 @@ void CClient::calculatePaths(const CGHeroInstance *h)
 	gs->calculatePaths(h, *pathInfo);
 }
 
+void CClient::commenceTacticPhaseForInt(CBattleGameInterface *battleInt)
+{
+	setThreadName(-1, "CClient::commenceTacticPhaseForInt");
+	try
+	{
+		battleInt->yourTacticPhase(gs->curB->tacticDistance);
+		MakeAction ma(BattleAction::makeEndOFTacticPhase(battleInt->playerID));
+		serv->sendPack(ma);
+	} HANDLE_EXCEPTION
+}
+
 template void CClient::serialize( CISer<CLoadFile> &h, const int version );
 template void CClient::serialize( COSer<CSaveFile> &h, const int version );
 

+ 1 - 0
client/Client.h

@@ -165,6 +165,7 @@ public:
 	
 	void handlePack( CPack * pack ); //applies the given pack and deletes it
 	void battleStarted(const BattleInfo * info);
+	void commenceTacticPhaseForInt(CBattleGameInterface *battleInt); //will be called as separate thread
 
 	void commitPackage(CPackForClient *pack) OVERRIDE;
 

+ 7 - 0
client/NetPacksClient.cpp

@@ -241,6 +241,11 @@ void HeroVisit::applyCl( CClient *cl )
 	INTERFACE_CALL_IF_PRESENT(hero->tempOwner, heroVisit, hero, obj, starting);
 }
 
+void NewTurn::applyCl( CClient *cl )
+{
+	cl->updatePaths();
+}
+
 
 void GiveBonus::applyCl( CClient *cl )
 {
@@ -711,6 +716,8 @@ void PackageApplied::applyCl( CClient *cl )
 	INTERFACE_CALL_IF_PRESENT(player, requestRealized, this);
 	if(cl->waitingRequest.get() == packType)
 		cl->waitingRequest.setn(false);
+	else if(cl->waitingRequest.get())
+		tlog3 << "Suprising server message!\n";
 }
 
 void SystemMessage::applyCl( CClient *cl )

+ 28 - 3
lib/CCreatureHandler.cpp

@@ -71,14 +71,39 @@ int CCreature::getQuantityID(const int & quantity)
 	if (quantity<250)
 		return 5;
 	if (quantity<500)
-		return 5;
-	if (quantity<1000)
 		return 6;
-	if (quantity<4000)
+	if (quantity<1000)
 		return 7;
 	return 8;
 }
 
+int CCreature::estimateCreatureCount(int countID)
+{
+	switch(countID)
+	{
+	case 0:
+		return 3;
+	case 1:
+		return 8;
+	case 2:
+		return 15;
+	case 3:
+		return 35;
+	case 4:
+		return 75;
+	case 5:
+		return 175;
+	case 6:
+		return 375;
+	case 7:
+		return 750;
+	case 8:
+		return 2500;
+	default:
+		assert("Wrong countID!");
+	}
+}
+
 bool CCreature::isDoubleWide() const
 {
 	return doubleWide;

+ 1 - 0
lib/CCreatureHandler.h

@@ -58,6 +58,7 @@ public:
 	bool isEvil () const;
 	si32 maxAmount(const std::vector<si32> &res) const; //how many creatures can be bought
 	static int getQuantityID(const int & quantity); //0 - a few, 1 - several, 2 - pack, 3 - lots, 4 - horde, 5 - throng, 6 - swarm, 7 - zounds, 8 - legion
+	static int estimateCreatureCount(int countID); //reverse version of above function, returns middle of range
 	bool isMyUpgrade(const CCreature *anotherCre) const;
 
 	bool valid() const;

+ 5 - 0
lib/CGameInterface.cpp

@@ -197,4 +197,9 @@ void CAdventureAI::battleStacksHealedRes(const std::vector<std::pair<ui32, ui32>
 BattleAction CAdventureAI::activeStack(const CStack * stack)
 {
 	return battleAI->activeStack(stack);
+}
+
+void CAdventureAI::yourTacticPhase(int distance)
+{
+	battleAI->yourTacticPhase(distance);
 }

+ 2 - 0
lib/CGameInterface.h

@@ -67,6 +67,7 @@ public:
 
 	//battle call-ins
 	virtual BattleAction activeStack(const CStack * stack)=0; //called when it's turn of that stack
+	virtual void yourTacticPhase(int distance){}; //called when interface has opportunity to use Tactics skill -> use cb->battleMakeTacticAction from this function
 };
 
 /// Central class for managing human player / AI interface logic
@@ -116,6 +117,7 @@ public:
 
 	//battle interface
 	virtual BattleAction activeStack(const CStack * stack);
+	virtual void yourTacticPhase(int distance);
 	virtual void battleNewRound(int round);
 	virtual void battleCatapultAttacked(const CatapultAttack & ca);
 	virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side);

+ 18 - 2
lib/CGameState.cpp

@@ -2990,7 +2990,7 @@ InfoAboutHero & InfoAboutHero::operator=( const InfoAboutHero & iah )
 
 
 
-ArmyDescriptor::ArmyDescriptor(const CArmedInstance *army, bool detailed)
+ArmyDescriptor::ArmyDescriptor(const CArmedInstance *army, bool detailed) : isDetailed(detailed)
 {
 	for(TSlots::const_iterator i = army->Slots().begin(); i != army->Slots().end(); i++)
 	{
@@ -3001,11 +3001,27 @@ ArmyDescriptor::ArmyDescriptor(const CArmedInstance *army, bool detailed)
 	}
 }
 
-ArmyDescriptor::ArmyDescriptor()
+ArmyDescriptor::ArmyDescriptor() : isDetailed(true)
 {
 
 }
 
+int ArmyDescriptor::getStrength() const
+{
+	ui64 ret = 0;
+	if(isDetailed)
+	{
+		for(const_iterator i = begin(); i != end(); i++)
+			ret += i->second.type->AIValue * i->second.count;
+	}
+	else
+	{
+		for(const_iterator i = begin(); i != end(); i++)
+			ret += i->second.type->AIValue * CCreature::estimateCreatureCount(i->second.count);
+	}
+	return ret;
+}
+
 DuelParameters::SideSettings::StackSettings::StackSettings()
 	: type(-1), count(0)
 {

+ 3 - 0
lib/CGameState.h

@@ -76,8 +76,11 @@ namespace boost
 //numbers of creatures are exact numbers if detailed else they are quantity ids (0 - a few, 1 - several and so on; additionaly -1 - unknown)
 struct ArmyDescriptor : public std::map<TSlot, CStackBasicDescriptor>
 {
+	bool isDetailed; 
 	DLL_EXPORT ArmyDescriptor(const CArmedInstance *army, bool detailed); //not detailed -> quantity ids as count
 	DLL_EXPORT ArmyDescriptor();
+
+	DLL_EXPORT int getStrength() const;
 };
 
 struct DLL_EXPORT InfoAboutHero

+ 6 - 0
lib/Connection.cpp

@@ -243,6 +243,12 @@ CPack * CConnection::retreivePack()
 	return ret;
 }
 
+void CConnection::sendPack(const CPack &pack)
+{
+	boost::unique_lock<boost::mutex> lock(*wmx);
+	*this << &pack; //packs has to be sent as polymorphic pointers!
+}
+
 CSaveFile::CSaveFile( const std::string &fname )
 	:sfile(NULL)
 {

+ 1 - 0
lib/Connection.h

@@ -922,6 +922,7 @@ public:
 	~CConnection(void);
 
 	CPack *retreivePack(); //gets from server next pack (allocates it with new)
+	void sendPack(const CPack &pack);
 };
 
 DLL_EXPORT std::ostream &operator<<(std::ostream &str, const CConnection &cpc);

+ 1 - 0
lib/NetPacks.h

@@ -952,6 +952,7 @@ struct NewTurn : public CPackForClient //101
 {
 	enum weekType {NORMAL, DOUBLE_GROWTH, BONUS_GROWTH, DEITYOFFIRE, PLAGUE, CUSTOM, NO_ACTION, NONE};
 
+	void applyCl(CClient *cl);
 	DLL_EXPORT void applyGs(CGameState *gs);
 
 	struct Hero