1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-21 19:19:26 +02:00

More work on auto-fight.

Dynamic libraries return smart-pointers to what they create.
This commit is contained in:
Michał W. Urbańczyk 2013-06-22 21:47:51 +00:00
parent 2be2143844
commit 4a0587d500
15 changed files with 130 additions and 136 deletions

View File

@ -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>();
}

View File

@ -12,19 +12,8 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
{
strcpy(name,NAME);
}
extern "C" DLL_EXPORT char * GetAiNameS()
extern "C" DLL_EXPORT void GetNewAI(shared_ptr<CGlobalAI> &out)
{
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)
{
delete (CEmptyAI*)i;
ais.erase(i);
}
out = make_shared<CEmptyAI>();
}

View File

@ -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>();
}

View File

@ -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>();
}

View File

@ -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;
}

View File

@ -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

View File

@ -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";

View File

@ -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);

View File

@ -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;

View File

@ -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)
{

View File

@ -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

View File

@ -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();

View File

@ -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)

View File

@ -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

View File

@ -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>();
}