mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Some very early work towards autofight feature.
Added EmptyAI to the solution. Passing callbacks by shared_ptr.
This commit is contained in:
		| @@ -8,7 +8,7 @@ | ||||
| #include "../../lib/VCMI_Lib.h" | ||||
|  | ||||
| using boost::optional; | ||||
| CBattleCallback * cbc; | ||||
| shared_ptr<CBattleCallback> cbc; | ||||
|  | ||||
| #define LOGL(text) print(text) | ||||
| #define LOGFL(text, formattingEl) print(boost::str(boost::format(text) % formattingEl)) | ||||
| @@ -85,7 +85,7 @@ CBattleAI::~CBattleAI(void) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CBattleAI::init( CBattleCallback * CB ) | ||||
| void CBattleAI::init(shared_ptr<CBattleCallback> CB) | ||||
| { | ||||
| 	print("init called, saving ptr to IBattleCallback"); | ||||
| 	cbc = cb = CB; | ||||
|   | ||||
| @@ -109,7 +109,7 @@ struct PotentialTargets | ||||
| class CBattleAI : public CBattleGameInterface | ||||
| { | ||||
| 	int side; | ||||
| 	CBattleCallback *cb; | ||||
| 	shared_ptr<CBattleCallback> cb; | ||||
| 	 | ||||
| 	//Previous setting of cb  | ||||
| 	bool wasWaitingForRealize, wasUnlockingGs; | ||||
| @@ -119,7 +119,7 @@ public: | ||||
| 	CBattleAI(void); | ||||
| 	~CBattleAI(void); | ||||
|  | ||||
| 	void init(CBattleCallback * CB) OVERRIDE; | ||||
| 	void init(shared_ptr<CBattleCallback> CB) OVERRIDE; | ||||
| 	void actionFinished(const BattleAction &action) OVERRIDE;//occurs AFTER every action taken by any stack or by the hero | ||||
| 	void actionStarted(const BattleAction &action) OVERRIDE;//occurs BEFORE every action taken by any stack or by the hero | ||||
| 	BattleAction activeStack(const CStack * stack) OVERRIDE; //called when it's turn of that stack | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| #include "StdInc.h" | ||||
| #include "CEmptyAI.h" | ||||
|  | ||||
| void CEmptyAI::init(CCallback * CB) | ||||
| void CEmptyAI::init(shared_ptr<CCallback> CB) | ||||
| { | ||||
| 	cb = CB; | ||||
| 	human=false; | ||||
|   | ||||
| @@ -7,10 +7,10 @@ struct HeroMoveDetails; | ||||
|  | ||||
| class CEmptyAI : public CGlobalAI | ||||
| { | ||||
| 	CCallback *cb; | ||||
| 	shared_ptr<CCallback> cb; | ||||
|  | ||||
| public: | ||||
| 	void init(CCallback * CB) override; | ||||
| 	void init(shared_ptr<CCallback> CB) override; | ||||
| 	void yourTurn() override; | ||||
| 	void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override; | ||||
| 	void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override; | ||||
|   | ||||
| @@ -41,23 +41,27 @@ | ||||
|     <ConfigurationType>DynamicLibrary</ConfigurationType> | ||||
|     <UseDebugLibraries>true</UseDebugLibraries> | ||||
|     <CharacterSet>MultiByte</CharacterSet> | ||||
|     <PlatformToolset>v110</PlatformToolset> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> | ||||
|     <ConfigurationType>DynamicLibrary</ConfigurationType> | ||||
|     <UseDebugLibraries>true</UseDebugLibraries> | ||||
|     <CharacterSet>MultiByte</CharacterSet> | ||||
|     <PlatformToolset>v110</PlatformToolset> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'" Label="Configuration"> | ||||
|     <ConfigurationType>DynamicLibrary</ConfigurationType> | ||||
|     <UseDebugLibraries>false</UseDebugLibraries> | ||||
|     <WholeProgramOptimization>true</WholeProgramOptimization> | ||||
|     <CharacterSet>MultiByte</CharacterSet> | ||||
|     <PlatformToolset>v110_xp</PlatformToolset> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|x64'" Label="Configuration"> | ||||
|     <ConfigurationType>DynamicLibrary</ConfigurationType> | ||||
|     <UseDebugLibraries>false</UseDebugLibraries> | ||||
|     <WholeProgramOptimization>true</WholeProgramOptimization> | ||||
|     <CharacterSet>MultiByte</CharacterSet> | ||||
|     <PlatformToolset>v110_xp</PlatformToolset> | ||||
|   </PropertyGroup> | ||||
|   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> | ||||
|   <ImportGroup Label="ExtensionSettings"> | ||||
| @@ -106,7 +110,8 @@ | ||||
|       <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | ||||
|       <PrecompiledHeader>Use</PrecompiledHeader> | ||||
|       <PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile> | ||||
|       <PreprocessorDefinitions>VCMI_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|       <AdditionalOptions>/Zm130 %(AdditionalOptions)</AdditionalOptions> | ||||
|     </ClCompile> | ||||
|     <Link> | ||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||
| @@ -122,7 +127,7 @@ | ||||
|       <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | ||||
|       <PrecompiledHeader>Use</PrecompiledHeader> | ||||
|       <PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile> | ||||
|       <PreprocessorDefinitions>VCMI_DLL;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|       <PreprocessorDefinitions>_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|     </ClCompile> | ||||
|     <Link> | ||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||
| @@ -140,7 +145,7 @@ | ||||
|       <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | ||||
|       <PrecompiledHeader>Use</PrecompiledHeader> | ||||
|       <PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile> | ||||
|       <PreprocessorDefinitions>VCMI_DLL;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|       <PreprocessorDefinitions>_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|     </ClCompile> | ||||
|     <Link> | ||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||
| @@ -160,7 +165,7 @@ | ||||
|       <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | ||||
|       <PrecompiledHeader>Use</PrecompiledHeader> | ||||
|       <PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile> | ||||
|       <PreprocessorDefinitions>VCMI_DLL;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|       <PreprocessorDefinitions>_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|     </ClCompile> | ||||
|     <Link> | ||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
| #include "../../CCallback.h" | ||||
| #include "../../lib/CCreatureHandler.h" | ||||
|  | ||||
| CPlayerBattleCallback * cbc; | ||||
| shared_ptr<CBattleCallback> cbc; | ||||
|  | ||||
| CStupidAI::CStupidAI(void) | ||||
| 	: side(-1), cb(NULL) | ||||
| @@ -19,7 +19,7 @@ CStupidAI::~CStupidAI(void) | ||||
| 	print("destroyed"); | ||||
| } | ||||
|  | ||||
| void CStupidAI::init( CBattleCallback * CB ) | ||||
| void CStupidAI::init(shared_ptr<CBattleCallback> CB) | ||||
| { | ||||
| 	print("init called, saving ptr to IBattleCallback"); | ||||
| 	cbc = cb = CB; | ||||
|   | ||||
| @@ -5,14 +5,14 @@ | ||||
| class CStupidAI : public CBattleGameInterface | ||||
| { | ||||
| 	int side; | ||||
| 	CBattleCallback *cb; | ||||
| 	shared_ptr<CBattleCallback> cb; | ||||
|  | ||||
| 	void print(const std::string &text) const; | ||||
| public: | ||||
| 	CStupidAI(void); | ||||
| 	~CStupidAI(void); | ||||
|  | ||||
| 	void init(CBattleCallback * CB) OVERRIDE; | ||||
| 	void init(shared_ptr<CBattleCallback> CB) OVERRIDE; | ||||
| 	void actionFinished(const BattleAction &action) OVERRIDE;//occurs AFTER every action taken by any stack or by the hero | ||||
| 	void actionStarted(const BattleAction &action) OVERRIDE;//occurs BEFORE every action taken by any stack or by the hero | ||||
| 	BattleAction activeStack(const CStack * stack) OVERRIDE; //called when it's turn of that stack | ||||
|   | ||||
| @@ -34,7 +34,7 @@ struct SetGlobalState | ||||
| 		assert(!cb.get()); | ||||
|  | ||||
| 		ai.reset(AI); | ||||
| 		cb.reset(AI->myCb); | ||||
| 		cb.reset(AI->myCb.get()); | ||||
| 	} | ||||
| 	~SetGlobalState() | ||||
| 	{ | ||||
| @@ -823,7 +823,7 @@ void VCAI::showMarketWindow(const IMarket *market, const CGHeroInstance *visitor | ||||
| 	NET_EVENT_HANDLER; | ||||
| } | ||||
|  | ||||
| void VCAI::init(CCallback * CB) | ||||
| void VCAI::init(shared_ptr<CCallback> CB) | ||||
| { | ||||
| 	LOG_TRACE(logAi); | ||||
| 	myCb = CB; | ||||
|   | ||||
| @@ -291,7 +291,7 @@ public: | ||||
| 	AIStatus status; | ||||
| 	std::string battlename; | ||||
|  | ||||
| 	CCallback *myCb; | ||||
| 	shared_ptr<CCallback> myCb; | ||||
|  | ||||
| 	unique_ptr<boost::thread> makingTurn; | ||||
|  | ||||
| @@ -306,7 +306,7 @@ public: | ||||
|  | ||||
| 	virtual std::string getBattleAIName() const OVERRIDE; | ||||
|  | ||||
| 	virtual void init(CCallback * CB) OVERRIDE; | ||||
| 	virtual void init(shared_ptr<CCallback> CB) OVERRIDE; | ||||
| 	virtual void yourTurn() OVERRIDE; | ||||
|  | ||||
| 	virtual void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) OVERRIDE; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id | ||||
|   | ||||
| @@ -35,6 +35,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Editor", "editor\Editor.vcx | ||||
| 		{B952FFC5-3039-4DE1-9F08-90ACDA483D8F} = {B952FFC5-3039-4DE1-9F08-90ACDA483D8F} | ||||
| 	EndProjectSection | ||||
| EndProject | ||||
| Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EmptyAI", "AI\EmptyAI\EmptyAI.vcxproj", "{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}" | ||||
| 	ProjectSection(ProjectDependencies) = postProject | ||||
| 		{B952FFC5-3039-4DE1-9F08-90ACDA483D8F} = {B952FFC5-3039-4DE1-9F08-90ACDA483D8F} | ||||
| 	EndProjectSection | ||||
| EndProject | ||||
| Global | ||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| 		Debug|Win32 = Debug|Win32 | ||||
| @@ -146,6 +151,18 @@ Global | ||||
| 		{B12702AD-ABFB-343A-A199-8E24837244A3}.Release|Win32.ActiveCfg = Release|Win32 | ||||
| 		{B12702AD-ABFB-343A-A199-8E24837244A3}.Release|Win32.Build.0 = Release|Win32 | ||||
| 		{B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.ActiveCfg = Release|Win32 | ||||
| 		{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.Debug|Win32.ActiveCfg = Debug|Win32 | ||||
| 		{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.Debug|Win32.Build.0 = Debug|Win32 | ||||
| 		{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.Debug|x64.ActiveCfg = Debug|x64 | ||||
| 		{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.Debug|x64.Build.0 = Debug|x64 | ||||
| 		{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.RD|Win32.ActiveCfg = RD|Win32 | ||||
| 		{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.RD|Win32.Build.0 = RD|Win32 | ||||
| 		{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.RD|x64.ActiveCfg = RD|x64 | ||||
| 		{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.RD|x64.Build.0 = RD|x64 | ||||
| 		{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.Release|Win32.ActiveCfg = RD|Win32 | ||||
| 		{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.Release|Win32.Build.0 = RD|Win32 | ||||
| 		{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.Release|x64.ActiveCfg = RD|x64 | ||||
| 		{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.Release|x64.Build.0 = RD|x64 | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(SolutionProperties) = preSolution | ||||
| 		HideSolutionNode = FALSE | ||||
|   | ||||
| @@ -135,9 +135,9 @@ CPlayerInterface::~CPlayerInterface() | ||||
|  | ||||
| 	LOCPLINT = NULL; | ||||
| } | ||||
| void CPlayerInterface::init(CCallback * CB) | ||||
| void CPlayerInterface::init(shared_ptr<CCallback> CB) | ||||
| { | ||||
| 	cb = dynamic_cast<CCallback*>(CB); | ||||
| 	cb = CB; | ||||
| 	if(observerInDuelMode) | ||||
| 		return; | ||||
|  | ||||
|   | ||||
| @@ -101,7 +101,7 @@ public: | ||||
| 	static CBattleInterface * battleInt; //NULL if no battle | ||||
| 	CInGameConsole * cingconsole; | ||||
|  | ||||
| 	CCallback * cb; //to communicate with engine | ||||
| 	shared_ptr<CCallback> cb; //to communicate with engine | ||||
| 	const BattleAction *curAction; //during the battle - action currently performed by active stack (or NULL) | ||||
|  | ||||
| 	std::list<CInfoWindow *> dialogs; //queue of dialogs awaiting to be shown (not currently shown!) | ||||
| @@ -221,7 +221,7 @@ public: | ||||
| 	void openTownWindow(const CGTownInstance * town); //shows townscreen | ||||
| 	void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero | ||||
| 	void updateInfo(const CGObjectInstance * specific); | ||||
| 	void init(CCallback * CB); | ||||
| 	void init(shared_ptr<CCallback> CB); | ||||
| 	int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on | ||||
| 	void showInfoDialog(const std::string &text, CComponent * component); | ||||
| 	void showInfoDialog(const std::string &text, const std::vector<CComponent*> & components = std::vector<CComponent*>(), int soundID = 0, bool delComps = false); | ||||
|   | ||||
| @@ -91,7 +91,6 @@ void CClient::init() | ||||
| 	IObjectInterface::cb = this; | ||||
| 	serv = nullptr; | ||||
| 	gs = nullptr; | ||||
| 	cb = nullptr; | ||||
| 	erm = nullptr; | ||||
| 	terminate = false; | ||||
| } | ||||
| @@ -216,6 +215,7 @@ void CClient::endGame( bool closeConnection /*= true*/ ) | ||||
| 	} | ||||
|  | ||||
| 	callbacks.clear(); | ||||
| 	battleCallbacks.clear(); | ||||
|     logNetwork->infoStream() << "Deleted playerInts."; | ||||
|  | ||||
|     logNetwork->infoStream() << "Client stopped."; | ||||
| @@ -372,7 +372,6 @@ void CClient::newGame( CConnection *con, StartInfo *si ) | ||||
| 	} | ||||
|  | ||||
| 	int humanPlayers = 0; | ||||
| 	int sensibleAILimit = settings["session"]["oneGoodAI"].Bool() ? 1 : PlayerColor::PLAYER_LIMIT_I; | ||||
| 	for(auto it = gs->scenarioOps->playerInfos.begin();  | ||||
| 		it != gs->scenarioOps->playerInfos.end(); ++it)//initializing interfaces for players | ||||
| 	{ | ||||
| @@ -384,45 +383,22 @@ void CClient::newGame( CConnection *con, StartInfo *si ) | ||||
|         logNetwork->traceStream() << "Preparing interface for player " << color; | ||||
| 		if(si->mode != StartInfo::DUEL) | ||||
| 		{ | ||||
| 			auto cb = make_shared<CCallback>(gs,color,this); | ||||
| 			if(it->second.playerID == PlayerSettings::PLAYER_AI) | ||||
| 			{ | ||||
| 				std::string AItoGive = settings["server"]["playerAI"].String(); | ||||
| 				if(!sensibleAILimit) | ||||
| 					AItoGive = "EmptyAI"; | ||||
| 				else | ||||
| 					sensibleAILimit--; | ||||
| 				playerint[color] = static_cast<CGameInterface*>(CDynLibHandler::getNewAI(AItoGive)); | ||||
|                 logNetwork->infoStream() << "Player " << static_cast<int>(color.getNum()) << " will be lead by " << AItoGive; | ||||
| 				auto AiToGive = aiNameForPlayer(it->second, false); | ||||
| 				logNetwork->infoStream() << boost::format("Player %s will be lead by %s") % color % AiToGive; | ||||
| 				installNewPlayerInterface(CDynLibHandler::getNewAI(AiToGive), color); | ||||
| 			} | ||||
| 			else  | ||||
| 			{ | ||||
| 				playerint[color] = new CPlayerInterface(color); | ||||
| 				installNewPlayerInterface(new CPlayerInterface(color), color); | ||||
| 				humanPlayers++; | ||||
| 			} | ||||
| 			battleints[color] = playerint[color]; | ||||
|  | ||||
|             logNetwork->traceStream() << "\tInitializing the interface"; | ||||
| 			playerint[color]->init(cb.get()); | ||||
| 			battleCallbacks[color] = callbacks[color] = cb; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			auto cbc = make_shared<CBattleCallback>(gs, color, this); | ||||
| 			battleCallbacks[color] = cbc; | ||||
|  | ||||
| 			std::string AItoGive = it->second.name; | ||||
| 			if(AItoGive.empty()) | ||||
| 			{ | ||||
| 				if(color == PlayerColor(0)) | ||||
| 					battleints[color] = CDynLibHandler::getNewBattleAI(settings["server"]["neutralAI"].String()); | ||||
| 				else | ||||
| 					battleints[color] = CDynLibHandler::getNewBattleAI("StupidAI"); | ||||
| 			} | ||||
|  | ||||
|  | ||||
| 			battleints[color] = CDynLibHandler::getNewBattleAI(AItoGive); | ||||
| 			battleints[color]->init(cbc.get()); | ||||
| 			std::string AItoGive = aiNameForPlayer(it->second, true); | ||||
| 			installNewBattleInterface(CDynLibHandler::getNewBattleAI(AItoGive), color); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -433,12 +409,8 @@ void CClient::newGame( CConnection *con, StartInfo *si ) | ||||
| 			boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim); | ||||
| 			CPlayerInterface *p = new CPlayerInterface(PlayerColor::NEUTRAL); | ||||
| 			p->observerInDuelMode = true; | ||||
| 			battleints[PlayerColor::UNFLAGGABLE] = playerint[PlayerColor::UNFLAGGABLE] = p; | ||||
| 			privilagedBattleEventReceivers.push_back(p); | ||||
| 			installNewPlayerInterface(p, boost::none); | ||||
| 			GH.curInt = p; | ||||
| 			auto cb = make_shared<CCallback>(gs, boost::optional<PlayerColor>(), this); | ||||
| 			battleCallbacks[PlayerColor::NEUTRAL] = callbacks[PlayerColor::NEUTRAL] = cb; | ||||
| 			p->init(cb.get()); | ||||
| 		} | ||||
| 		battleStarted(gs->curB); | ||||
| 	} | ||||
| @@ -502,10 +474,7 @@ void CClient::serialize( Handler &h, const int version ) | ||||
| 			{ | ||||
| 				if(pid == PlayerColor::NEUTRAL) | ||||
| 				{ | ||||
| 					//CBattleCallback * cbc = new CBattleCallback(gs, pid, this);//FIXME: unused? | ||||
| 					CBattleGameInterface *cbgi = CDynLibHandler::getNewBattleAI(dllname); | ||||
| 					battleints[pid] = cbgi; | ||||
| 					cbgi->init(cb); | ||||
| 					installNewBattleInterface(CDynLibHandler::getNewBattleAI(dllname), pid); | ||||
| 					//TODO? consider serialization  | ||||
| 					continue; | ||||
| 				} | ||||
| @@ -525,9 +494,7 @@ void CClient::serialize( Handler &h, const int version ) | ||||
| 			nInt->human = isHuman; | ||||
| 			nInt->playerID = pid; | ||||
|  | ||||
| 			battleCallbacks[pid] = callbacks[pid] = make_shared<CCallback>(gs,pid,this); | ||||
| 			battleints[pid] = playerint[pid] = nInt; | ||||
| 			nInt->init(callbacks[pid].get()); | ||||
| 			installNewPlayerInterface(nInt, pid); | ||||
| 			nInt->loadGame(dynamic_cast<CISer<CLoadFile>&>(h), version); //another evil cast, check above | ||||
| 		} | ||||
|  | ||||
| @@ -658,10 +625,7 @@ void CClient::battleFinished() | ||||
|  | ||||
| void CClient::loadNeutralBattleAI() | ||||
| { | ||||
| 	battleints[PlayerColor::NEUTRAL] = CDynLibHandler::getNewBattleAI(settings["server"]["neutralAI"].String()); | ||||
| 	auto cbc = make_shared<CBattleCallback>(gs, PlayerColor::NEUTRAL, this); | ||||
| 	battleCallbacks[PlayerColor::NEUTRAL] = cbc; | ||||
| 	battleints[PlayerColor::NEUTRAL]->init(cbc.get()); | ||||
| 	installNewBattleInterface(CDynLibHandler::getNewBattleAI(settings["server"]["neutralAI"].String()), PlayerColor::NEUTRAL); | ||||
| } | ||||
|  | ||||
| void CClient::commitPackage( CPackForClient *pack ) | ||||
| @@ -746,6 +710,65 @@ void CClient::campaignMapFinished( shared_ptr<CCampaignState> camp ) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CClient::installNewPlayerInterface(CGameInterface *gameInterface, boost::optional<PlayerColor> color) | ||||
| { | ||||
| 	boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim); | ||||
| 	PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE); | ||||
|  | ||||
| 	if(!color)  | ||||
| 		privilagedGameEventReceivers.push_back(gameInterface); | ||||
|  | ||||
| 	playerint[colorUsed] = gameInterface; | ||||
|  | ||||
| 	logGlobal->traceStream() << boost::format("\tInitializing the interface for player %s") % colorUsed; | ||||
| 	auto cb = make_shared<CCallback>(gs, color, this); | ||||
| 	callbacks[colorUsed] = cb; | ||||
| 	battleCallbacks[colorUsed] = cb; | ||||
| 	gameInterface->init(cb); | ||||
|  | ||||
| 	installNewBattleInterface(gameInterface, color, false); | ||||
| } | ||||
|  | ||||
| void CClient::installNewBattleInterface(CBattleGameInterface* battleInterface, boost::optional<PlayerColor> color, bool needCallback /*= true*/) | ||||
| { | ||||
| 	boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim); | ||||
| 	PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE); | ||||
|  | ||||
| 	if(!color)  | ||||
| 		privilagedBattleEventReceivers.push_back(battleInterface); | ||||
|  | ||||
| 	battleints[colorUsed] = battleInterface; | ||||
|  | ||||
| 	if(needCallback) | ||||
| 	{ | ||||
| 		logGlobal->traceStream() << boost::format("\tInitializing the battle interface for player %s") % *color; | ||||
| 		auto cbc = make_shared<CBattleCallback>(gs, color, this); | ||||
| 		battleCallbacks[colorUsed] = cbc; | ||||
| 		battleInterface->init(cbc); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| std::string CClient::aiNameForPlayer(const PlayerSettings &ps, bool battleAI) | ||||
| { | ||||
| 	if(ps.name.size()) | ||||
| 	{ | ||||
| 		std::string filename = VCMIDirs::get().libraryPath() + "/AI/" + VCMIDirs::get().libraryName(ps.name); | ||||
| 		if(boost::filesystem::exists(filename)) | ||||
| 			return ps.name; | ||||
| 	} | ||||
|  | ||||
| 	const int sensibleAILimit = settings["session"]["oneGoodAI"].Bool() ? 1 : PlayerColor::PLAYER_LIMIT_I; | ||||
| 	std::string goodAI = battleAI ? settings["server"]["neutralAI"].String() : settings["server"]["playerAI"].String(); | ||||
| 	std::string badAI = battleAI ? "StupidAI" : "EmptyAI"; | ||||
|  | ||||
|  | ||||
| 	//TODO what about human players | ||||
| 	if(battleints.size() >= sensibleAILimit) | ||||
| 		return badAI; | ||||
|  | ||||
| 	return goodAI; | ||||
| } | ||||
|  | ||||
| template void CClient::serialize( CISer<CLoadFile> &h, const int version ); | ||||
| template void CClient::serialize( COSer<CSaveFile> &h, const int version ); | ||||
|  | ||||
|   | ||||
| @@ -112,7 +112,6 @@ public: | ||||
| class CClient : public IGameCallback | ||||
| { | ||||
| public: | ||||
| 	CCallback *cb; | ||||
| 	std::map<PlayerColor,shared_ptr<CCallback> > callbacks; //callbacks given to player interfaces | ||||
| 	std::map<PlayerColor,shared_ptr<CBattleCallback> > battleCallbacks; //callbacks given to player interfaces | ||||
| 	std::vector<IGameEventsReceiver*> privilagedGameEventReceivers; //scripting modules, spectator interfaces | ||||
| @@ -141,6 +140,10 @@ public: | ||||
| 	void newGame(CConnection *con, StartInfo *si); //con - connection to server | ||||
|  | ||||
| 	void loadNeutralBattleAI(); | ||||
| 	void installNewPlayerInterface(CGameInterface *gameInterface, boost::optional<PlayerColor> color); | ||||
| 	void installNewBattleInterface(CBattleGameInterface* battleInterface, boost::optional<PlayerColor> color, bool needCallback = true); | ||||
| 	std::string aiNameForPlayer(const PlayerSettings &ps, bool battleAI); //empty means no AI -> human | ||||
|  | ||||
| 	void endGame(bool closeConnection = true); | ||||
| 	void stopConnection(); | ||||
| 	void save(const std::string & fname); | ||||
|   | ||||
| @@ -93,8 +93,8 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe | ||||
| 	  activeStack(NULL), stackToActivate(NULL), selectedStack(NULL), mouseHoveredStack(-1), lastMouseHoveredStackAnimationTime(-1), previouslyHoveredHex(-1), | ||||
| 	  currentlyHoveredHex(-1), attackingHex(-1), tacticianInterface(NULL),  stackCanCastSpell(false), creatureCasting(false), spellDestSelectMode(false), spellSelMode(NO_LOCATION), spellToCast(NULL), sp(NULL), | ||||
| 	  siegeH(NULL), attackerInt(att), defenderInt(defen), curInt(att), animIDhelper(0), | ||||
| 	  givenCommand(NULL), myTurn(false), resWindow(NULL), moveStarted(false), moveSh(-1), bresult(NULL) | ||||
|  | ||||
| 	  givenCommand(NULL), myTurn(false), resWindow(NULL), moveStarted(false), moveSh(-1), bresult(NULL), | ||||
| 	  autofightingAI(nullptr), background(nullptr) | ||||
| { | ||||
| 	OBJ_CONSTRUCTION; | ||||
|  | ||||
| @@ -172,8 +172,16 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		std::vector< std::string > & backref = graphics->battleBacks[ curInt->cb->battleGetBattlefieldType() ]; | ||||
| 		background = BitmapHandler::loadBitmap(backref[ rand() % backref.size()], false ); | ||||
| 		auto bfieldType = (int)curInt->cb->battleGetBattlefieldType(); | ||||
| 		if(graphics->battleBacks.size() <= bfieldType || bfieldType < 0) | ||||
| 			logGlobal->errorStream() << bfieldType << " is not valid battlefield type index!"; | ||||
| 		else if(graphics->battleBacks[bfieldType].empty()) | ||||
| 			logGlobal->errorStream() << bfieldType << " battlefield type does not have any backgrounds!"; | ||||
| 		else | ||||
| 		{ | ||||
| 			const std::string bgName = vstd::pickRandomElementOf(graphics->battleBacks[bfieldType], rand); | ||||
| 			background = BitmapHandler::loadBitmap(bgName, false); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	//preparing menu background | ||||
| @@ -446,6 +454,8 @@ CBattleInterface::~CBattleInterface() | ||||
|  | ||||
| 	delete siegeH; | ||||
|  | ||||
| 	delete autofightingAI; | ||||
|  | ||||
| 	//TODO: play AI tracks if battle was during AI turn | ||||
| 	//if (!curInt->makingTurn) | ||||
| 	//CCS->musich->playMusicFromSet(CCS->musich->aiMusics, -1); | ||||
| @@ -1254,6 +1264,39 @@ void CBattleInterface::bAutofightf() | ||||
| { | ||||
| 	if(spellDestSelectMode) //we are casting a spell | ||||
| 		return; | ||||
| 	 | ||||
| 	static bool isAutoFightOn = false; | ||||
| 	static unique_ptr<boost::thread> aiThread = nullptr; | ||||
|  | ||||
| 	if(isAutoFightOn) | ||||
| 	{ | ||||
| 		assert(autofightingAI); | ||||
| 		isAutoFightOn = false; | ||||
| 		aiThread->join(); | ||||
|  | ||||
| 		vstd::clear_pointer(autofightingAI); | ||||
| 		aiThread = nullptr; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		isAutoFightOn = true; | ||||
| 		autofightingAI = CDynLibHandler::getNewBattleAI(settings["server"]["neutralAI"].String()); | ||||
| 		autofightingAI->init(curInt->cb); | ||||
| 		autofightingAI->battleStart(army1, army2, int3(0,0,0), attackingHeroInstance, defendingHeroInstance, curInt->cb->battleGetMySide()); | ||||
|  | ||||
| 		//Deactivate everything | ||||
| 		deactivate(); | ||||
| 		bAutofight->activate(); //only autofight button is to remain active | ||||
| 		aiThread = make_unique<boost::thread>([&]  | ||||
| 		{ | ||||
| 			auto ba = new BattleAction(autofightingAI->activeStack(activeStack)); | ||||
|  | ||||
| 			if(isAutoFightOn) | ||||
| 			{ | ||||
| 				givenCommand->setn(ba); | ||||
| 			} | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CBattleInterface::bSpellf() | ||||
|   | ||||
| @@ -48,6 +48,7 @@ class CClickableHex; | ||||
| struct BattleHex; | ||||
| struct InfoAboutHero; | ||||
| struct BattleAction; | ||||
| class CBattleGameInterface; | ||||
|  | ||||
| /// Class which manages the locked hex fields that are blocked e.g. by obstacles | ||||
| class CBattleObstacle | ||||
| @@ -155,6 +156,8 @@ private: | ||||
| 	PossibleActions selectedAction; //last action chosen (and saved) by player | ||||
| 	PossibleActions illegalAction; //most likely action that can't be performed here | ||||
|  | ||||
| 	CBattleGameInterface *autofightingAI; | ||||
|  | ||||
| 	void getPossibleActionsForStack (const CStack * stack); //called when stack gets its turn | ||||
| 	void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled) | ||||
|  | ||||
|   | ||||
| @@ -61,7 +61,7 @@ public: | ||||
| 	std::string dllName; | ||||
|  | ||||
| 	virtual ~CBattleGameInterface() {}; | ||||
| 	virtual void init(CBattleCallback * CB){}; | ||||
| 	virtual void init(shared_ptr<CBattleCallback> CB){}; | ||||
|  | ||||
| 	//battle call-ins | ||||
| 	virtual BattleAction activeStack(const CStack * stack)=0; //called when it's turn of that stack | ||||
| @@ -76,7 +76,7 @@ public: | ||||
| class CGameInterface : public CBattleGameInterface, public IGameEventsReceiver | ||||
| { | ||||
| public: | ||||
| 	virtual void init(CCallback * CB){}; | ||||
| 	virtual void init(shared_ptr<CCallback> CB){}; | ||||
| 	virtual void yourTurn(){}; //called AFTER playerStartsTurn(player) | ||||
|  | ||||
| 	//pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id | ||||
| @@ -115,7 +115,7 @@ public: | ||||
| 	CAdventureAI() : battleAI(NULL), cbc(NULL) {}; | ||||
|  | ||||
| 	CBattleGameInterface *battleAI; | ||||
| 	CBattleCallback *cbc; | ||||
| 	shared_ptr<CBattleCallback> cbc; | ||||
|  | ||||
| 	virtual std::string getBattleAIName() const = 0; //has to return name of the battle AI to be used | ||||
|  | ||||
|   | ||||
| @@ -4384,6 +4384,9 @@ bool CGameHandler::makeCustomAction( BattleAction &ba ) | ||||
| 	{ | ||||
| 	case Battle::HERO_SPELL: | ||||
| 		{ | ||||
| 			COMPLAIN_RET_FALSE_IF(ba.side > 1, "Side must be 0 or 1!"); | ||||
| 				 | ||||
|  | ||||
| 			const CGHeroInstance *h = gs->curB->heroes[ba.side]; | ||||
| 			const CGHeroInstance *secondHero = gs->curB->heroes[!ba.side]; | ||||
| 			if(!h) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user