mirror of
https://github.com/vcmi/vcmi.git
synced 2025-09-16 09:26:28 +02:00
More work on auto-fight.
Dynamic libraries return smart-pointers to what they create.
This commit is contained in:
@@ -19,18 +19,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
|
|||||||
strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
|
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
|
out = make_shared<CBattleAI>();
|
||||||
return NULL;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" DLL_EXPORT CBattleGameInterface* GetNewBattleAI()
|
|
||||||
{
|
|
||||||
return new CBattleAI();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" DLL_EXPORT void ReleaseBattleAI(CBattleGameInterface* i)
|
|
||||||
{
|
|
||||||
delete (CBattleAI*)i;
|
|
||||||
}
|
|
@@ -12,19 +12,8 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
|
|||||||
{
|
{
|
||||||
strcpy(name,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];
|
out = make_shared<CEmptyAI>();
|
||||||
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);
|
|
||||||
}
|
|
@@ -19,18 +19,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
|
|||||||
strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
|
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
|
out = make_shared<CStupidAI>();
|
||||||
return NULL;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" DLL_EXPORT CBattleGameInterface* GetNewBattleAI()
|
|
||||||
{
|
|
||||||
return new CStupidAI();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" DLL_EXPORT void ReleaseBattleAI(CBattleGameInterface* i)
|
|
||||||
{
|
|
||||||
delete (CStupidAI*)i;
|
|
||||||
}
|
|
@@ -17,7 +17,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
|
|||||||
strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
|
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>();
|
||||||
}
|
}
|
@@ -361,7 +361,7 @@ void CCallback::validatePaths()
|
|||||||
ASSERT_IF_CALLED_WITH_PLAYER
|
ASSERT_IF_CALLED_WITH_PLAYER
|
||||||
const CGHeroInstance *h = cl->IGameCallback::getSelectedHero(*player);
|
const CGHeroInstance *h = cl->IGameCallback::getSelectedHero(*player);
|
||||||
if(h && ( cl->pathInfo->hero != h //wrong hero
|
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
|
|| !cl->pathInfo->isValid)) //paths invalidated by game event
|
||||||
{
|
{
|
||||||
recalculatePaths();
|
recalculatePaths();
|
||||||
@@ -376,25 +376,25 @@ int CCallback::mergeOrSwapStacks(const CArmedInstance *s1, const CArmedInstance
|
|||||||
return swapCreatures(s1, s2, p1, p2);
|
return swapCreatures(s1, s2, p1, p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCallback::registerGameInterface(CGameInterface *cgi)
|
void CCallback::registerGameInterface(shared_ptr<CGameInterface> cgi)
|
||||||
{
|
{
|
||||||
cl->additionalPlayerInts[*player].push_back(cgi);
|
cl->additionalPlayerInts[*player].push_back(cgi);
|
||||||
registerBattleInterface(cgi);
|
registerBattleInterface(cgi);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCallback::registerBattleInterface(CBattleGameInterface *cbga)
|
void CCallback::registerBattleInterface(shared_ptr<CBattleGameInterface> cbga)
|
||||||
{
|
{
|
||||||
cl->additionalBattleInts[*player].push_back(cbga);
|
cl->additionalBattleInts[*player].push_back(cbga);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCallback::unregisterGameInterface(CGameInterface *cgi)
|
void CCallback::unregisterGameInterface(shared_ptr<CGameInterface> cgi)
|
||||||
{
|
{
|
||||||
cl->additionalPlayerInts[*player] -= cgi;
|
cl->additionalPlayerInts[*player] -= cgi;
|
||||||
unregisterBattleInterface(cgi);
|
unregisterBattleInterface(cgi);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCallback::unregisterBattleInterface(CBattleGameInterface *cbga)
|
void CCallback::unregisterBattleInterface(shared_ptr<CBattleGameInterface> cbga)
|
||||||
{
|
{
|
||||||
cl->additionalBattleInts[*player] -= cbga;
|
cl->additionalBattleInts[*player] -= cbga;
|
||||||
}
|
}
|
||||||
|
@@ -114,10 +114,10 @@ public:
|
|||||||
virtual void recalculatePaths(); //updates main, client pathfinder info (should be called when moving hero is over)
|
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.
|
//Set of metrhods that allows adding more interfaces for this player that'll receive game event call-ins.
|
||||||
void registerGameInterface(CGameInterface *cgi);
|
void registerGameInterface(shared_ptr<CGameInterface> cgi);
|
||||||
void registerBattleInterface(CBattleGameInterface *cbga);
|
void registerBattleInterface(shared_ptr<CBattleGameInterface> cbga);
|
||||||
void unregisterGameInterface(CGameInterface *cgi);
|
void unregisterGameInterface(shared_ptr<CGameInterface> cgi);
|
||||||
void unregisterBattleInterface(CBattleGameInterface *cbga);
|
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
|
void unregisterMyInterface(); //stops delivering information about game events to that player's interface -> can be called ONLY after victory/loss
|
||||||
|
|
||||||
|
@@ -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
|
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"];
|
Settings neutralAI = settings.write["server"]["neutralAI"];
|
||||||
neutralAI->String() = fname;
|
neutralAI->String() = fname;
|
||||||
std::cout << "Setting changed, from now the battle ai will be " << fname << "!\n";
|
std::cout << "Setting changed, from now the battle ai will be " << fname << "!\n";
|
||||||
|
@@ -207,13 +207,8 @@ void CClient::endGame( bool closeConnection /*= true*/ )
|
|||||||
logNetwork->infoStream() << "Deleted mapHandler and gameState.";
|
logNetwork->infoStream() << "Deleted mapHandler and gameState.";
|
||||||
LOCPLINT = NULL;
|
LOCPLINT = NULL;
|
||||||
}
|
}
|
||||||
while (!playerint.empty())
|
|
||||||
{
|
|
||||||
CGameInterface *pint = playerint.begin()->second;
|
|
||||||
playerint.erase(playerint.begin());
|
|
||||||
delete pint;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
playerint.clear();
|
||||||
callbacks.clear();
|
callbacks.clear();
|
||||||
battleCallbacks.clear();
|
battleCallbacks.clear();
|
||||||
logNetwork->infoStream() << "Deleted playerInts.";
|
logNetwork->infoStream() << "Deleted playerInts.";
|
||||||
@@ -391,7 +386,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
installNewPlayerInterface(new CPlayerInterface(color), color);
|
installNewPlayerInterface(make_shared<CPlayerInterface>(color), color);
|
||||||
humanPlayers++;
|
humanPlayers++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -407,10 +402,10 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
|||||||
if(!gNoGUI)
|
if(!gNoGUI)
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
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;
|
p->observerInDuelMode = true;
|
||||||
installNewPlayerInterface(p, boost::none);
|
installNewPlayerInterface(p, boost::none);
|
||||||
GH.curInt = p;
|
GH.curInt = p.get();
|
||||||
}
|
}
|
||||||
battleStarted(gs->curB);
|
battleStarted(gs->curB);
|
||||||
}
|
}
|
||||||
@@ -469,7 +464,7 @@ void CClient::serialize( Handler &h, const int version )
|
|||||||
h & pid & dllname & isHuman;
|
h & pid & dllname & isHuman;
|
||||||
LOG_TRACE_PARAMS(logGlobal, "Loading player %s interface", pid);
|
LOG_TRACE_PARAMS(logGlobal, "Loading player %s interface", pid);
|
||||||
|
|
||||||
CGameInterface *nInt = nullptr;
|
shared_ptr<CGameInterface> nInt = nullptr;
|
||||||
if(dllname.length())
|
if(dllname.length())
|
||||||
{
|
{
|
||||||
if(pid == PlayerColor::NEUTRAL)
|
if(pid == PlayerColor::NEUTRAL)
|
||||||
@@ -487,7 +482,7 @@ void CClient::serialize( Handler &h, const int version )
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(isHuman);
|
assert(isHuman);
|
||||||
nInt = new CPlayerInterface(pid);
|
nInt = make_shared<CPlayerInterface>(pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
nInt->dllName = dllname;
|
nInt->dllName = dllname;
|
||||||
@@ -584,18 +579,18 @@ void CClient::battleStarted(const BattleInfo * info)
|
|||||||
// if(battleCallbacks.count(side))
|
// if(battleCallbacks.count(side))
|
||||||
// battleCallbacks[side]->setBattle(info);
|
// battleCallbacks[side]->setBattle(info);
|
||||||
|
|
||||||
CPlayerInterface * att, * def;
|
shared_ptr<CPlayerInterface> att, def;
|
||||||
if(vstd::contains(playerint, info->sides[0]) && playerint[info->sides[0]]->human)
|
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
|
else
|
||||||
att = NULL;
|
att = NULL;
|
||||||
|
|
||||||
if(vstd::contains(playerint, info->sides[1]) && playerint[info->sides[1]]->human)
|
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
|
else
|
||||||
def = NULL;
|
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);
|
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||||
new CBattleInterface(info->belligerents[0], info->belligerents[1], info->heroes[0], info->heroes[1],
|
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);
|
gs->calculatePaths(h, *pathInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::commenceTacticPhaseForInt(CBattleGameInterface *battleInt)
|
void CClient::commenceTacticPhaseForInt(shared_ptr<CBattleGameInterface> battleInt)
|
||||||
{
|
{
|
||||||
setThreadName("CClient::commenceTacticPhaseForInt");
|
setThreadName("CClient::commenceTacticPhaseForInt");
|
||||||
try
|
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);
|
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||||
PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE);
|
PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE);
|
||||||
@@ -729,7 +724,7 @@ void CClient::installNewPlayerInterface(CGameInterface *gameInterface, boost::op
|
|||||||
installNewBattleInterface(gameInterface, color, false);
|
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);
|
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||||
PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE);
|
PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE);
|
||||||
|
@@ -114,13 +114,13 @@ class CClient : public IGameCallback
|
|||||||
public:
|
public:
|
||||||
std::map<PlayerColor,shared_ptr<CCallback> > callbacks; //callbacks given to player interfaces
|
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::map<PlayerColor,shared_ptr<CBattleCallback> > battleCallbacks; //callbacks given to player interfaces
|
||||||
std::vector<IGameEventsReceiver*> privilagedGameEventReceivers; //scripting modules, spectator interfaces
|
std::vector<shared_ptr<IGameEventsReceiver>> privilagedGameEventReceivers; //scripting modules, spectator interfaces
|
||||||
std::vector<IBattleEventsReceiver*> privilagedBattleEventReceivers; //scripting modules, spectator interfaces
|
std::vector<shared_ptr<IBattleEventsReceiver>> privilagedBattleEventReceivers; //scripting modules, spectator interfaces
|
||||||
std::map<PlayerColor,CGameInterface *> playerint;
|
std::map<PlayerColor, shared_ptr<CGameInterface>> playerint;
|
||||||
std::map<PlayerColor,CBattleGameInterface *> battleints;
|
std::map<PlayerColor, shared_ptr<CBattleGameInterface>> battleints;
|
||||||
|
|
||||||
std::map<PlayerColor,std::vector<CGameInterface *>> additionalPlayerInts;
|
std::map<PlayerColor,std::vector<shared_ptr<CGameInterface>>> additionalPlayerInts;
|
||||||
std::map<PlayerColor,std::vector<CBattleGameInterface *>> additionalBattleInts;
|
std::map<PlayerColor,std::vector<shared_ptr<CBattleGameInterface>>> additionalBattleInts;
|
||||||
|
|
||||||
bool hotSeat;
|
bool hotSeat;
|
||||||
CConnection *serv;
|
CConnection *serv;
|
||||||
@@ -144,8 +144,8 @@ public:
|
|||||||
void newGame(CConnection *con, StartInfo *si); //con - connection to server
|
void newGame(CConnection *con, StartInfo *si); //con - connection to server
|
||||||
|
|
||||||
void loadNeutralBattleAI();
|
void loadNeutralBattleAI();
|
||||||
void installNewPlayerInterface(CGameInterface *gameInterface, boost::optional<PlayerColor> color);
|
void installNewPlayerInterface(shared_ptr<CGameInterface> gameInterface, boost::optional<PlayerColor> color);
|
||||||
void installNewBattleInterface(CBattleGameInterface* battleInterface, boost::optional<PlayerColor> color, bool needCallback = true);
|
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
|
std::string aiNameForPlayer(const PlayerSettings &ps, bool battleAI); //empty means no AI -> human
|
||||||
|
|
||||||
void endGame(bool closeConnection = true);
|
void endGame(bool closeConnection = true);
|
||||||
@@ -229,7 +229,7 @@ public:
|
|||||||
|
|
||||||
void handlePack( CPack * pack ); //applies the given pack and deletes it
|
void handlePack( CPack * pack ); //applies the given pack and deletes it
|
||||||
void battleStarted(const BattleInfo * info);
|
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;
|
void commitPackage(CPackForClient *pack) OVERRIDE;
|
||||||
|
|
||||||
|
@@ -88,24 +88,31 @@ void CBattleInterface::addNewAnim(CBattleAnimation * anim)
|
|||||||
animsAreDisplayed.setn(true);
|
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),
|
: queue(NULL), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0),
|
||||||
activeStack(NULL), stackToActivate(NULL), selectedStack(NULL), mouseHoveredStack(-1), lastMouseHoveredStackAnimationTime(-1), previouslyHoveredHex(-1),
|
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),
|
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),
|
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)
|
autofightingAI(nullptr), isAutoFightOn(false), aiThread(nullptr), background(nullptr)
|
||||||
{
|
{
|
||||||
OBJ_CONSTRUCTION;
|
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);
|
animsAreDisplayed.setn(false);
|
||||||
pos = myRect;
|
pos = myRect;
|
||||||
strongInterest = true;
|
strongInterest = true;
|
||||||
givenCommand = new CondSh<BattleAction *>(NULL);
|
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;
|
tacticianInterface = attackerInt;
|
||||||
else if(defenderInt && defenderInt->cb->battleGetTacticDist())
|
else if(defenderInt && defenderInt->cb->battleGetTacticDist())
|
||||||
tacticianInterface = defenderInt;
|
tacticianInterface = defenderInt;
|
||||||
@@ -453,9 +460,7 @@ CBattleInterface::~CBattleInterface()
|
|||||||
delete bigForceField[1];
|
delete bigForceField[1];
|
||||||
|
|
||||||
delete siegeH;
|
delete siegeH;
|
||||||
|
|
||||||
delete autofightingAI;
|
|
||||||
|
|
||||||
//TODO: play AI tracks if battle was during AI turn
|
//TODO: play AI tracks if battle was during AI turn
|
||||||
//if (!curInt->makingTurn)
|
//if (!curInt->makingTurn)
|
||||||
//CCS->musich->playMusicFromSet(CCS->musich->aiMusics, -1);
|
//CCS->musich->playMusicFromSet(CCS->musich->aiMusics, -1);
|
||||||
@@ -493,6 +498,12 @@ void CBattleInterface::setPrintMouseShadow(bool set)
|
|||||||
|
|
||||||
void CBattleInterface::activate()
|
void CBattleInterface::activate()
|
||||||
{
|
{
|
||||||
|
if(isAutoFightOn)
|
||||||
|
{
|
||||||
|
bAutofight->activate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CIntObject::activate();
|
CIntObject::activate();
|
||||||
bOptions->activate();
|
bOptions->activate();
|
||||||
bSurrender->activate();
|
bSurrender->activate();
|
||||||
@@ -1265,16 +1276,16 @@ void CBattleInterface::bAutofightf()
|
|||||||
if(spellDestSelectMode) //we are casting a spell
|
if(spellDestSelectMode) //we are casting a spell
|
||||||
return;
|
return;
|
||||||
|
|
||||||
static bool isAutoFightOn = false;
|
//Stop auto-fight mode
|
||||||
static unique_ptr<boost::thread> aiThread = nullptr;
|
|
||||||
|
|
||||||
if(isAutoFightOn)
|
if(isAutoFightOn)
|
||||||
{
|
{
|
||||||
assert(autofightingAI);
|
assert(autofightingAI);
|
||||||
isAutoFightOn = false;
|
isAutoFightOn = false;
|
||||||
|
logGlobal->traceStream() << "Stopping the autofight...";
|
||||||
|
aiThread->interrupt();
|
||||||
aiThread->join();
|
aiThread->join();
|
||||||
|
|
||||||
vstd::clear_pointer(autofightingAI);
|
autofightingAI = nullptr;
|
||||||
aiThread = nullptr;
|
aiThread = nullptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1284,18 +1295,7 @@ void CBattleInterface::bAutofightf()
|
|||||||
autofightingAI->init(curInt->cb);
|
autofightingAI->init(curInt->cb);
|
||||||
autofightingAI->battleStart(army1, army2, int3(0,0,0), attackingHeroInstance, defendingHeroInstance, curInt->cb->battleGetMySide());
|
autofightingAI->battleStart(army1, army2, int3(0,0,0), attackingHeroInstance, defendingHeroInstance, curInt->cb->battleGetMySide());
|
||||||
|
|
||||||
//Deactivate everything
|
requestAutofightingAIToTakeAction();
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1313,7 +1313,7 @@ void CBattleInterface::bSpellf()
|
|||||||
ESpellCastProblem::ESpellCastProblem spellCastProblem;
|
ESpellCastProblem::ESpellCastProblem spellCastProblem;
|
||||||
if (curInt->cb->battleCanCastSpell(&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);
|
GH.pushInt(spellWindow);
|
||||||
}
|
}
|
||||||
else if(spellCastProblem == ESpellCastProblem::MAGIC_IS_BLOCKED)
|
else if(spellCastProblem == ESpellCastProblem::MAGIC_IS_BLOCKED)
|
||||||
@@ -2057,7 +2057,7 @@ void CBattleInterface::activateStack()
|
|||||||
const CStack *s = activeStack;
|
const CStack *s = activeStack;
|
||||||
|
|
||||||
myTurn = true;
|
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;
|
curInt = attackerInt->playerID == s->owner ? attackerInt : defenderInt;
|
||||||
|
|
||||||
queue->update();
|
queue->update();
|
||||||
@@ -2096,6 +2096,9 @@ void CBattleInterface::activateStack()
|
|||||||
if(!pendingAnims.size() && !active)
|
if(!pendingAnims.size() && !active)
|
||||||
activate();
|
activate();
|
||||||
|
|
||||||
|
if(isAutoFightOn)
|
||||||
|
requestAutofightingAIToTakeAction();
|
||||||
|
|
||||||
GH.fakeMouseMove();
|
GH.fakeMouseMove();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3585,6 +3588,24 @@ InfoAboutHero CBattleInterface::enemyHero() const
|
|||||||
return ret;
|
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)
|
CBattleInterface::SiegeHelper::SiegeHelper(const CGTownInstance *siegeTown, const CBattleInterface * _owner)
|
||||||
: owner(_owner), town(siegeTown)
|
: owner(_owner), town(siegeTown)
|
||||||
{
|
{
|
||||||
|
@@ -140,7 +140,7 @@ private:
|
|||||||
double getAnimSpeedMultiplier() const; //returns multiplier for number of frames in a group
|
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'
|
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 tacticsMode;
|
||||||
bool stackCanCastSpell; //if true, active stack could possibly cats some target spell
|
bool stackCanCastSpell; //if true, active stack could possibly cats some target spell
|
||||||
bool creatureCasting; //if true, stack currently aims to cats a 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 selectedAction; //last action chosen (and saved) by player
|
||||||
PossibleActions illegalAction; //most likely action that can't be performed here
|
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 getPossibleActionsForStack (const CStack * stack); //called when stack gets its turn
|
||||||
void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled)
|
void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled)
|
||||||
@@ -198,16 +202,16 @@ private:
|
|||||||
friend class CBattleInterface;
|
friend class CBattleInterface;
|
||||||
} * siegeH;
|
} * 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
|
const CGHeroInstance * getActiveHero(); //returns hero that can currently cast a spell
|
||||||
public:
|
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>
|
std::list<std::pair<CBattleAnimation *, bool> > pendingAnims; //currently displayed animations <anim, initialized>
|
||||||
void addNewAnim(CBattleAnimation * anim); //adds new anim to pendingAnims
|
void addNewAnim(CBattleAnimation * anim); //adds new anim to pendingAnims
|
||||||
ui32 animIDhelper; //for giving IDs for animations
|
ui32 animIDhelper; //for giving IDs for animations
|
||||||
static CondSh<bool> animsAreDisplayed; //for waiting with the end of battle for end of anims
|
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
|
~CBattleInterface(); //d-tor
|
||||||
|
|
||||||
//std::vector<TimeInterested*> timeinterested; //animation handling
|
//std::vector<TimeInterested*> timeinterested; //animation handling
|
||||||
|
@@ -174,7 +174,7 @@ void CBattleHero::clickLeft(tribool down, bool previousState)
|
|||||||
}
|
}
|
||||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
|
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);
|
GH.pushInt(spellWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -483,7 +483,7 @@ void CBattleResultWindow::bExitf()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPlayerInterface * intTmp = owner->curInt;
|
auto intTmp = owner->curInt;
|
||||||
GH.popInts(2); //first - we; second - battle interface
|
GH.popInts(2); //first - we; second - battle interface
|
||||||
intTmp->showingDialog->setn(false);
|
intTmp->showingDialog->setn(false);
|
||||||
CCS->videoh->close();
|
CCS->videoh->close();
|
||||||
|
@@ -22,27 +22,33 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<typename rett>
|
template<typename rett>
|
||||||
rett * createAny(std::string dllname, std::string methodName)
|
shared_ptr<rett> createAny(std::string dllname, std::string methodName)
|
||||||
{
|
{
|
||||||
char temp[50];
|
typedef void(*TGetAIFun)(shared_ptr<rett>&);
|
||||||
rett * ret=NULL;
|
typedef void(*TGetNameFun)(char*);
|
||||||
rett*(*getAI)();
|
|
||||||
void(*getName)(char*);
|
char temp[150];
|
||||||
|
|
||||||
|
TGetAIFun getAI = nullptr;
|
||||||
|
TGetNameFun getName = nullptr;
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
HINSTANCE dll = LoadLibraryA(dllname.c_str());
|
HINSTANCE dll = LoadLibraryA(dllname.c_str());
|
||||||
if (dll)
|
if (dll)
|
||||||
{
|
{
|
||||||
getName = (void(*)(char*))GetProcAddress(dll,"GetAiName");
|
getName = (TGetNameFun)GetProcAddress(dll,"GetAiName");
|
||||||
getAI = (rett*(*)())GetProcAddress(dll,methodName.c_str());
|
getAI = (TGetAIFun)GetProcAddress(dll,methodName.c_str());
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void *dll = dlopen(dllname.c_str(), RTLD_LOCAL | RTLD_LAZY);
|
void *dll = dlopen(dllname.c_str(), RTLD_LOCAL | RTLD_LAZY);
|
||||||
if (dll)
|
if (dll)
|
||||||
{
|
{
|
||||||
getName = (void(*)(char*))dlsym(dll,"GetAiName");
|
getName = (TGetNameFun)dlsym(dll,"GetAiName");
|
||||||
getAI = (rett*(*)())dlsym(dll,methodName.c_str());
|
getAI = (TGetAIFun)dlsym(dll,methodName.c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
logGlobal->errorStream() << "Error: " << dlerror();
|
logGlobal->errorStream() << "Error: " << dlerror();
|
||||||
@@ -65,8 +71,9 @@ rett * createAny(std::string dllname, std::string methodName)
|
|||||||
|
|
||||||
getName(temp);
|
getName(temp);
|
||||||
logGlobal->infoStream() << "Loaded " << temp;
|
logGlobal->infoStream() << "Loaded " << temp;
|
||||||
ret = getAI();
|
|
||||||
|
|
||||||
|
shared_ptr<rett> ret;
|
||||||
|
getAI(ret);
|
||||||
if(!ret)
|
if(!ret)
|
||||||
logGlobal->errorStream() << "Cannot get AI!";
|
logGlobal->errorStream() << "Cannot get AI!";
|
||||||
|
|
||||||
@@ -74,26 +81,27 @@ rett * createAny(std::string dllname, std::string methodName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename rett>
|
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;
|
logGlobal->infoStream() << "Opening " << dllname;
|
||||||
std::string filename = VCMIDirs::get().libraryName(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;
|
ret->dllName = dllname;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGlobalAI * CDynLibHandler::getNewAI(std::string dllname)
|
shared_ptr<CGlobalAI> CDynLibHandler::getNewAI(std::string dllname)
|
||||||
{
|
{
|
||||||
return createAnyAI<CGlobalAI>(dllname, "GetNewAI");
|
return createAnyAI<CGlobalAI>(dllname, "GetNewAI");
|
||||||
}
|
}
|
||||||
|
|
||||||
CBattleGameInterface * CDynLibHandler::getNewBattleAI(std::string dllname )
|
shared_ptr<CBattleGameInterface> CDynLibHandler::getNewBattleAI(std::string dllname )
|
||||||
{
|
{
|
||||||
return createAnyAI<CBattleGameInterface>(dllname, "GetNewBattleAI");
|
return createAnyAI<CBattleGameInterface>(dllname, "GetNewBattleAI");
|
||||||
}
|
}
|
||||||
|
|
||||||
CScriptingModule * CDynLibHandler::getNewScriptingModule(std::string dllname)
|
shared_ptr<CScriptingModule> CDynLibHandler::getNewScriptingModule(std::string dllname)
|
||||||
{
|
{
|
||||||
return createAny<CScriptingModule>(dllname, "GetNewModule");
|
return createAny<CScriptingModule>(dllname, "GetNewModule");
|
||||||
}
|
}
|
||||||
@@ -187,7 +195,7 @@ void CAdventureAI::battleSpellCast(const BattleSpellCast *sc)
|
|||||||
void CAdventureAI::battleEnd(const BattleResult *br)
|
void CAdventureAI::battleEnd(const BattleResult *br)
|
||||||
{
|
{
|
||||||
battleAI->battleEnd(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)
|
void CAdventureAI::battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, bool tentHeal, si32 lifeDrainFrom)
|
||||||
|
@@ -96,9 +96,9 @@ public:
|
|||||||
class DLL_LINKAGE CDynLibHandler
|
class DLL_LINKAGE CDynLibHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static CGlobalAI * getNewAI(std::string dllname);
|
static shared_ptr<CGlobalAI> getNewAI(std::string dllname);
|
||||||
static CBattleGameInterface * getNewBattleAI(std::string dllname);
|
static shared_ptr<CBattleGameInterface> getNewBattleAI(std::string dllname);
|
||||||
static CScriptingModule * getNewScriptingModule(std::string dllname);
|
static shared_ptr<CScriptingModule> getNewScriptingModule(std::string dllname);
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE CGlobalAI : public CGameInterface // AI class (to derivate)
|
class DLL_LINKAGE CGlobalAI : public CGameInterface // AI class (to derivate)
|
||||||
@@ -114,7 +114,7 @@ class DLL_LINKAGE CAdventureAI : public CGlobalAI
|
|||||||
public:
|
public:
|
||||||
CAdventureAI() : battleAI(NULL), cbc(NULL) {};
|
CAdventureAI() : battleAI(NULL), cbc(NULL) {};
|
||||||
|
|
||||||
CBattleGameInterface *battleAI;
|
shared_ptr<CBattleGameInterface> battleAI;
|
||||||
shared_ptr<CBattleCallback> cbc;
|
shared_ptr<CBattleCallback> cbc;
|
||||||
|
|
||||||
virtual std::string getBattleAIName() const = 0; //has to return name of the battle AI to be used
|
virtual std::string getBattleAIName() const = 0; //has to return name of the battle AI to be used
|
||||||
|
@@ -28,7 +28,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
|
|||||||
strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
|
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>();
|
||||||
}
|
}
|
Reference in New Issue
Block a user