mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-28 08:48:48 +02:00
* fixed crash related to cammander's SPELL_AFTER_ATTACK spell id not initialized properly (text id was resolved on copy of bonus)
* fixed duels, added no-GUI mode for automatic AI testing * minor things
This commit is contained in:
parent
30fb552fb4
commit
6a88604937
@ -354,15 +354,16 @@ BattleAction CBattleAI::activeStack( const CStack * stack )
|
||||
if(cb->battleCanCastSpell())
|
||||
attemptCastingSpell();
|
||||
|
||||
if(auto action = considerFleeingOrSurrendering())
|
||||
return *action;
|
||||
|
||||
if(cb->battleGetStacks(CBattleInfoEssentials::ONLY_ENEMY).empty())
|
||||
{
|
||||
//We apparently won battle by casting spell, return defend... (accessing cb may cause trouble)
|
||||
return BattleAction::makeDefend(stack);
|
||||
}
|
||||
|
||||
ThreatMap threatsToUs(stack);
|
||||
PotentialTargets targets(stack);
|
||||
|
||||
if(targets.possibleAttacks.size())
|
||||
{
|
||||
auto hlp = targets.bestAction();
|
||||
@ -375,6 +376,7 @@ BattleAction CBattleAI::activeStack( const CStack * stack )
|
||||
{
|
||||
if(stack->waited())
|
||||
{
|
||||
ThreatMap threatsToUs(stack);
|
||||
auto dists = cbc->battleGetDistances(stack);
|
||||
const EnemyInfo &ei= *range::min_element(targets.unreachableEnemies, boost::bind(isCloser, _1, _2, boost::ref(dists)));
|
||||
if(distToNearestNeighbour(ei.s->position, dists) < GameConstants::BFIELD_SIZE)
|
||||
@ -749,3 +751,16 @@ std::vector<BattleHex> CBattleAI::getTargetsToConsider( const CSpell *spell ) co
|
||||
return cbc->battleGetPossibleTargets(playerID, spell);
|
||||
}
|
||||
}
|
||||
|
||||
boost::optional<BattleAction> CBattleAI::considerFleeingOrSurrendering()
|
||||
{
|
||||
if(cb->battleCanSurrender(playerID))
|
||||
{
|
||||
|
||||
}
|
||||
if(cb->battleCanFlee())
|
||||
{
|
||||
|
||||
}
|
||||
return boost::none;
|
||||
}
|
||||
|
@ -42,6 +42,8 @@ public:
|
||||
BattleAction goTowards(const CStack * stack, BattleHex hex );
|
||||
BattleAction useCatapult(const CStack * stack);
|
||||
|
||||
boost::optional<BattleAction> considerFleeingOrSurrendering();
|
||||
|
||||
void attemptCastingSpell();
|
||||
std::vector<BattleHex> getTargetsToConsider(const CSpell *spell) const;
|
||||
};
|
||||
|
@ -239,8 +239,8 @@ void CCreatureWindow::init(const CStackInstance *Stack, const CBonusSystemNode *
|
||||
else
|
||||
{
|
||||
selectableSkill->pos = Rect (95, 256, 55, 55); //TODO: scroll
|
||||
Bonus b = CGI->creh->skillRequirements[option-100].first;
|
||||
bonusItems.push_back (new CBonusItem (genRect(0, 0, 251, 57), stack->bonusToString(&b, false), stack->bonusToString(&b, true), stack->bonusToGraphics(&b)));
|
||||
const Bonus *b = CGI->creh->skillRequirements[option-100].first;
|
||||
bonusItems.push_back (new CBonusItem (genRect(0, 0, 251, 57), stack->bonusToString(b, false), stack->bonusToString(b, true), stack->bonusToGraphics(b)));
|
||||
selectableBonuses.push_back (selectableSkill); //insert these before other bonuses
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,7 @@
|
||||
#endif
|
||||
#include "../lib/CDefObjInfoHandler.h"
|
||||
#include "../lib/UnlockGuard.h"
|
||||
#include "CMT.h"
|
||||
|
||||
#if __MINGW32__
|
||||
#undef main
|
||||
@ -76,6 +77,7 @@ static boost::thread *mainGUIThread;
|
||||
std::queue<SDL_Event> events;
|
||||
boost::mutex eventsM;
|
||||
|
||||
bool gNoGUI = false;
|
||||
static bool gOnlyAI = false;
|
||||
//static bool setResolution = false; //set by event handling thread after resolution is adjusted
|
||||
|
||||
@ -146,6 +148,8 @@ void init()
|
||||
logGlobal->infoStream()<<"Initializing VCMI_Lib: "<<tmh.getDiff();
|
||||
|
||||
pomtime.getDiff();
|
||||
if(!gNoGUI)
|
||||
{
|
||||
CCS->curh = new CCursorHandler;
|
||||
graphics = new Graphics(); // should be before curh->init()
|
||||
|
||||
@ -161,6 +165,7 @@ void init()
|
||||
CMessage::init();
|
||||
logGlobal->infoStream()<<"Message handler: "<<tmh.getDiff();
|
||||
}
|
||||
}
|
||||
|
||||
static void prog_version(void)
|
||||
{
|
||||
@ -219,7 +224,8 @@ int main(int argc, char** argv)
|
||||
("version,v", "display version information and exit")
|
||||
("battle,b", po::value<std::string>(), "runs game in duel mode (battle-only")
|
||||
("start", po::value<std::string>(), "starts game from saved StartInfo file")
|
||||
("onlyAI", "runs without GUI, all players will be default AI")
|
||||
("onlyAI", "runs without human player, all players will be default AI")
|
||||
("noGUI", "runs without GUI, implies --onlyAI")
|
||||
("oneGoodAI", "puts one default AI and the rest will be EmptyAI")
|
||||
("autoSkip", "automatically skip turns in GUI")
|
||||
("disable-video", "disable video player")
|
||||
@ -249,6 +255,11 @@ int main(int argc, char** argv)
|
||||
prog_version();
|
||||
return 0;
|
||||
}
|
||||
if(vm.count("noGUI"))
|
||||
{
|
||||
gNoGUI = true;
|
||||
vm["onlyAI"];
|
||||
}
|
||||
|
||||
//Set environment vars to make window centered. Sometimes work, sometimes not. :/
|
||||
putenv((char*)"SDL_VIDEO_WINDOW_POS");
|
||||
@ -304,15 +315,6 @@ int main(int argc, char** argv)
|
||||
|
||||
srand ( time(NULL) );
|
||||
|
||||
CCS = new CClientState;
|
||||
CGI = new CGameInfo; //contains all global informations about game (texts, lodHandlers, map handler etc.)
|
||||
|
||||
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO))
|
||||
{
|
||||
logGlobal->errorStream()<<"Something was wrong: "<< SDL_GetError();
|
||||
exit(-1);
|
||||
}
|
||||
atexit(SDL_Quit);
|
||||
|
||||
const JsonNode& video = settings["video"];
|
||||
const JsonNode& res = video["screenRes"];
|
||||
@ -328,15 +330,26 @@ int main(int argc, char** argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if(!gNoGUI)
|
||||
{
|
||||
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO))
|
||||
{
|
||||
logGlobal->errorStream()<<"Something was wrong: "<< SDL_GetError();
|
||||
exit(-1);
|
||||
}
|
||||
atexit(SDL_Quit);
|
||||
setScreenRes(res["width"].Float(), res["height"].Float(), video["bitsPerPixel"].Float(), video["fullscreen"].Bool());
|
||||
|
||||
logGlobal->infoStream() <<"\tInitializing screen: "<<pomtime.getDiff();
|
||||
}
|
||||
|
||||
|
||||
CCS = new CClientState;
|
||||
CGI = new CGameInfo; //contains all global informations about game (texts, lodHandlers, map handler etc.)
|
||||
// Initialize video
|
||||
#if DISABLE_VIDEO
|
||||
CCS->videoh = new CEmptyVideoPlayer;
|
||||
#else
|
||||
if (!vm.count("disable-video"))
|
||||
if (!gNoGUI && !vm.count("disable-video"))
|
||||
CCS->videoh = new CVideoPlayer;
|
||||
else
|
||||
CCS->videoh = new CEmptyVideoPlayer;
|
||||
@ -344,13 +357,18 @@ int main(int argc, char** argv)
|
||||
|
||||
logGlobal->infoStream()<<"\tInitializing video: "<<pomtime.getDiff();
|
||||
|
||||
|
||||
|
||||
//we can properly play intro only in the main thread, so we have to move loading to the separate thread
|
||||
boost::thread loading(init);
|
||||
|
||||
if(!gNoGUI )
|
||||
{
|
||||
if(!vm.count("battle") && !vm.count("nointro"))
|
||||
playIntro();
|
||||
|
||||
SDL_FillRect(screen,NULL,0);
|
||||
}
|
||||
|
||||
CSDL_Ext::update(screen);
|
||||
loading.join();
|
||||
logGlobal->infoStream()<<"Initialization of VCMI (together): "<<total.getDiff();
|
||||
@ -387,8 +405,17 @@ int main(int argc, char** argv)
|
||||
si->playerInfos[PlayerColor(1)].color = PlayerColor(1);
|
||||
startGame(si);
|
||||
}
|
||||
|
||||
if(!gNoGUI)
|
||||
{
|
||||
mainGUIThread = new boost::thread(&CGuiHandler::run, boost::ref(GH));
|
||||
listenForEvents();
|
||||
}
|
||||
else
|
||||
{
|
||||
while(true)
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -822,20 +849,7 @@ static void listenForEvents()
|
||||
if (ret == 0 || (ev.type==SDL_QUIT) ||
|
||||
(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4 && (ev.key.keysym.mod & KMOD_ALT)))
|
||||
{
|
||||
if (client)
|
||||
client->endGame();
|
||||
if (mainGUIThread)
|
||||
{
|
||||
GH.terminate = true;
|
||||
mainGUIThread->join();
|
||||
delete mainGUIThread;
|
||||
mainGUIThread = NULL;
|
||||
}
|
||||
delete console;
|
||||
console = NULL;
|
||||
SDL_Delay(750);
|
||||
SDL_Quit();
|
||||
std::cout << "Ending...";
|
||||
handleQuit();
|
||||
break;
|
||||
}
|
||||
else if(LOCPLINT && ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4)
|
||||
@ -929,3 +943,24 @@ void startGame(StartInfo * options, CConnection *serv/* = NULL*/)
|
||||
|
||||
client->connectionHandler = new boost::thread(&CClient::run, client);
|
||||
}
|
||||
|
||||
void handleQuit()
|
||||
{
|
||||
if (client)
|
||||
client->endGame();
|
||||
if (mainGUIThread)
|
||||
{
|
||||
GH.terminate = true;
|
||||
mainGUIThread->join();
|
||||
delete mainGUIThread;
|
||||
mainGUIThread = NULL;
|
||||
}
|
||||
delete console;
|
||||
console = NULL;
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(750));
|
||||
if(!gNoGUI)
|
||||
SDL_Quit();
|
||||
|
||||
std::cout << "Ending...";
|
||||
exit(0);
|
||||
}
|
||||
|
@ -3,3 +3,7 @@
|
||||
extern SDL_Surface *screen; // main screen surface
|
||||
extern SDL_Surface *screen2; // and hlp surface (used to store not-active interfaces layer)
|
||||
extern SDL_Surface *screenBuf; // points to screen (if only advmapint is present) or screen2 (else) - should be used when updating controls which are not regularly redrawed
|
||||
|
||||
extern bool gNoGUI; //if true there is no client window and game is silently played between AIs
|
||||
|
||||
void handleQuit();
|
@ -34,6 +34,7 @@
|
||||
#include "../lib/CScriptingModule.h"
|
||||
#include "../lib/RegisterTypes.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "CMT.h"
|
||||
|
||||
extern std::string NAME;
|
||||
namespace intpr = boost::interprocess;
|
||||
@ -418,9 +419,11 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
}
|
||||
|
||||
if(si->mode == StartInfo::DUEL)
|
||||
{
|
||||
if(!gNoGUI)
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||
CPlayerInterface *p = new CPlayerInterface(PlayerColor::NEUTRAL); //TODO: check if neutral really works -- was -1, but CPlayerInterface seems to cooperate with this value not too well
|
||||
CPlayerInterface *p = new CPlayerInterface(PlayerColor::NEUTRAL);
|
||||
p->observerInDuelMode = true;
|
||||
battleints[PlayerColor::UNFLAGGABLE] = playerint[PlayerColor::UNFLAGGABLE] = p;
|
||||
privilagedBattleEventReceivers.push_back(p);
|
||||
@ -428,6 +431,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
auto cb = make_shared<CCallback>(gs, boost::optional<PlayerColor>(), this);
|
||||
battleCallbacks[PlayerColor::NEUTRAL] = callbacks[PlayerColor::NEUTRAL] = cb;
|
||||
p->init(cb.get());
|
||||
}
|
||||
battleStarted(gs->curB);
|
||||
}
|
||||
else
|
||||
@ -616,7 +620,7 @@ void CClient::battleStarted(const BattleInfo * info)
|
||||
else
|
||||
def = NULL;
|
||||
|
||||
if(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],
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "../lib/BattleState.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "CMT.h"
|
||||
|
||||
//macros to avoid code duplication - calls given method with given arguments if interface for specific player is present
|
||||
//awaiting variadic templates...
|
||||
@ -705,9 +706,7 @@ void BattleResultsApplied::applyCl( CClient *cl )
|
||||
INTERFACE_CALL_IF_PRESENT(PlayerColor::UNFLAGGABLE, battleResultsApplied);
|
||||
if(GS(cl)->initialOpts->mode == StartInfo::DUEL)
|
||||
{
|
||||
cl->terminate = true;
|
||||
CloseServer cs;
|
||||
*cl->serv << &cs;
|
||||
handleQuit();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,8 +204,8 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
|
||||
bOptions = new CAdventureMapButton (CGI->generaltexth->zelp[381].first, CGI->generaltexth->zelp[381].second, boost::bind(&CBattleInterface::bOptionsf,this), 3, 561, "icm003.def", SDLK_o);
|
||||
bSurrender = new CAdventureMapButton (CGI->generaltexth->zelp[379].first, CGI->generaltexth->zelp[379].second, boost::bind(&CBattleInterface::bSurrenderf,this), 54, 561, "icm001.def", SDLK_s);
|
||||
bFlee = new CAdventureMapButton (CGI->generaltexth->zelp[380].first, CGI->generaltexth->zelp[380].second, boost::bind(&CBattleInterface::bFleef,this), 105, 561, "icm002.def", SDLK_r);
|
||||
bFlee->block(!curInt->cb->battleCanFlee());
|
||||
bSurrender->block(curInt->cb->battleGetSurrenderCost() < 0);
|
||||
bFlee->block(!curInt->cb->getMyColor() || !curInt->cb->battleCanFlee());
|
||||
bSurrender->block(!curInt->cb->getMyColor() || curInt->cb->battleGetSurrenderCost() < 0);
|
||||
bAutofight = new CAdventureMapButton (CGI->generaltexth->zelp[382].first, CGI->generaltexth->zelp[382].second, boost::bind(&CBattleInterface::bAutofightf,this), 157, 561, "icm004.def", SDLK_a);
|
||||
bSpell = new CAdventureMapButton (CGI->generaltexth->zelp[385].first, CGI->generaltexth->zelp[385].second, boost::bind(&CBattleInterface::bSpellf,this), 645, 561, "icm005.def", SDLK_c);
|
||||
bSpell->block(true);
|
||||
|
@ -942,6 +942,11 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo &info) c
|
||||
multBonus *= 0.5;
|
||||
}
|
||||
|
||||
|
||||
// TODO attack on petrified unit 50%
|
||||
// psychic elementals versus mind immune units 50%
|
||||
// blinded unit retaliates
|
||||
|
||||
minDmg *= additiveBonus * multBonus;
|
||||
maxDmg *= additiveBonus * multBonus;
|
||||
|
||||
@ -2268,7 +2273,10 @@ TStacks CPlayerBattleCallback::battleGetStacks(EStackOwnership whose /*= MINE_AN
|
||||
{
|
||||
TStacks ret;
|
||||
RETURN_IF_NOT_BATTLE(ret);
|
||||
if(whose != MINE_AND_ENEMY)
|
||||
{
|
||||
ASSERT_IF_CALLED_WITH_PLAYER
|
||||
}
|
||||
vstd::copy_if(battleGetAllStacks(), std::back_inserter(ret), [=](const CStack *s) -> bool
|
||||
{
|
||||
const bool ownerMatches = (whose == MINE_AND_ENEMY)
|
||||
|
@ -128,7 +128,7 @@ CBonusTypeHandler::~CBonusTypeHandler()
|
||||
//dtor
|
||||
}
|
||||
|
||||
std::string CBonusTypeHandler::bonusToString(Bonus *bonus, const IBonusBearer *bearer, bool description) const
|
||||
std::string CBonusTypeHandler::bonusToString(const Bonus *bonus, const IBonusBearer *bearer, bool description) const
|
||||
{
|
||||
auto getValue = [=](const std::string &name) -> std::string
|
||||
{
|
||||
@ -171,7 +171,7 @@ std::string CBonusTypeHandler::bonusToString(Bonus *bonus, const IBonusBearer *b
|
||||
return text;
|
||||
}
|
||||
|
||||
std::string CBonusTypeHandler::bonusToGraphics(Bonus* bonus) const
|
||||
std::string CBonusTypeHandler::bonusToGraphics(const Bonus* bonus) const
|
||||
{
|
||||
std::string fileName;
|
||||
bool fullPath = false;
|
||||
|
@ -75,8 +75,8 @@ public:
|
||||
CBonusTypeHandler();
|
||||
virtual ~CBonusTypeHandler();
|
||||
|
||||
std::string bonusToString(Bonus *bonus, const IBonusBearer *bearer, bool description) const override;
|
||||
std::string bonusToGraphics(Bonus *bonus) const override;
|
||||
std::string bonusToString(const Bonus *bonus, const IBonusBearer *bearer, bool description) const override;
|
||||
std::string bonusToGraphics(const Bonus *bonus) const override;
|
||||
|
||||
void load();
|
||||
void load(const JsonNode& config);
|
||||
|
@ -212,8 +212,8 @@ void CCreatureHandler::loadCommanders()
|
||||
|
||||
BOOST_FOREACH (auto ability, config["abilityRequirements"].Vector())
|
||||
{
|
||||
std::pair <Bonus, std::pair <ui8, ui8> > a;
|
||||
a.first = *JsonUtils::parseBonus (ability["ability"].Vector());
|
||||
std::pair <Bonus*, std::pair <ui8, ui8> > a;
|
||||
a.first = JsonUtils::parseBonus (ability["ability"].Vector());
|
||||
a.second.first = ability["skills"].Vector()[0].Float();
|
||||
a.second.second = ability["skills"].Vector()[1].Float();
|
||||
skillRequirements.push_back (a);
|
||||
|
@ -181,7 +181,7 @@ public:
|
||||
//Commanders
|
||||
BonusList commanderLevelPremy; //bonus values added with each level-up
|
||||
std::vector< std::vector <ui8> > skillLevels; //how much of a bonus will be given to commander with every level. SPELL_POWER also gives CASTS and RESISTANCE
|
||||
std::vector <std::pair <Bonus, std::pair <ui8, ui8> > > skillRequirements; // first - Bonus, second - which two skills are needed to use it
|
||||
std::vector <std::pair <Bonus*, std::pair <ui8, ui8> > > skillRequirements; // first - Bonus, second - which two skills are needed to use it
|
||||
|
||||
void deserializationFix();
|
||||
CreatureID pickRandomMonster(const boost::function<int()> &randGen = 0, int tier = -1) const; //tier <1 - CREATURES_PER_TOWN> or -1 for any
|
||||
|
@ -565,7 +565,7 @@ void CStackInstance::setType(const CCreature *c)
|
||||
if(type)
|
||||
attachTo(const_cast<CCreature*>(type));
|
||||
}
|
||||
std::string CStackInstance::bonusToString(Bonus *bonus, bool description) const
|
||||
std::string CStackInstance::bonusToString(const Bonus *bonus, bool description) const
|
||||
{
|
||||
if(Bonus::MAGIC_RESISTANCE == bonus->type)
|
||||
{
|
||||
@ -578,7 +578,7 @@ std::string CStackInstance::bonusToString(Bonus *bonus, bool description) const
|
||||
|
||||
}
|
||||
|
||||
std::string CStackInstance::bonusToGraphics(Bonus *bonus) const
|
||||
std::string CStackInstance::bonusToGraphics(const Bonus *bonus) const
|
||||
{
|
||||
return VLC->getBth()->bonusToGraphics(bonus);
|
||||
}
|
||||
|
@ -56,8 +56,8 @@ public:
|
||||
}
|
||||
|
||||
//overrides CBonusSystemNode
|
||||
std::string bonusToString(Bonus *bonus, bool description) const override; // how would bonus description look for this particular type of node
|
||||
std::string bonusToGraphics(Bonus *bonus) const; //file name of graphics from StackSkills , in future possibly others
|
||||
std::string bonusToString(const Bonus *bonus, bool description) const override; // how would bonus description look for this particular type of node
|
||||
std::string bonusToGraphics(const Bonus *bonus) const; //file name of graphics from StackSkills , in future possibly others
|
||||
|
||||
virtual ui64 getPower() const;
|
||||
int getQuantityID() const;
|
||||
|
@ -619,7 +619,7 @@ public:
|
||||
//bool isLimitedOnUs(Bonus *b) const; //if bonus should be removed from list acquired from this node
|
||||
|
||||
void popBonuses(const CSelector &s);
|
||||
virtual std::string bonusToString(Bonus *bonus, bool description) const {return "";}; //description or bonus name
|
||||
virtual std::string bonusToString(const Bonus *bonus, bool description) const {return "";}; //description or bonus name
|
||||
virtual std::string nodeName() const;
|
||||
|
||||
void deserializationFix();
|
||||
|
@ -20,6 +20,6 @@ class IBonusTypeHandler
|
||||
public:
|
||||
virtual ~IBonusTypeHandler(){};
|
||||
|
||||
virtual std::string bonusToString(Bonus *bonus, const IBonusBearer *bearer, bool description) const = 0;
|
||||
virtual std::string bonusToGraphics(Bonus *bonus) const = 0;
|
||||
virtual std::string bonusToString(const Bonus *bonus, const IBonusBearer *bearer, bool description) const = 0;
|
||||
virtual std::string bonusToGraphics(const Bonus *bonus) const = 0;
|
||||
};
|
||||
|
@ -293,7 +293,7 @@ void CGameHandler::levelUpCommander (const CCommanderInstance * c, int skill)
|
||||
else if (skill >= 100)
|
||||
{
|
||||
scp.which = SetCommanderProperty::SPECIAL_SKILL;
|
||||
scp.accumulatedBonus = VLC->creh->skillRequirements[skill-100].first;
|
||||
scp.accumulatedBonus = *VLC->creh->skillRequirements[skill-100].first;
|
||||
scp.additionalInfo = skill; //unnormalized
|
||||
sendAndApply (&scp);
|
||||
}
|
||||
@ -435,17 +435,22 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
const auto battleQuery = findBattleQuery();
|
||||
auto battleQuery = findBattleQuery();
|
||||
if(!battleQuery)
|
||||
{
|
||||
logGlobal->errorStream() << "Cannot find battle query!";
|
||||
if(gs->initialOpts->mode == StartInfo::DUEL)
|
||||
{
|
||||
battleQuery = make_shared<CBattleQuery>(gs->curB);
|
||||
}
|
||||
}
|
||||
if(battleQuery != queries.topQuery(gs->curB->sides[0]))
|
||||
complain("Player " + boost::lexical_cast<std::string>(gs->curB->sides[0]) + " although in battle has no battle query at the top!");
|
||||
|
||||
battleQuery->result = *battleResult.data;
|
||||
|
||||
//Check how many battle queries were created (number of players blocked by battle)
|
||||
const int queriedPlayers = boost::count(queries.allQueries(), battleQuery);
|
||||
|
||||
const int queriedPlayers = battleQuery ? boost::count(queries.allQueries(), battleQuery) : 0;
|
||||
finishingBattle = make_unique<FinishingBattleHelper>(battleQuery, gs->initialOpts->mode == StartInfo::DUEL, queriedPlayers);
|
||||
|
||||
|
||||
@ -592,7 +597,13 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
|
||||
}
|
||||
|
||||
if(finishingBattle->duel)
|
||||
{
|
||||
BattleResultsApplied resultsApplied;
|
||||
resultsApplied.player1 = finishingBattle->victor;
|
||||
resultsApplied.player2 = finishingBattle->loser;
|
||||
sendAndApply(&resultsApplied);
|
||||
return;
|
||||
}
|
||||
|
||||
cab1.takeFromArmy(this); cab2.takeFromArmy(this); //take casualties after battle is deleted
|
||||
|
||||
@ -826,6 +837,12 @@ void CGameHandler::handleConnection(std::set<PlayerColor> players, CConnection &
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(*c.rmx);
|
||||
c >> player >> requestID >> pack; //get the package
|
||||
|
||||
if(!pack)
|
||||
{
|
||||
logGlobal ->errorStream() << boost::format("Received a null package marked as request %d from player %d") % requestID % player;
|
||||
}
|
||||
|
||||
packType = typeList.getTypeID(pack); //get the id of type
|
||||
|
||||
logGlobal->traceStream() << boost::format("Received client message (request %d by player %d) of type with ID=%d (%s).\n")
|
||||
@ -1427,6 +1444,8 @@ void CGameHandler::newTurn()
|
||||
}
|
||||
void CGameHandler::run(bool resume)
|
||||
{
|
||||
LOG_TRACE_PARAMS(logGlobal, "resume=%d", resume);
|
||||
|
||||
using namespace boost::posix_time;
|
||||
BOOST_FOREACH(CConnection *cc, conns)
|
||||
{
|
||||
@ -1468,6 +1487,12 @@ void CGameHandler::run(bool resume)
|
||||
if(gs->scenarioOps->mode == StartInfo::DUEL)
|
||||
{
|
||||
runBattle();
|
||||
end2 = true;
|
||||
|
||||
|
||||
while(conns.size() && (*conns.begin())->isOpen())
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(5)); //give time client to close socket
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -265,7 +265,7 @@ public:
|
||||
FinishingBattleHelper();
|
||||
FinishingBattleHelper(shared_ptr<const CBattleQuery> Query, bool Duel, int RemainingBattleQueriesCount);
|
||||
|
||||
shared_ptr<const CBattleQuery> query;
|
||||
//shared_ptr<const CBattleQuery> query;
|
||||
const CGHeroInstance *winnerHero, *loserHero;
|
||||
PlayerColor victor, loser;
|
||||
bool duel;
|
||||
@ -274,7 +274,7 @@ public:
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & query & winnerHero & loserHero & victor & loser & duel & remainingBattleQueriesCount;
|
||||
h & /*query & */winnerHero & loserHero & victor & loser & duel & remainingBattleQueriesCount;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -179,6 +179,10 @@ QueryPtr Queries::topQuery(PlayerColor player)
|
||||
|
||||
void Queries::popIfTop(QueryPtr query)
|
||||
{
|
||||
LOG_TRACE_PARAMS(logGlobal, "query='%d'", query);
|
||||
if(!query)
|
||||
logGlobal->errorStream() << "The query is nullptr! Ignoring.";
|
||||
|
||||
popIfTop(*query);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user