Просмотр исходного кода

More work on auto-fight.
Dynamic libraries return smart-pointers to what they create.

Michał W. Urbańczyk 12 лет назад
Родитель
Сommit
4a0587d500

+ 3 - 14
AI/BattleAI/main.cpp

@@ -19,18 +19,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
 	strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
 }
 
-extern "C" DLL_EXPORT char* GetAiNameS()
+extern "C" DLL_EXPORT void GetNewBattleAI(shared_ptr<CBattleGameInterface> &out)
 {
-	// need to be defined
-	return NULL;
-}
-
-extern "C" DLL_EXPORT CBattleGameInterface* GetNewBattleAI()
-{
-	return new CBattleAI();
-}
-
-extern "C" DLL_EXPORT void ReleaseBattleAI(CBattleGameInterface* i)
-{
-	delete (CBattleAI*)i;
-}
+	out = make_shared<CBattleAI>();
+}

+ 4 - 15
AI/EmptyAI/exp_funcs.cpp

@@ -12,19 +12,8 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
 {
 	strcpy(name,NAME);
 }
-extern "C" DLL_EXPORT char * GetAiNameS()
-{
-	char * ret = new char[50];
-	strcpy(ret,NAME);
-	return ret;
-}
-extern "C" DLL_EXPORT CGlobalAI * GetNewAI()
-{
-	return new CEmptyAI();
-// return
-}
-extern "C" DLL_EXPORT void ReleaseAI(CGlobalAI * i)
+
+extern "C" DLL_EXPORT void GetNewAI(shared_ptr<CGlobalAI> &out)
 {
-	delete (CEmptyAI*)i;
-	ais.erase(i);
-}
+	out = make_shared<CEmptyAI>();
+}

+ 3 - 14
AI/StupidAI/main.cpp

@@ -19,18 +19,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
 	strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
 }
 
-extern "C" DLL_EXPORT char* GetAiNameS()
+extern "C" DLL_EXPORT void GetNewBattleAI(shared_ptr<CBattleGameInterface> &out)
 {
-	// need to be defined
-	return NULL;
-}
-
-extern "C" DLL_EXPORT CBattleGameInterface* GetNewBattleAI()
-{
-	return new CStupidAI();
-}
-
-extern "C" DLL_EXPORT void ReleaseBattleAI(CBattleGameInterface* i)
-{
-	delete (CStupidAI*)i;
-}
+	out = make_shared<CStupidAI>();
+}

+ 2 - 2
AI/VCAI/main.cpp

@@ -17,7 +17,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
 	strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
 }
 
-extern "C" DLL_EXPORT CGlobalAI* GetNewAI()
+extern "C" DLL_EXPORT void GetNewAI(shared_ptr<CGlobalAI> &out)
 {
-	return new VCAI();
+	out = make_shared<VCAI>();
 }

+ 5 - 5
CCallback.cpp

@@ -361,7 +361,7 @@ void CCallback::validatePaths()
 	ASSERT_IF_CALLED_WITH_PLAYER
 	const CGHeroInstance *h = cl->IGameCallback::getSelectedHero(*player);
 	if(h  && ( cl->pathInfo->hero != h							//wrong hero
-		       || cl->pathInfo->hpos != h->getPosition(false)  //wrong hero positoin
+		       || cl->pathInfo->hpos != h->getPosition(false)  //wrong hero position
 		       || !cl->pathInfo->isValid)) //paths invalidated by game event
 	{
 		recalculatePaths();
@@ -376,25 +376,25 @@ int CCallback::mergeOrSwapStacks(const CArmedInstance *s1, const CArmedInstance
 		return swapCreatures(s1, s2, p1, p2);
 }
 
-void CCallback::registerGameInterface(CGameInterface *cgi)
+void CCallback::registerGameInterface(shared_ptr<CGameInterface> cgi)
 {
 	cl->additionalPlayerInts[*player].push_back(cgi);
 	registerBattleInterface(cgi);
 }
 
-void CCallback::registerBattleInterface(CBattleGameInterface *cbga)
+void CCallback::registerBattleInterface(shared_ptr<CBattleGameInterface> cbga)
 {
 	cl->additionalBattleInts[*player].push_back(cbga);
 }
 
-void CCallback::unregisterGameInterface(CGameInterface *cgi)
+void CCallback::unregisterGameInterface(shared_ptr<CGameInterface> cgi)
 {
 	cl->additionalPlayerInts[*player] -= cgi;
 	unregisterBattleInterface(cgi);
 
 }
 
-void CCallback::unregisterBattleInterface(CBattleGameInterface *cbga)
+void CCallback::unregisterBattleInterface(shared_ptr<CBattleGameInterface> cbga)
 {
 	cl->additionalBattleInts[*player] -= cbga;
 }

+ 4 - 4
CCallback.h

@@ -114,10 +114,10 @@ public:
 	virtual void recalculatePaths(); //updates main, client pathfinder info (should be called when moving hero is over)
 
 	//Set of metrhods that allows adding more interfaces for this player that'll receive game event call-ins.
-	void registerGameInterface(CGameInterface *cgi);
-	void registerBattleInterface(CBattleGameInterface *cbga);
-	void unregisterGameInterface(CGameInterface *cgi);
-	void unregisterBattleInterface(CBattleGameInterface *cbga);
+	void registerGameInterface(shared_ptr<CGameInterface> cgi);
+	void registerBattleInterface(shared_ptr<CBattleGameInterface> cbga);
+	void unregisterGameInterface(shared_ptr<CGameInterface> cgi);
+	void unregisterBattleInterface(shared_ptr<CBattleGameInterface> cbga);
 
 	void unregisterMyInterface(); //stops delivering information about game events to that player's interface -> can be called ONLY after victory/loss
 

+ 0 - 1
client/CMT.cpp

@@ -706,7 +706,6 @@ void processCommand(const std::string &message)
 		{
 			if(auto ai = CDynLibHandler::getNewBattleAI(fname)) //test that given AI is indeed available... heavy but it is easy to make a typo and break the game
 			{
-				delete ai;
 				Settings neutralAI = settings.write["server"]["neutralAI"];
 				neutralAI->String() = fname;
                 std::cout << "Setting changed, from now the battle ai will be " << fname << "!\n";

+ 13 - 18
client/Client.cpp

@@ -207,13 +207,8 @@ void CClient::endGame( bool closeConnection /*= true*/ )
         logNetwork->infoStream() << "Deleted mapHandler and gameState.";
 		LOCPLINT = NULL;
 	}
-	while (!playerint.empty())
-	{
-		CGameInterface *pint = playerint.begin()->second;
-		playerint.erase(playerint.begin());
-		delete pint;
-	}
 
+	playerint.clear();
 	callbacks.clear();
 	battleCallbacks.clear();
     logNetwork->infoStream() << "Deleted playerInts.";
@@ -391,7 +386,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
 			}
 			else 
 			{
-				installNewPlayerInterface(new CPlayerInterface(color), color);
+				installNewPlayerInterface(make_shared<CPlayerInterface>(color), color);
 				humanPlayers++;
 			}
 		}
@@ -407,10 +402,10 @@ void CClient::newGame( CConnection *con, StartInfo *si )
 		if(!gNoGUI)
 		{
 			boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
-			CPlayerInterface *p = new CPlayerInterface(PlayerColor::NEUTRAL);
+			auto p = make_shared<CPlayerInterface>(PlayerColor::NEUTRAL);
 			p->observerInDuelMode = true;
 			installNewPlayerInterface(p, boost::none);
-			GH.curInt = p;
+			GH.curInt = p.get();
 		}
 		battleStarted(gs->curB);
 	}
@@ -469,7 +464,7 @@ void CClient::serialize( Handler &h, const int version )
 			h & pid & dllname & isHuman;
 			LOG_TRACE_PARAMS(logGlobal, "Loading player %s interface", pid);
 
-			CGameInterface *nInt = nullptr;
+			shared_ptr<CGameInterface> nInt = nullptr;
 			if(dllname.length())
 			{
 				if(pid == PlayerColor::NEUTRAL)
@@ -487,7 +482,7 @@ void CClient::serialize( Handler &h, const int version )
 			else
 			{
 				assert(isHuman);
-				nInt = new CPlayerInterface(pid);
+				nInt = make_shared<CPlayerInterface>(pid);
 			}
 
 			nInt->dllName = dllname;
@@ -584,18 +579,18 @@ void CClient::battleStarted(const BattleInfo * info)
 // 		if(battleCallbacks.count(side))
 // 			battleCallbacks[side]->setBattle(info);
 
-	CPlayerInterface * att, * def;
+	shared_ptr<CPlayerInterface> att, def;
 	if(vstd::contains(playerint, info->sides[0]) && playerint[info->sides[0]]->human)
-		att = static_cast<CPlayerInterface*>( playerint[info->sides[0]] );
+		att = std::dynamic_pointer_cast<CPlayerInterface>( playerint[info->sides[0]] );
 	else
 		att = NULL;
 
 	if(vstd::contains(playerint, info->sides[1]) && playerint[info->sides[1]]->human)
-		def = static_cast<CPlayerInterface*>( playerint[info->sides[1]] );
+		def = std::dynamic_pointer_cast<CPlayerInterface>( playerint[info->sides[1]] );
 	else
 		def = NULL;
 
-	if(!gNoGUI && (att || def || gs->scenarioOps->mode == StartInfo::DUEL))
+	if(!gNoGUI && (!!att || !!def || gs->scenarioOps->mode == StartInfo::DUEL))
 	{
 		boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
 		new CBattleInterface(info->belligerents[0], info->belligerents[1], info->heroes[0], info->heroes[1],
@@ -650,7 +645,7 @@ void CClient::calculatePaths(const CGHeroInstance *h)
 	gs->calculatePaths(h, *pathInfo);
 }
 
-void CClient::commenceTacticPhaseForInt(CBattleGameInterface *battleInt)
+void CClient::commenceTacticPhaseForInt(shared_ptr<CBattleGameInterface> battleInt)
 {
 	setThreadName("CClient::commenceTacticPhaseForInt");
 	try
@@ -710,7 +705,7 @@ void CClient::campaignMapFinished( shared_ptr<CCampaignState> camp )
 	}
 }
 
-void CClient::installNewPlayerInterface(CGameInterface *gameInterface, boost::optional<PlayerColor> color)
+void CClient::installNewPlayerInterface(shared_ptr<CGameInterface> gameInterface, boost::optional<PlayerColor> color)
 {
 	boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
 	PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE);
@@ -729,7 +724,7 @@ void CClient::installNewPlayerInterface(CGameInterface *gameInterface, boost::op
 	installNewBattleInterface(gameInterface, color, false);
 }
 
-void CClient::installNewBattleInterface(CBattleGameInterface* battleInterface, boost::optional<PlayerColor> color, bool needCallback /*= true*/)
+void CClient::installNewBattleInterface(shared_ptr<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);

+ 9 - 9
client/Client.h

@@ -114,13 +114,13 @@ class CClient : public IGameCallback
 public:
 	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
-	std::vector<IBattleEventsReceiver*> privilagedBattleEventReceivers; //scripting modules, spectator interfaces
-	std::map<PlayerColor,CGameInterface *> playerint;
-	std::map<PlayerColor,CBattleGameInterface *> battleints;
+	std::vector<shared_ptr<IGameEventsReceiver>> privilagedGameEventReceivers; //scripting modules, spectator interfaces
+	std::vector<shared_ptr<IBattleEventsReceiver>> privilagedBattleEventReceivers; //scripting modules, spectator interfaces
+	std::map<PlayerColor, shared_ptr<CGameInterface>> playerint;
+	std::map<PlayerColor, shared_ptr<CBattleGameInterface>> battleints;
 
-	std::map<PlayerColor,std::vector<CGameInterface *>> additionalPlayerInts;
-	std::map<PlayerColor,std::vector<CBattleGameInterface *>> additionalBattleInts;
+	std::map<PlayerColor,std::vector<shared_ptr<CGameInterface>>> additionalPlayerInts;
+	std::map<PlayerColor,std::vector<shared_ptr<CBattleGameInterface>>> additionalBattleInts;
 
 	bool hotSeat;
 	CConnection *serv;
@@ -144,8 +144,8 @@ 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);
+	void installNewPlayerInterface(shared_ptr<CGameInterface> gameInterface, boost::optional<PlayerColor> color);
+	void installNewBattleInterface(shared_ptr<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);
@@ -229,7 +229,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 commenceTacticPhaseForInt(shared_ptr<CBattleGameInterface> battleInt); //will be called as separate thread
 
 	void commitPackage(CPackForClient *pack) OVERRIDE;
 

+ 46 - 25
client/battle/CBattleInterface.cpp

@@ -88,24 +88,31 @@ void CBattleInterface::addNewAnim(CBattleAnimation * anim)
 	animsAreDisplayed.setn(true);
 }
 
-CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, const SDL_Rect & myRect, CPlayerInterface * att, CPlayerInterface * defen)
+CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, 
+								   CGHeroInstance *hero1, CGHeroInstance *hero2, 
+								   const SDL_Rect & myRect, 
+								   shared_ptr<CPlayerInterface> att, shared_ptr<CPlayerInterface> defen)
 	: queue(NULL), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0),
 	  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),
-	  autofightingAI(nullptr), background(nullptr)
+	  autofightingAI(nullptr), isAutoFightOn(false), aiThread(nullptr), background(nullptr)
 {
 	OBJ_CONSTRUCTION;
 
-	if(!curInt) curInt = LOCPLINT; //may happen when we are defending during network MP game
+	if(!curInt)
+	{
+		//May happen when we are defending during network MP game -> attacker interface is just not present
+		curInt = defenderInt; 
+	}
 
 	animsAreDisplayed.setn(false);
 	pos = myRect;
 	strongInterest = true;
 	givenCommand = new CondSh<BattleAction *>(NULL);
 
-	if(attackerInt && attackerInt->cb->battleGetTacticDist()) //hotseat -> check tactics for both players (defender may be local human)
+	if(attackerInt && attackerInt->cb->battleGetTacticDist()) //hot-seat -> check tactics for both players (defender may be local human)
 		tacticianInterface = attackerInt;
 	else if(defenderInt && defenderInt->cb->battleGetTacticDist())
 		tacticianInterface = defenderInt;
@@ -453,9 +460,7 @@ CBattleInterface::~CBattleInterface()
 	delete bigForceField[1];
 
 	delete siegeH;
-
-	delete autofightingAI;
-
+	
 	//TODO: play AI tracks if battle was during AI turn
 	//if (!curInt->makingTurn)
 	//CCS->musich->playMusicFromSet(CCS->musich->aiMusics, -1);
@@ -493,6 +498,12 @@ void CBattleInterface::setPrintMouseShadow(bool set)
 
 void CBattleInterface::activate()
 {
+	if(isAutoFightOn)
+	{
+		bAutofight->activate();
+		return;
+	}
+
 	CIntObject::activate();
 	bOptions->activate();
 	bSurrender->activate();
@@ -1265,16 +1276,16 @@ void CBattleInterface::bAutofightf()
 	if(spellDestSelectMode) //we are casting a spell
 		return;
 	
-	static bool isAutoFightOn = false;
-	static unique_ptr<boost::thread> aiThread = nullptr;
-
+	//Stop auto-fight mode
 	if(isAutoFightOn)
 	{
 		assert(autofightingAI);
 		isAutoFightOn = false;
+		logGlobal->traceStream() << "Stopping the autofight...";
+		aiThread->interrupt();
 		aiThread->join();
 
-		vstd::clear_pointer(autofightingAI);
+		autofightingAI = nullptr;
 		aiThread = nullptr;
 	}
 	else
@@ -1284,18 +1295,7 @@ void CBattleInterface::bAutofightf()
 		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);
-			}
-		});
+		requestAutofightingAIToTakeAction();
 	}
 }
 
@@ -1313,7 +1313,7 @@ void CBattleInterface::bSpellf()
 	ESpellCastProblem::ESpellCastProblem spellCastProblem;
 	if (curInt->cb->battleCanCastSpell(&spellCastProblem))
 	{
-		CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (screen->w - 620)/2, (screen->h - 595)/2), myHero, curInt);
+		CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (screen->w - 620)/2, (screen->h - 595)/2), myHero, curInt.get());
 		GH.pushInt(spellWindow);
 	}
 	else if(spellCastProblem == ESpellCastProblem::MAGIC_IS_BLOCKED)
@@ -2057,7 +2057,7 @@ void CBattleInterface::activateStack()
 	const CStack *s = activeStack;
 
 	myTurn = true;
-	if(attackerInt && defenderInt) //hotseat -> need to pick which interface "takes over" as active
+	if(!!attackerInt && defenderInt) //hotseat -> need to pick which interface "takes over" as active
 		curInt = attackerInt->playerID == s->owner ? attackerInt : defenderInt;
 
 	queue->update();
@@ -2096,6 +2096,9 @@ void CBattleInterface::activateStack()
 	if(!pendingAnims.size() && !active)
 		activate();
 
+	if(isAutoFightOn)
+		requestAutofightingAIToTakeAction();
+
 	GH.fakeMouseMove();
 }
 
@@ -3585,6 +3588,24 @@ InfoAboutHero CBattleInterface::enemyHero() const
 	return ret;
 }
 
+void CBattleInterface::requestAutofightingAIToTakeAction()
+{
+	assert(isAutoFightOn);
+
+	deactivate();
+	bAutofight->activate();
+
+	aiThread = make_unique<boost::thread>([&] 
+	{
+		auto ba = new BattleAction(autofightingAI->activeStack(activeStack));
+
+		if(isAutoFightOn)
+		{
+			givenCommand->setn(ba);
+		}
+	});
+}
+
 CBattleInterface::SiegeHelper::SiegeHelper(const CGTownInstance *siegeTown, const CBattleInterface * _owner)
   : owner(_owner), town(siegeTown)
 {

+ 9 - 5
client/battle/CBattleInterface.h

@@ -140,7 +140,7 @@ private:
 	double getAnimSpeedMultiplier() const; //returns multiplier for number of frames in a group
 	std::map<int, int> standingFrame; //number of frame in standing animation by stack ID, helps in showing 'random moves'
 
-	CPlayerInterface * tacticianInterface; //used during tactics mode, points to the interface of player with higher tactics (can be either attacker or defender in hot-seat), valid onloy for human players
+	shared_ptr<CPlayerInterface> tacticianInterface; //used during tactics mode, points to the interface of player with higher tactics (can be either attacker or defender in hot-seat), valid onloy for human players
 	bool tacticsMode;
 	bool stackCanCastSpell; //if true, active stack could possibly cats some target spell
 	bool creatureCasting; //if true, stack currently aims to cats a spell
@@ -156,7 +156,11 @@ private:
 	PossibleActions selectedAction; //last action chosen (and saved) by player
 	PossibleActions illegalAction; //most likely action that can't be performed here
 
-	CBattleGameInterface *autofightingAI;
+	shared_ptr<CBattleGameInterface> autofightingAI;
+	bool isAutoFightOn;
+	unique_ptr<boost::thread> aiThread;
+
+	void requestAutofightingAIToTakeAction();
 
 	void getPossibleActionsForStack (const CStack * stack); //called when stack gets its turn
 	void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled)
@@ -198,16 +202,16 @@ private:
 		friend class CBattleInterface;
 	} * siegeH;
 
-	CPlayerInterface * attackerInt, * defenderInt; //because LOCPLINT is not enough in hotSeat
+	shared_ptr<CPlayerInterface> attackerInt, defenderInt; //because LOCPLINT is not enough in hotSeat
 	const CGHeroInstance * getActiveHero(); //returns hero that can currently cast a spell
 public:
-	CPlayerInterface * curInt; //current player interface
+	shared_ptr<CPlayerInterface> curInt; //current player interface
 	std::list<std::pair<CBattleAnimation *, bool> > pendingAnims; //currently displayed animations <anim, initialized>
 	void addNewAnim(CBattleAnimation * anim); //adds new anim to pendingAnims
 	ui32 animIDhelper; //for giving IDs for animations
 	static CondSh<bool> animsAreDisplayed; //for waiting with the end of battle for end of anims
 
-	CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, const SDL_Rect & myRect, CPlayerInterface * att, CPlayerInterface * defen); //c-tor
+	CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, const SDL_Rect & myRect, shared_ptr<CPlayerInterface> att, shared_ptr<CPlayerInterface> defen); //c-tor
 	~CBattleInterface(); //d-tor
 
 	//std::vector<TimeInterested*> timeinterested; //animation handling

+ 2 - 2
client/battle/CBattleInterfaceClasses.cpp

@@ -174,7 +174,7 @@ void CBattleHero::clickLeft(tribool down, bool previousState)
 		}
 		CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
 
-		CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (screen->w - 620)/2, (screen->h - 595)/2), myHero, myOwner->curInt);
+		CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (screen->w - 620)/2, (screen->h - 595)/2), myHero, myOwner->curInt.get());
 		GH.pushInt(spellWindow);
 	}
 }
@@ -483,7 +483,7 @@ void CBattleResultWindow::bExitf()
 		return;
 	}
 
-	CPlayerInterface * intTmp = owner->curInt;
+	auto intTmp = owner->curInt;
 	GH.popInts(2); //first - we; second - battle interface
 	intTmp->showingDialog->setn(false);
 	CCS->videoh->close();

+ 24 - 16
lib/CGameInterface.cpp

@@ -22,27 +22,33 @@
  *
  */
 
+
+
 template<typename rett>
-rett * createAny(std::string dllname, std::string methodName)
+shared_ptr<rett> createAny(std::string dllname, std::string methodName)
 {
-	char temp[50];
-	rett * ret=NULL;
-	rett*(*getAI)(); 
-	void(*getName)(char*); 
+	typedef void(*TGetAIFun)(shared_ptr<rett>&); 
+	typedef void(*TGetNameFun)(char*); 
+
+	char temp[150];
+
+	TGetAIFun getAI = nullptr;
+	TGetNameFun getName = nullptr;
+
 
 #ifdef _WIN32
 	HINSTANCE dll = LoadLibraryA(dllname.c_str());
 	if (dll)
 	{
-		getName = (void(*)(char*))GetProcAddress(dll,"GetAiName");
-		getAI = (rett*(*)())GetProcAddress(dll,methodName.c_str());
+		getName = (TGetNameFun)GetProcAddress(dll,"GetAiName");
+		getAI = (TGetAIFun)GetProcAddress(dll,methodName.c_str());
 	}
 #else
 	void *dll = dlopen(dllname.c_str(), RTLD_LOCAL | RTLD_LAZY);
 	if (dll)
 	{
-		getName = (void(*)(char*))dlsym(dll,"GetAiName");
-		getAI = (rett*(*)())dlsym(dll,methodName.c_str());
+		getName = (TGetNameFun)dlsym(dll,"GetAiName");
+		getAI = (TGetAIFun)dlsym(dll,methodName.c_str());
 	}
 	else
         logGlobal->errorStream() << "Error: " << dlerror();
@@ -65,8 +71,9 @@ rett * createAny(std::string dllname, std::string methodName)
 
 	getName(temp);
     logGlobal->infoStream() << "Loaded " << temp;
-	ret = getAI();
 
+	shared_ptr<rett> ret;
+	getAI(ret);
 	if(!ret)
         logGlobal->errorStream() << "Cannot get AI!";
 
@@ -74,26 +81,27 @@ rett * createAny(std::string dllname, std::string methodName)
 }
 
 template<typename rett>
-rett * createAnyAI(std::string dllname, std::string methodName)
+shared_ptr<rett> createAnyAI(std::string dllname, std::string methodName)
 {
     logGlobal->infoStream() << "Opening " << dllname;
 	std::string filename = VCMIDirs::get().libraryName(dllname);
-	rett* ret = createAny<rett>(VCMIDirs::get().libraryPath() + "/AI/" + filename, methodName);
+
+	auto ret = createAny<rett>(VCMIDirs::get().libraryPath() + "/AI/" + filename, methodName);
 	ret->dllName = dllname;
 	return ret;
 }
 
-CGlobalAI * CDynLibHandler::getNewAI(std::string dllname)
+shared_ptr<CGlobalAI> CDynLibHandler::getNewAI(std::string dllname)
 {
 	return createAnyAI<CGlobalAI>(dllname, "GetNewAI");
 }
 
-CBattleGameInterface * CDynLibHandler::getNewBattleAI(std::string dllname )
+shared_ptr<CBattleGameInterface> CDynLibHandler::getNewBattleAI(std::string dllname )
 {
 	return createAnyAI<CBattleGameInterface>(dllname, "GetNewBattleAI");
 }
 
-CScriptingModule * CDynLibHandler::getNewScriptingModule(std::string dllname)
+shared_ptr<CScriptingModule> CDynLibHandler::getNewScriptingModule(std::string dllname)
 {
 	return createAny<CScriptingModule>(dllname, "GetNewModule");
 }
@@ -187,7 +195,7 @@ void CAdventureAI::battleSpellCast(const BattleSpellCast *sc)
 void CAdventureAI::battleEnd(const BattleResult *br)
 {
 	battleAI->battleEnd(br);
-	vstd::clear_pointer(battleAI);
+	battleAI = nullptr;
 }
 
 void CAdventureAI::battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, bool tentHeal, si32 lifeDrainFrom)

+ 4 - 4
lib/CGameInterface.h

@@ -96,9 +96,9 @@ public:
 class DLL_LINKAGE CDynLibHandler
 {
 public:
-	static CGlobalAI * getNewAI(std::string dllname);
-	static CBattleGameInterface * getNewBattleAI(std::string dllname);
-	static CScriptingModule * getNewScriptingModule(std::string dllname);
+	static shared_ptr<CGlobalAI> getNewAI(std::string dllname);
+	static shared_ptr<CBattleGameInterface> getNewBattleAI(std::string dllname);
+	static shared_ptr<CScriptingModule> getNewScriptingModule(std::string dllname);
 };
 
 class DLL_LINKAGE CGlobalAI : public CGameInterface // AI class (to derivate)
@@ -114,7 +114,7 @@ class DLL_LINKAGE CAdventureAI : public CGlobalAI
 public:
 	CAdventureAI() : battleAI(NULL), cbc(NULL) {};
 
-	CBattleGameInterface *battleAI;
+	shared_ptr<CBattleGameInterface> battleAI;
 	shared_ptr<CBattleCallback> cbc;
 
 	virtual std::string getBattleAIName() const = 0; //has to return name of the battle AI to be used

+ 2 - 2
scripting/erm/ERMScriptModule.cpp

@@ -28,7 +28,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
 	strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
 }
 
-extern "C" DLL_EXPORT CScriptingModule* GetNewModule()
+extern "C" DLL_EXPORT void GetNewModule(shared_ptr<CScriptingModule> &out)
 {
-	return new ERMInterpreter();
+	out = make_shared<ERMInterpreter>();
 }