1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-20 20:23:03 +02:00

* fixed project files for RD configuration

* fixed crash when creature is casting Hypnosis (ie. exped Vampire Lords)
* fixed crash when creature is casting Cure before attack (ie. exped Unicorns)
* fixed crash when creature is summoning elemental (TODO fix it)
* fixed crash when doing a bonus system operation with a hero liberated from prison (ie. entering town or battle)
* fixed deadlock when StupidAI tried to assault the turrets
* fixed never ending siege when StupidAI has to use catapult (no more deadlocks on AI-AI siege)
* fixed deadlock when a hero received a level during another player's turn (ie. when he successfully defended)
* AI can win the game by defeating all enemies if there is a specific victory condition applying only to human players
* added options to help testing adventure map AI (--onlyAI, --autoSkip and --oneGoodAI).
* many minor changes
This commit is contained in:
Michał W. Urbańczyk 2012-01-03 01:55:26 +00:00
parent 91c0ce33f4
commit 046e54563c
35 changed files with 305 additions and 107 deletions

View File

@ -1353,14 +1353,6 @@ void CGeniusAI::battleSpellCast(const BattleSpellCast *sc)
// } // }
/**
*
*/
void CGeniusAI::battleStackAttacking(int ID, int dest)
{
DbgBox("\t\t\tCGeniusAI::battleStackAttacking");
}
/** /**
* *
@ -1386,9 +1378,11 @@ BattleAction CGeniusAI::activeStack(const CStack * stack)
message += ")"; message += ")";
DbgBox(message.c_str()); DbgBox(message.c_str());
BattleAction bact = m_battleLogic->MakeDecision(stack->ID); return BattleAction::makeDefend(stack);
assert(m_cb->battleGetStackByID(bact.stackNumber)); //
return bact; // BattleAction bact = m_battleLogic->MakeDecision(stack->ID);
// assert(m_cb->battleGetStackByID(bact.stackNumber));
// return bact;
} }

View File

@ -207,7 +207,6 @@ public:
//virtual void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles); //called when battlefield is prepared, prior the battle beginning //virtual void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles); //called when battlefield is prepared, prior the battle beginning
// //
//virtual void battleStackMoved(int ID, int dest, bool startMoving, bool endMoving); //virtual void battleStackMoved(int ID, int dest, bool startMoving, bool endMoving);
virtual void battleStackAttacking(int ID, int dest);
virtual void battleStackIsAttacked(int ID, int dmg, int killed, int IDby, bool byShooting); virtual void battleStackIsAttacked(int ID, int dmg, int killed, int IDby, bool byShooting);
virtual BattleAction activeStack(const CStack * stack); virtual BattleAction activeStack(const CStack * stack);
void battleResultsApplied(); void battleResultsApplied();

View File

@ -102,6 +102,19 @@ BattleAction CStupidAI::activeStack( const CStack * stack )
std::vector<int> dists = cb->battleGetDistances(stack); std::vector<int> dists = cb->battleGetDistances(stack);
std::vector<EnemyInfo> enemiesShootable, enemiesReachable, enemiesUnreachable; std::vector<EnemyInfo> enemiesShootable, enemiesReachable, enemiesUnreachable;
if(stack->type->idNumber == 145) //catapult
{
BattleAction attack;
static const int wallHexes[] = {50, 183, 182, 130, 62, 29, 12, 95};
attack.destinationTile = wallHexes[ rand()%ARRAY_COUNT(wallHexes) ];
attack.actionType = BattleAction::CATAPULT;
attack.additionalInfo = 0;
attack.side = side;
attack.stackNumber = stack->ID;
return attack;
}
BOOST_FOREACH(const CStack *s, cb->battleGetStacks(CBattleCallback::ONLY_ENEMY)) BOOST_FOREACH(const CStack *s, cb->battleGetStacks(CBattleCallback::ONLY_ENEMY))
{ {
if(cb->battleCanShoot(stack, s->position)) if(cb->battleCanShoot(stack, s->position))
@ -125,7 +138,7 @@ BattleAction CStupidAI::activeStack( const CStack * stack )
} }
} }
if(!vstd::contains(enemiesReachable, s)) if(!vstd::contains(enemiesReachable, s) && s->position.isValid())
enemiesUnreachable.push_back(s); enemiesUnreachable.push_back(s);
} }
} }

View File

@ -107,7 +107,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -124,7 +124,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -143,7 +143,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -160,6 +160,9 @@
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">StdInc.h</PrecompiledHeaderFile> <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">StdInc.h</PrecompiledHeaderFile>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='RD|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='RD|x64'">Create</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="StupidAI.cpp" /> <ClCompile Include="StupidAI.cpp" />
</ItemGroup> </ItemGroup>

View File

@ -58,9 +58,7 @@ void CCallback::selectionMade(int selection, int asker)
{ {
QueryReply pack(asker,selection); QueryReply pack(asker,selection);
pack.player = player; pack.player = player;
cl->serv->sendPackToServer(pack, player);
boost::unique_lock<boost::mutex> lock(*cl->serv->wmx);
*cl->serv << &pack;
} }
void CCallback::recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount, si32 level/*=-1*/) void CCallback::recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount, si32 level/*=-1*/)
{ {
@ -192,7 +190,7 @@ void CBattleCallback::sendRequest(const CPack* request)
if(waitTillRealize) if(waitTillRealize)
cl->waitingRequest.set(typeList.getTypeID(request)); cl->waitingRequest.set(typeList.getTypeID(request));
cl->serv->sendPack(*request); cl->serv->sendPackToServer(*request, player);
if(waitTillRealize) if(waitTillRealize)
{ {

View File

@ -172,7 +172,8 @@ void config::CConfigHandler::init()
const JsonNode config(GameConstants::DATA_DIR + "/config/resolutions.json"); const JsonNode config(GameConstants::DATA_DIR + "/config/resolutions.json");
const JsonVector &guisettings_vec = config["GUISettings"].Vector(); const JsonVector &guisettings_vec = config["GUISettings"].Vector();
BOOST_FOREACH(const JsonNode &g, guisettings_vec) { BOOST_FOREACH(const JsonNode &g, guisettings_vec)
{
std::pair<int,int> curRes(g["resolution"]["x"].Float(), g["resolution"]["y"].Float()); std::pair<int,int> curRes(g["resolution"]["x"].Float(), g["resolution"]["y"].Float());
GUIOptions *current = &conf.guiOptions[curRes]; GUIOptions *current = &conf.guiOptions[curRes];
@ -249,6 +250,7 @@ void config::CConfigHandler::init()
cc.screenx = cc.resx; cc.screenx = cc.resx;
cc.screeny = cc.resy; cc.screeny = cc.resy;
} }
cc.autoSkip = false;
cc.oneGoodAI = false;
SetResolution(cc.resx, cc.resy); SetResolution(cc.resx, cc.resy);
} }

View File

@ -27,6 +27,7 @@ namespace config
defaultPlayerAI, defaultBattleAI; //dll names defaultPlayerAI, defaultBattleAI; //dll names
bool showFPS; //show/hide FPS counter bool showFPS; //show/hide FPS counter
bool classicCreatureWindow; bool classicCreatureWindow;
bool autoSkip, oneGoodAI; //for AI testing purposes
}; };
struct ButtonInfo struct ButtonInfo

View File

@ -93,6 +93,20 @@ void startGame(StartInfo * options, CConnection *serv = NULL);
#include <getopt.h> #include <getopt.h>
#endif #endif
void startGameFromFile(const std::string &fname)
{
if(fname.size() && boost::filesystem::exists(fname))
{
StartInfo si;
CLoadFile out(fname);
out >> si;
while(GH.topInt())
GH.popIntTotally(GH.topInt());
startGame(&si);
}
}
void init() void init()
{ {
CStopWatch tmh, pomtime; CStopWatch tmh, pomtime;
@ -164,16 +178,17 @@ static void prog_version(void)
printf(" binary directory: %s\n", GameConstants::BIN_DIR.c_str()); printf(" binary directory: %s\n", GameConstants::BIN_DIR.c_str());
} }
static void prog_help(const char *progname) static void prog_help(const po::options_description &opts)
{ {
printf("%s - A Heroes of Might and Magic 3 clone\n", GameConstants::VCMI_VERSION.c_str()); printf("%s - A Heroes of Might and Magic 3 clone\n", GameConstants::VCMI_VERSION.c_str());
printf("Copyright (C) 2007-2010 VCMI dev team - see AUTHORS file\n"); printf("Copyright (C) 2007-2012 VCMI dev team - see AUTHORS file\n");
printf("This is free software; see the source for copying conditions. There is NO\n"); printf("This is free software; see the source for copying conditions. There is NO\n");
printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"); printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
printf("\n"); printf("\n");
printf("Usage:\n"); printf("Usage:\n");
printf(" -h, --help display this help and exit\n"); std::cout << opts;
printf(" -v, --version display version information and exit\n"); // printf(" -h, --help display this help and exit\n");
// printf(" -v, --version display version information and exit\n");
} }
@ -189,6 +204,10 @@ int main(int argc, char** argv)
("help,h", "display help and exit") ("help,h", "display help and exit")
("version,v", "display version information and exit") ("version,v", "display version information and exit")
("battle,b", po::value<std::string>(), "runs game in duel mode (battle-only") ("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")
("oneGoodAI", "puts one default AI and the rest will be GeniusAI")
("autoSkip", "automatically skip turns in GUI")
("nointro,i", "skips intro movies"); ("nointro,i", "skips intro movies");
po::variables_map vm; po::variables_map vm;
@ -207,7 +226,7 @@ int main(int argc, char** argv)
po::notify(vm); po::notify(vm);
if(vm.count("help")) if(vm.count("help"))
{ {
prog_help(0); prog_help(opts);
return 0; return 0;
} }
if(vm.count("version")) if(vm.count("version"))
@ -269,8 +288,15 @@ int main(int argc, char** argv)
if(!vm.count("battle")) if(!vm.count("battle"))
{ {
//CCS->musich->playMusic(musicBase::mainMenu, -1); gOnlyAI = vm.count("onlyAI");
conf.cc.autoSkip = vm.count("autoSkip");
conf.cc.oneGoodAI = vm.count("oneGoodAI");
if(!vm.count("start"))
GH.curInt = new CGPreGame; //will set CGP pointer to itself GH.curInt = new CGPreGame; //will set CGP pointer to itself
else
startGameFromFile(vm["start"].as<std::string>());
} }
else else
{ {
@ -508,6 +534,22 @@ void processCommand(const std::string &message)
{ {
conf.cc.classicCreatureWindow = !conf.cc.classicCreatureWindow; conf.cc.classicCreatureWindow = !conf.cc.classicCreatureWindow;
} }
else if(cn == "sinfo")
{
std::string fname;
readed >> fname;
if(fname.size() && SEL)
{
CSaveFile out(fname);
out << SEL->sInfo;
}
}
else if(cn == "start")
{
std::string fname;
readed >> fname;
startGameFromFile(fname);
}
else if(client && client->serv && client->serv->connected) //send to server else if(client && client->serv && client->serv->connected) //send to server
{ {
PlayerMessage pm(LOCPLINT->playerID,message); PlayerMessage pm(LOCPLINT->playerID,message);

View File

@ -2140,6 +2140,11 @@ CGPath * CPlayerInterface::getAndVerifyPath(const CGHeroInstance * h)
void CPlayerInterface::acceptTurn() void CPlayerInterface::acceptTurn()
{ {
if(conf.cc.autoSkip)
{
while(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt()))
iw->close();
}
waitWhileDialog(); waitWhileDialog();
if(howManyPeople > 1) if(howManyPeople > 1)
@ -2171,24 +2176,47 @@ void CPlayerInterface::acceptTurn()
adventureInt->select(towns.front()); adventureInt->select(towns.front());
adventureInt->showAll(screen); adventureInt->showAll(screen);
if(conf.cc.autoSkip && !LOCPLINT->shiftPressed())
{
if(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt()))
iw->close();
adventureInt->endTurn.callback();
}
} }
void CPlayerInterface::tryDiggging(const CGHeroInstance *h) void CPlayerInterface::tryDiggging(const CGHeroInstance *h)
{ {
std::string hlp; std::string hlp;
if(h->movement < h->maxMovePoints(true))
showInfoDialog(CGI->generaltexth->allTexts[56]); //"Digging for artifacts requires a whole day, try again tomorrow."
else if(cb->getTile(h->getPosition(false))->tertype == TerrainTile::water)
showInfoDialog(CGI->generaltexth->allTexts[60]); //Try looking on land!
else
{
const TerrainTile *t = cb->getTile(h->getPosition());
CGI->mh->getTerrainDescr(h->getPosition(false), hlp, false); CGI->mh->getTerrainDescr(h->getPosition(false), hlp, false);
if(hlp.length() || t->blockingObjects.size() > 1)
showInfoDialog(CGI->generaltexth->allTexts[97]); //Try searching on clear ground. int msgToShow = -1;
else CGHeroInstance::ECanDig isDiggingPossible = h->diggingStatus();
cb->dig(h); if(hlp.length())
isDiggingPossible = CGHeroInstance::TILE_OCCUPIED; //TODO integrate with canDig
switch(isDiggingPossible)
{
case CGHeroInstance::CAN_DIG:
break;
case CGHeroInstance::LACK_OF_MOVEMENT:
msgToShow = 56; //"Digging for artifacts requires a whole day, try again tomorrow."
break;
case CGHeroInstance::TILE_OCCUPIED:
msgToShow = 97; //Try searching on clear ground.
break;
case CGHeroInstance::WRONG_TERRAIN:
msgToShow = 60; ////Try looking on land!
break;
default:
assert(0);
} }
if(msgToShow < 0)
cb->dig(h);
else
showInfoDialog(CGI->generaltexth->allTexts[msgToShow]);
} }
void CPlayerInterface::updateInfo(const CGObjectInstance * specific) void CPlayerInterface::updateInfo(const CGObjectInstance * specific)

View File

@ -503,4 +503,5 @@ public:
void openCampaignScreen(std::string name); void openCampaignScreen(std::string name);
}; };
extern ISelectionScreenInfo *SEL;
extern CGPreGame *CGP; extern CGPreGame *CGP;

View File

@ -121,7 +121,7 @@ void CClient::waitForMoveAndSend(int color)
assert(vstd::contains(battleints, color)); assert(vstd::contains(battleints, color));
BattleAction ba = battleints[color]->activeStack(gs->curB->getStack(gs->curB->activeStack, false)); BattleAction ba = battleints[color]->activeStack(gs->curB->getStack(gs->curB->activeStack, false));
MakeAction temp_action(ba); MakeAction temp_action(ba);
*serv << &temp_action; serv->sendPackToServer(temp_action, color);
return; return;
}HANDLE_EXCEPTION }HANDLE_EXCEPTION
tlog1 << "We should not be here!" << std::endl; tlog1 << "We should not be here!" << std::endl;
@ -169,7 +169,7 @@ void CClient::save(const std::string & fname)
} }
SaveGame save_game(fname); SaveGame save_game(fname);
*serv << &save_game; serv->sendPackToServer((CPackForClient&)save_game, getCurrentPlayer());
} }
void CClient::endGame( bool closeConnection /*= true*/ ) void CClient::endGame( bool closeConnection /*= true*/ )
@ -348,6 +348,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
} }
int humanPlayers = 0; int humanPlayers = 0;
int sensibleAILimit = conf.cc.oneGoodAI ? 1 : GameConstants::PLAYER_LIMIT;
for(std::map<int, PlayerSettings>::iterator it = gs->scenarioOps->playerInfos.begin(); for(std::map<int, PlayerSettings>::iterator it = gs->scenarioOps->playerInfos.begin();
it != gs->scenarioOps->playerInfos.end(); ++it)//initializing interfaces for players it != gs->scenarioOps->playerInfos.end(); ++it)//initializing interfaces for players
{ {
@ -361,7 +362,13 @@ void CClient::newGame( CConnection *con, StartInfo *si )
CCallback *cb = new CCallback(gs,color,this); CCallback *cb = new CCallback(gs,color,this);
if(!it->second.human) if(!it->second.human)
{ {
playerint[color] = static_cast<CGameInterface*>(CDynLibHandler::getNewAI(conf.cc.defaultPlayerAI)); std::string AItoGive = conf.cc.defaultPlayerAI;
if(!sensibleAILimit)
AItoGive = "GeniusAI";
else
sensibleAILimit--;
playerint[color] = static_cast<CGameInterface*>(CDynLibHandler::getNewAI(AItoGive));
tlog1 << "Player " << (int)color << " will be lead by " << AItoGive << std::endl;
} }
else else
{ {
@ -515,7 +522,7 @@ void CClient::stopConnection()
tlog0 << "Connection has been requested to be closed.\n"; tlog0 << "Connection has been requested to be closed.\n";
boost::unique_lock<boost::mutex>(*serv->wmx); boost::unique_lock<boost::mutex>(*serv->wmx);
CloseServer close_server; CloseServer close_server;
*serv << &close_server; serv->sendPackToServer(close_server, 255);
tlog0 << "Sent closing signal to the server\n"; tlog0 << "Sent closing signal to the server\n";
} }
@ -579,7 +586,7 @@ void CClient::commitPackage( CPackForClient *pack )
CommitPackage cp; CommitPackage cp;
cp.freePack = false; cp.freePack = false;
cp.packToCommit = pack; cp.packToCommit = pack;
*serv << &cp; serv->sendPackToServer(cp, 255);
} }
int CClient::getLocalPlayer() const int CClient::getLocalPlayer() const
@ -605,7 +612,7 @@ void CClient::commenceTacticPhaseForInt(CBattleGameInterface *battleInt)
if(gs && !!gs->curB && gs->curB->tacticDistance) //while awaiting for end of tactics phase, many things can happen (end of battle... or game) if(gs && !!gs->curB && gs->curB->tacticDistance) //while awaiting for end of tactics phase, many things can happen (end of battle... or game)
{ {
MakeAction ma(BattleAction::makeEndOFTacticPhase(battleInt->playerID)); MakeAction ma(BattleAction::makeEndOFTacticPhase(battleInt->playerID));
serv->sendPack(ma); serv->sendPackToServer(ma, battleInt->playerID);
} }
} HANDLE_EXCEPTION } HANDLE_EXCEPTION
} }

View File

@ -710,7 +710,6 @@ void EndAction::applyCl( CClient *cl )
void PackageApplied::applyCl( CClient *cl ) void PackageApplied::applyCl( CClient *cl )
{ {
ui8 player = GS(cl)->currentPlayer;
INTERFACE_CALL_IF_PRESENT(player, requestRealized, this); INTERFACE_CALL_IF_PRESENT(player, requestRealized, this);
if(cl->waitingRequest.get() == packType) if(cl->waitingRequest.get() == packType)
cl->waitingRequest.setn(false); cl->waitingRequest.setn(false);
@ -811,6 +810,8 @@ void OpenWindow::applyCl(CClient *cl)
case THIEVES_GUILD: case THIEVES_GUILD:
{ {
//displays Thieves' Guild window (when hero enters Den of Thieves) //displays Thieves' Guild window (when hero enters Den of Thieves)
if(!LOCPLINT)
return;
const CGObjectInstance *obj = cl->getObj(id1); const CGObjectInstance *obj = cl->getObj(id1);
GH.pushInt( new CThievesGuildWindow(obj) ); GH.pushInt( new CThievesGuildWindow(obj) );
} }

View File

@ -136,6 +136,8 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings> <DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<AssemblerOutput>NoListing</AssemblerOutput> <AssemblerOutput>NoListing</AssemblerOutput>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>SDL.lib;zlib.lib;SDL_image.lib;SDL_ttf.lib;SDL_mixer.lib;VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>SDL.lib;zlib.lib;SDL_image.lib;SDL_ttf.lib;SDL_mixer.lib;VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -168,6 +170,8 @@
<AssemblerListingLocation>$(SolutionDir)$(Configuration)\</AssemblerListingLocation> <AssemblerListingLocation>$(SolutionDir)$(Configuration)\</AssemblerListingLocation>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>SDL.lib;zlib.lib;SDL_image.lib;SDL_ttf.lib;SDL_mixer.lib;VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>SDL.lib;zlib.lib;SDL_image.lib;SDL_ttf.lib;SDL_mixer.lib;VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -203,6 +207,8 @@
<AssemblerListingLocation>$(SolutionDir)$(Configuration)\</AssemblerListingLocation> <AssemblerListingLocation>$(SolutionDir)$(Configuration)\</AssemblerListingLocation>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>SDL.lib;zlib.lib;SDL_image.lib;SDL_ttf.lib;SDL_mixer.lib;VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>SDL.lib;zlib.lib;SDL_image.lib;SDL_ttf.lib;SDL_mixer.lib;VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -250,6 +256,9 @@
<ClCompile Include="StdInc.cpp"> <ClCompile Include="StdInc.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">StdInc.h</PrecompiledHeaderFile> <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">StdInc.h</PrecompiledHeaderFile>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='RD|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='RD|x64'">Create</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="UIFramework\CCursorHandler.cpp" /> <ClCompile Include="UIFramework\CCursorHandler.cpp" />
<ClCompile Include="UIFramework\CGuiHandler.cpp" /> <ClCompile Include="UIFramework\CGuiHandler.cpp" />
@ -301,6 +310,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\ChangeLog" /> <None Include="..\ChangeLog" />
<None Include="ClassDiagram21.cd" />
<None Include="vcmi.ico" /> <None Include="vcmi.ico" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -2203,7 +2203,7 @@ ESpellCastProblem::ESpellCastProblem BattleInfo::battleIsImmune(const CGHeroInst
return ESpellCastProblem::OK; return ESpellCastProblem::OK;
} }
std::vector<ui32> BattleInfo::calculateResistedStacks( const CSpell * sp, const CGHeroInstance * caster, const CGHeroInstance * hero2, const std::set<CStack*> affectedCreatures, int casterSideOwner, ECastingMode::ECastingMode mode ) const std::vector<ui32> BattleInfo::calculateResistedStacks(const CSpell * sp, const CGHeroInstance * caster, const CGHeroInstance * hero2, const std::set<CStack*> affectedCreatures, int casterSideOwner, ECastingMode::ECastingMode mode, int usedSpellPower, int spellLevel) const
{ {
std::vector<ui32> ret; std::vector<ui32> ret;
for(std::set<CStack*>::const_iterator it = affectedCreatures.begin(); it != affectedCreatures.end(); ++it) for(std::set<CStack*>::const_iterator it = affectedCreatures.begin(); it != affectedCreatures.end(); ++it)
@ -2241,7 +2241,7 @@ std::vector<ui32> BattleInfo::calculateResistedStacks( const CSpell * sp, const
if( (*it)->hasBonusOfType(Bonus::SPELL_IMMUNITY, sp->id) //100% sure spell immunity if( (*it)->hasBonusOfType(Bonus::SPELL_IMMUNITY, sp->id) //100% sure spell immunity
|| ( (*it)->count - 1 ) * (*it)->MaxHealth() + (*it)->firstHPleft || ( (*it)->count - 1 ) * (*it)->MaxHealth() + (*it)->firstHPleft
> >
caster->getPrimSkillLevel(2) * 25 + sp->powers[caster->getSpellSchoolLevel(sp)] usedSpellPower * 25 + sp->powers[spellLevel]
) )
{ {
ret.push_back((*it)->ID); ret.push_back((*it)->ID);

View File

@ -135,7 +135,7 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode
TSpell getRandomBeneficialSpell(const CStack * subject) const; TSpell getRandomBeneficialSpell(const CStack * subject) const;
TSpell getRandomCastedSpell(const CStack * caster) const; //called at the beginning of turn for Faerie Dragon TSpell getRandomCastedSpell(const CStack * caster) const; //called at the beginning of turn for Faerie Dragon
std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHeroInstance * caster, const CGHeroInstance * hero2, const std::set<CStack*> affectedCreatures, int casterSideOwner, ECastingMode::ECastingMode mode) const; std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHeroInstance * caster, const CGHeroInstance * hero2, const std::set<CStack*> affectedCreatures, int casterSideOwner, ECastingMode::ECastingMode mode, int usedSpellPower, int spellLevel) const;
bool battleCanFlee(int player) const; //returns true if player can flee from the battle bool battleCanFlee(int player) const; //returns true if player can flee from the battle

View File

@ -210,13 +210,13 @@ ui64 CCreatureSet::getArmyStrength() const
{ {
ui64 ret = 0; ui64 ret = 0;
for(TSlots::const_iterator i = stacks.begin(); i != stacks.end(); i++) for(TSlots::const_iterator i = stacks.begin(); i != stacks.end(); i++)
ret += i->second->type->AIValue * i->second->count; ret += i->second->getPower();
return ret; return ret;
} }
ui64 CCreatureSet::getPower (TSlot slot) const ui64 CCreatureSet::getPower (TSlot slot) const
{ {
return getCreature(slot)->AIValue * getStackCount(slot); return getStack(slot).getPower();
} }
std::string CCreatureSet::getRoughAmount (TSlot slot) const std::string CCreatureSet::getRoughAmount (TSlot slot) const
{ {
@ -942,6 +942,12 @@ std::string CStackInstance::getName() const
return (count > 1) ? type->namePl : type->nameSing; return (count > 1) ? type->namePl : type->nameSing;
} }
ui64 CStackInstance::getPower() const
{
assert(type);
return type->AIValue * count;
}
CStackBasicDescriptor::CStackBasicDescriptor() CStackBasicDescriptor::CStackBasicDescriptor()
{ {
type = NULL; type = NULL;

View File

@ -48,6 +48,7 @@ public:
std::string bonusToString(Bonus *bonus, bool description) const; // how would bonus description look for this particular type of node std::string bonusToString(Bonus *bonus, bool description) const; // 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 bonusToGraphics(Bonus *bonus) const; //file name of graphics from StackSkills , in future possibly others
ui64 getPower() const;
int getQuantityID() const; int getQuantityID() const;
std::string getQuantityTXT(bool capitalized = true) const; std::string getQuantityTXT(bool capitalized = true) const;
int getExpRank() const; int getExpRank() const;

View File

@ -92,12 +92,6 @@ class DLL_LINKAGE CGlobalAI : public CGameInterface // AI class (to derivate)
{ {
public: public:
CGlobalAI(); CGlobalAI();
virtual void yourTurn() OVERRIDE{};
virtual void heroKilled(const CGHeroInstance*){};
virtual void heroCreated(const CGHeroInstance*) OVERRIDE{};
virtual void battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance) OVERRIDE{};
virtual void battleStackAttacking(int ID, int dest) {};
virtual void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa) OVERRIDE{};
virtual BattleAction activeStack(const CStack * stack) OVERRIDE; virtual BattleAction activeStack(const CStack * stack) OVERRIDE;
}; };

View File

@ -1720,6 +1720,9 @@ int CGameState::getPlayerRelations( ui8 color1, ui8 color2 )
{ {
if ( color1 == color2 ) if ( color1 == color2 )
return 2; return 2;
if(color1 == 255 || color2 == 255) //neutral player has no friends
return 0;
const TeamState * ts = getPlayerTeam(color1); const TeamState * ts = getPlayerTeam(color1);
if (ts && vstd::contains(ts->players, color2)) if (ts && vstd::contains(ts->players, color2))
return 1; return 1;
@ -2007,9 +2010,12 @@ bool CGameState::checkForVisitableDir( const int3 & src, const TerrainTile *pom,
int CGameState::victoryCheck( ui8 player ) const int CGameState::victoryCheck( ui8 player ) const
{ {
const PlayerState *p = CGameInfoCallback::getPlayer(player); const PlayerState *p = CGameInfoCallback::getPlayer(player);
if(map->victoryCondition.condition == EVictoryConditionType::WINSTANDARD || map->victoryCondition.allowNormalVictory) if(map->victoryCondition.condition == EVictoryConditionType::WINSTANDARD || map->victoryCondition.allowNormalVictory
|| (!p->human && !map->victoryCondition.appliesToAI)) //if the special victory condition applies only to human, AI has the standard)
{
if(player == checkForStandardWin()) if(player == checkForStandardWin())
return -1; return -1;
}
if (p->enteredWinningCheatCode) if (p->enteredWinningCheatCode)
{ //cheater or tester, but has entered the code... { //cheater or tester, but has entered the code...
@ -2477,6 +2483,11 @@ CGPathNode::CGPathNode()
theNodeBefore = NULL; theNodeBefore = NULL;
} }
bool CGPathNode::reachable() const
{
return turns < 255;
}
bool CPathsInfo::getPath( const int3 &dst, CGPath &out ) bool CPathsInfo::getPath( const int3 &dst, CGPath &out )
{ {
assert(isValid); assert(isValid);
@ -2940,7 +2951,8 @@ bool CPathfinder::goodForLandSeaTransition()
return false; return false;
//tile must be accessible -> exception: unblocked blockvis tiles -> clear but guarded by nearby monster coast //tile must be accessible -> exception: unblocked blockvis tiles -> clear but guarded by nearby monster coast
if(dp->accessible != CGPathNode::ACCESSIBLE && (dp->accessible != CGPathNode::BLOCKVIS || dt->blocked)) if(dp->accessible != CGPathNode::ACCESSIBLE && (dp->accessible != CGPathNode::BLOCKVIS || dt->blocked)
|| dt->visitable) //TODO: passableness problem -> town says it's passable (thus accessible) but we obviously can't disembark onto town gate
return false;; return false;;
useEmbarkCost = 2; useEmbarkCost = 2;

View File

@ -217,7 +217,7 @@ struct CPathNode
bool visited; bool visited;
}; };
struct CGPathNode struct DLL_LINKAGE CGPathNode
{ {
enum EAccessibility enum EAccessibility
{ {
@ -233,7 +233,9 @@ struct CGPathNode
ui32 moveRemains; ui32 moveRemains;
CGPathNode * theNodeBefore; CGPathNode * theNodeBefore;
int3 coord; //coordinates int3 coord; //coordinates
CGPathNode(); CGPathNode();
bool reachable() const;
}; };
@ -306,7 +308,7 @@ struct DLL_LINKAGE DuelParameters
class CPathfinder : private CGameInfoCallback class CPathfinder : private CGameInfoCallback
{ {
public: private:
bool useSubterraneanGates; bool useSubterraneanGates;
bool allowEmbarkAndDisembark; bool allowEmbarkAndDisembark;
CPathsInfo &out; CPathsInfo &out;
@ -323,19 +325,18 @@ public:
ui8 useEmbarkCost; //0 - usual movement; 1 - embark; 2 - disembark ui8 useEmbarkCost; //0 - usual movement; 1 - embark; 2 - disembark
int destTopVisObjID; int destTopVisObjID;
CPathfinder(CPathsInfo &_out, CGameState *_gs, const CGHeroInstance *_hero);;
CGPathNode *getNode(const int3 &coord); CGPathNode *getNode(const int3 &coord);
void initializeGraph(); void initializeGraph();
CGPathNode::EAccessibility evaluateAccessibility(const TerrainTile *tinfo) const;
void calculatePaths(int3 src = int3(-1,-1,-1), int movement = -1); //calculates possible paths for hero, by default uses current hero position and movement left; returns pointer to newly allocated CPath or NULL if path does not exists
bool canMoveBetween(const int3 &a, const int3 &b) const; //checks only for visitable objects that may make moving between tiles impossible, not other conditions (like tiles itself accessibility)
bool canStepOntoDst() const;
bool goodForLandSeaTransition(); //checks if current move will be between sea<->land. If so, checks it legality (returns false if movement is not possible) and sets useEmbarkCost bool goodForLandSeaTransition(); //checks if current move will be between sea<->land. If so, checks it legality (returns false if movement is not possible) and sets useEmbarkCost
CGPathNode::EAccessibility evaluateAccessibility(const TerrainTile *tinfo) const;
bool canMoveBetween(const int3 &a, const int3 &b) const; //checks only for visitable objects that may make moving between tiles impossible, not other conditions (like tiles itself accessibility)
bool canStepOntoDst() const;
public:
CPathfinder(CPathsInfo &_out, CGameState *_gs, const CGHeroInstance *_hero);
void calculatePaths(int3 src = int3(-1,-1,-1), int movement = -1); //calculates possible paths for hero, by default uses current hero position and movement left; returns pointer to newly allocated CPath or NULL if path does not exists
}; };

View File

@ -1486,6 +1486,25 @@ int CGHeroInstance::movementPointsAfterEmbark(int MPsBefore, int basicCost, bool
return 0; //take all MPs otherwise return 0; //take all MPs otherwise
} }
CGHeroInstance::ECanDig CGHeroInstance::diggingStatus() const
{
std::string hlp;
if(movement < maxMovePoints(true))
return LACK_OF_MOVEMENT;
else if(cb->getTile(getPosition(false))->tertype == TerrainTile::water)
return WRONG_TERRAIN;
else
{
const TerrainTile *t = cb->getTile(getPosition());
//TODO look for hole
//CGI->mh->getTerrainDescr(h->getPosition(false), hlp, false);
if(/*hlp.length() || */t->blockingObjects.size() > 1)
return TILE_OCCUPIED;
else
return CAN_DIG;
}
}
void CGDwelling::initObj() void CGDwelling::initObj()
{ {
switch(ID) switch(ID)
@ -2392,6 +2411,11 @@ const CArmedInstance * CGTownInstance::getUpperArmy() const
return this; return this;
} }
bool CGTownInstance::hasBuilt(int buildingID) const
{
return vstd::contains(builtBuildings, buildingID);
}
void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const
{ {
if(visitors.find(h->id)==visitors.end()) if(visitors.find(h->id)==visitors.end())

View File

@ -123,11 +123,11 @@ public:
class DLL_LINKAGE IMarket class DLL_LINKAGE IMarket
{ {
virtual int getMarketEfficiency() const =0;
public: public:
const CGObjectInstance *o; const CGObjectInstance *o;
IMarket(const CGObjectInstance *O); IMarket(const CGObjectInstance *O);
virtual int getMarketEfficiency() const =0;
virtual bool allowsTrade(EMarketMode::EMarketMode mode) const; virtual bool allowsTrade(EMarketMode::EMarketMode mode) const;
virtual int availableUnits(EMarketMode::EMarketMode mode, int marketItemSerial) const; //-1 if unlimited virtual int availableUnits(EMarketMode::EMarketMode mode, int marketItemSerial) const; //-1 if unlimited
virtual std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const; virtual std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const;
@ -256,6 +256,10 @@ public:
SCHOLAR, TACTICS, ARTILLERY, LEARNING, OFFENCE, ARMORER, INTELLIGENCE, SORCERY, RESISTANCE, SCHOLAR, TACTICS, ARTILLERY, LEARNING, OFFENCE, ARMORER, INTELLIGENCE, SORCERY, RESISTANCE,
FIRST_AID FIRST_AID
}; };
enum ECanDig
{
CAN_DIG, LACK_OF_MOVEMENT, WRONG_TERRAIN, TILE_OCCUPIED
};
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
ui8 moveDir; //format: 123 ui8 moveDir; //format: 123
@ -366,6 +370,7 @@ public:
bool canCastThisSpell(const CSpell * spell) const; //determines if this hero can cast given spell; takes into account existing spell in spellbook, existing spellbook and artifact bonuses bool canCastThisSpell(const CSpell * spell) const; //determines if this hero can cast given spell; takes into account existing spell in spellbook, existing spellbook and artifact bonuses
CStackBasicDescriptor calculateNecromancy (const BattleResult &battleResult) const; CStackBasicDescriptor calculateNecromancy (const BattleResult &battleResult) const;
void showNecromancyDialog(const CStackBasicDescriptor &raisedStack) const; void showNecromancyDialog(const CStackBasicDescriptor &raisedStack) const;
ECanDig diggingStatus() const; //0 - can dig; 1 - lack of movement; 2 -
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -607,6 +612,7 @@ public:
GrowthInfo getGrowthInfo(int level) const; GrowthInfo getGrowthInfo(int level) const;
bool hasFort() const; bool hasFort() const;
bool hasCapitol() const; bool hasCapitol() const;
bool hasBuilt(int buildingID) const;
int dailyIncome() const; //calculates daily income of this town int dailyIncome() const; //calculates daily income of this town
int spellsAtLevel(int level, bool checkGuild) const; //levels are counted from 1 (1 - 5) int spellsAtLevel(int level, bool checkGuild) const; //levels are counted from 1 (1 - 5)
void removeCapitols (ui8 owner) const; void removeCapitols (ui8 owner) const;

View File

@ -240,10 +240,11 @@ CPack * CConnection::retreivePack()
return ret; return ret;
} }
void CConnection::sendPack(const CPack &pack) void CConnection::sendPackToServer(const CPack &pack, ui8 player)
{ {
boost::unique_lock<boost::mutex> lock(*wmx); boost::unique_lock<boost::mutex> lock(*wmx);
*this << &pack; //packs has to be sent as polymorphic pointers! tlog5 << "Sending to server a pack of type " << typeid(pack).name() << std::endl;
*this << player << &pack; //packs has to be sent as polymorphic pointers!
} }
CSaveFile::CSaveFile( const std::string &fname ) CSaveFile::CSaveFile( const std::string &fname )

View File

@ -916,7 +916,7 @@ public:
~CConnection(void); ~CConnection(void);
CPack *retreivePack(); //gets from server next pack (allocates it with new) CPack *retreivePack(); //gets from server next pack (allocates it with new)
void sendPack(const CPack &pack); void sendPackToServer(const CPack &pack, ui8 player);
}; };
DLL_LINKAGE std::ostream &operator<<(std::ostream &str, const CConnection &cpc); DLL_LINKAGE std::ostream &operator<<(std::ostream &str, const CConnection &cpc);

View File

@ -1253,6 +1253,11 @@ int CGameInfoCallback::getLocalPlayer() const
return getCurrentPlayer(); return getCurrentPlayer();
} }
bool CGameInfoCallback::isInTheMap(const int3 &pos) const
{
return gs->map->isInTheMap(pos);
}
void IGameEventRealizer::showInfoDialog( InfoWindow *iw ) void IGameEventRealizer::showInfoDialog( InfoWindow *iw )
{ {
commitPackage(iw); commitPackage(iw);

View File

@ -190,6 +190,7 @@ public:
const CMapHeader * getMapHeader()const; const CMapHeader * getMapHeader()const;
int3 getMapSize() const; //returns size of map - z is 1 for one - level map and 2 for two level map int3 getMapSize() const; //returns size of map - z is 1 for one - level map and 2 for two level map
const TerrainTile * getTile(int3 tile, bool verbose = true) const; const TerrainTile * getTile(int3 tile, bool verbose = true) const;
bool isInTheMap(const int3 &pos) const;
//town //town
const CGTownInstance* getTown(int objid) const; const CGTownInstance* getTown(int objid) const;

View File

@ -60,12 +60,14 @@ struct CPackForClient : public CPack
struct CPackForServer : public CPack struct CPackForServer : public CPack
{ {
ui8 player;
CConnection *c; CConnection *c;
CGameState* GS(CGameHandler *gh); CGameState* GS(CGameHandler *gh);
CPackForServer() CPackForServer()
{ {
type = 2; type = 2;
c = NULL; c = NULL;
player = 255;
}; };
bool applyGh(CGameHandler *gh);//called after applying to gs bool applyGh(CGameHandler *gh);//called after applying to gs
@ -170,10 +172,11 @@ struct PackageApplied : public CPackForClient //94
ui8 result; //0 - something went wrong, request hasn't been realized; 1 - OK ui8 result; //0 - something went wrong, request hasn't been realized; 1 - OK
ui32 packType; //type id of applied package ui32 packType; //type id of applied package
ui8 player;
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & result & packType; h & result & packType & player;
} }
}; };

View File

@ -449,6 +449,11 @@ DLL_LINKAGE void HeroRecruited::applyGs( CGameState *gs )
DLL_LINKAGE void GiveHero::applyGs( CGameState *gs ) DLL_LINKAGE void GiveHero::applyGs( CGameState *gs )
{ {
CGHeroInstance *h = gs->getHero(id); CGHeroInstance *h = gs->getHero(id);
//bonus system
h->detachFrom(&gs->globalEffects);
h->attachTo(gs->getPlayer(player));
gs->map->removeBlockVisTiles(h,true); gs->map->removeBlockVisTiles(h,true);
h->setOwner(player); h->setOwner(player);
h->movement = h->maxMovePoints(true); h->movement = h->maxMovePoints(true);

View File

@ -78,6 +78,14 @@ namespace Res
return ret; return ret;
} }
DLL_LINKAGE ResourceSet & operator=(const TResource &rhs)
{
for(int i = 0; i < size(); i++)
at(i) = rhs;
return *this;
}
// WARNING: comparison operators are used for "can afford" relation: a <= b means that foreach i a[i] <= b[i] // WARNING: comparison operators are used for "can afford" relation: a <= b means that foreach i a[i] <= b[i]
// that doesn't work the other way: a > b doesn't mean that a cannot be afforded with b, it's still b can afford a // that doesn't work the other way: a > b doesn't mean that a cannot be afforded with b, it's still b can afford a
// bool operator<(const ResourceSet &rhs) // bool operator<(const ResourceSet &rhs)

View File

@ -134,6 +134,7 @@
<ExpandAttributedSource>false</ExpandAttributedSource> <ExpandAttributedSource>false</ExpandAttributedSource>
<AssemblerOutput>NoListing</AssemblerOutput> <AssemblerOutput>NoListing</AssemblerOutput>
<PreprocessToFile>false</PreprocessToFile> <PreprocessToFile>false</PreprocessToFile>
<PreprocessorDefinitions>VCMI_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>zlib.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -161,6 +162,9 @@
<AssemblerListingLocation>$(SolutionDir)$(Configuration)\</AssemblerListingLocation> <AssemblerListingLocation>$(SolutionDir)$(Configuration)\</AssemblerListingLocation>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<PreprocessorDefinitions>VCMI_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>zlib.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -197,6 +201,9 @@
<AssemblerListingLocation>$(SolutionDir)$(Configuration)\</AssemblerListingLocation> <AssemblerListingLocation>$(SolutionDir)$(Configuration)\</AssemblerListingLocation>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<PreprocessorDefinitions>VCMI_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>zlib.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -246,6 +253,10 @@
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">VCMI_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">VCMI_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">StdInc.h</PrecompiledHeaderFile> <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">StdInc.h</PrecompiledHeaderFile>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='RD|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='RD|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">StdInc.h</PrecompiledHeaderFile>
</ClCompile> </ClCompile>
<ClCompile Include="VCMI_Lib.cpp" /> <ClCompile Include="VCMI_Lib.cpp" />
</ItemGroup> </ItemGroup>

View File

@ -2222,3 +2222,8 @@ bool TerrainTile::hasFavourableWinds() const
{ {
return siodmyTajemniczyBajt & 128; return siodmyTajemniczyBajt & 128;
} }
bool TerrainTile::isWater() const
{
return tertype == water;
}

View File

@ -67,6 +67,8 @@ struct DLL_LINKAGE TerrainTile
bool isClear(const TerrainTile *from = NULL) const; //checks for blocking objs and terraint type (water / land) bool isClear(const TerrainTile *from = NULL) const; //checks for blocking objs and terraint type (water / land)
int topVisitableID() const; //returns ID of the top visitable ovject or -1 if there is none int topVisitableID() const; //returns ID of the top visitable ovject or -1 if there is none
bool isWater() const;
bool isCoastal() const; bool isCoastal() const;
bool hasFavourableWinds() const; bool hasFavourableWinds() const;
}; };

View File

@ -53,6 +53,7 @@ extern bool end2;
#define COMPLAIN_RET_IF(cond, txt) do {if(cond){complain(txt); return;}} while(0) #define COMPLAIN_RET_IF(cond, txt) do {if(cond){complain(txt); return;}} while(0)
#define COMPLAIN_RET(txt) {complain(txt); return false;} #define COMPLAIN_RET(txt) {complain(txt); return false;}
#define COMPLAIN_RETF(txt, FORMAT) {complain(boost::str(boost::format(txt) % FORMAT)); return false;}
#define NEW_ROUND BattleNextRound bnr;\ #define NEW_ROUND BattleNextRound bnr;\
bnr.round = gs->curB->round + 1;\ bnr.round = gs->curB->round + 1;\
sendAndApply(&bnr); sendAndApply(&bnr);
@ -67,7 +68,7 @@ template <typename T> class CApplyOnGH;
class CBaseForGHApply class CBaseForGHApply
{ {
public: public:
virtual bool applyOnGH(CGameHandler *gh, CConnection *c, void *pack) const =0; virtual bool applyOnGH(CGameHandler *gh, CConnection *c, void *pack, ui8 player) const =0;
virtual ~CBaseForGHApply(){} virtual ~CBaseForGHApply(){}
template<typename U> static CBaseForGHApply *getApplier(const U * t=NULL) template<typename U> static CBaseForGHApply *getApplier(const U * t=NULL)
{ {
@ -78,10 +79,11 @@ public:
template <typename T> class CApplyOnGH : public CBaseForGHApply template <typename T> class CApplyOnGH : public CBaseForGHApply
{ {
public: public:
bool applyOnGH(CGameHandler *gh, CConnection *c, void *pack) const bool applyOnGH(CGameHandler *gh, CConnection *c, void *pack, ui8 player) const
{ {
T *ptr = static_cast<T*>(pack); T *ptr = static_cast<T*>(pack);
ptr->c = c; ptr->c = c;
ptr->player = player;
return ptr->applyGh(gh); return ptr->applyGh(gh);
} }
}; };
@ -121,7 +123,8 @@ void PlayerStatuses::addPlayer(ui8 player)
boost::unique_lock<boost::mutex> l(mx); boost::unique_lock<boost::mutex> l(mx);
players[player]; players[player];
} }
bool PlayerStatuses::hasQueries(ui8 player)
int PlayerStatuses::getQueriesCount(ui8 player)
{ {
boost::unique_lock<boost::mutex> l(mx); boost::unique_lock<boost::mutex> l(mx);
if(players.find(player) != players.end()) if(players.find(player) != players.end())
@ -130,9 +133,10 @@ bool PlayerStatuses::hasQueries(ui8 player)
} }
else else
{ {
throw std::string("No such player!"); return 0;
} }
} }
bool PlayerStatuses::checkFlag(ui8 player, bool PlayerStatus::*flag) bool PlayerStatuses::checkFlag(ui8 player, bool PlayerStatus::*flag)
{ {
boost::unique_lock<boost::mutex> l(mx); boost::unique_lock<boost::mutex> l(mx);
@ -624,24 +628,26 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
setThreadName(-1, "CGameHandler::handleConnection"); setThreadName(-1, "CGameHandler::handleConnection");
srand(time(NULL)); srand(time(NULL));
CPack *pack = NULL; CPack *pack = NULL;
ui8 player = 255;
try try
{ {
while(1)//server should never shut connection first //was: while(!end2) while(1)//server should never shut connection first //was: while(!end2)
{ {
{ {
boost::unique_lock<boost::mutex> lock(*c.rmx); boost::unique_lock<boost::mutex> lock(*c.rmx);
c >> pack; //get the package c >> player >> pack; //get the package
tlog5 << "Received client message of type " << typeid(*pack).name() << std::endl; tlog5 << "Received client message of type " << typeid(*pack).name() << std::endl;
} }
int packType = typeList.getTypeID(pack); //get the id of type int packType = typeList.getTypeID(pack); //get the id of type
CBaseForGHApply *apply = applier->apps[packType]; //and appropriae applier object CBaseForGHApply *apply = applier->apps[packType]; //and appropriae applier object
if(packType != typeList.getTypeID<QueryReply>() && if(packType != typeList.getTypeID<QueryReply>()
(packType != typeList.getTypeID<ArrangeStacks>() || !isAllowedArrangePack((ArrangeStacks*)pack)) && // for dialogs like garrison && (packType != typeList.getTypeID<ArrangeStacks>() || !isAllowedArrangePack((ArrangeStacks*)pack)) // for dialogs like garrison
states[getCurrentPlayer()].queries.size()) && states.getQueriesCount(player))
{ {
complain("Answer the query before attempting any further actions!"); complain(boost::str(boost::format("Player %d has to answer queries before attempting any further actions (count=%d)!") % (int)player % states.getQueriesCount(player)));
PackageApplied applied; PackageApplied applied;
applied.player = player;
applied.result = false; applied.result = false;
applied.packType = packType; applied.packType = packType;
{ {
@ -651,11 +657,12 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
} }
else if(apply) else if(apply)
{ {
bool result = apply->applyOnGH(this,&c,pack); bool result = apply->applyOnGH(this,&c,pack, player);
tlog5 << "Message successfully applied (result=" << result << ")!\n"; tlog5 << "Message successfully applied (result=" << result << ")!\n";
//send confirmation that we've applied the package //send confirmation that we've applied the package
PackageApplied applied; PackageApplied applied;
applied.player = player;
applied.result = result; applied.result = result;
applied.packType = packType; applied.packType = packType;
{ {
@ -669,6 +676,7 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
} }
delete pack; delete pack;
pack = NULL; pack = NULL;
player = 255;
} }
} }
catch(boost::system::system_error &e) //for boost errors just log, not crash - probably client shut down connection catch(boost::system::system_error &e) //for boost errors just log, not crash - probably client shut down connection
@ -3544,7 +3552,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
} }
//checking if creatures resist //checking if creatures resist
sc.resisted = gs->curB->calculateResistedStacks(spell, caster, secHero, attackedCres, casterColor, mode); sc.resisted = gs->curB->calculateResistedStacks(spell, caster, secHero, attackedCres, casterColor, mode, usedSpellPower, spellLvl);
//calculating dmg to display //calculating dmg to display
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it) for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
@ -3775,7 +3783,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
hi.healedHP = gs->curB->calculateHealedHP(hpGained, spell, *it); hi.healedHP = gs->curB->calculateHealedHP(hpGained, spell, *it);
} }
else else
hi.healedHP = gs->curB->calculateHealedHP(spell, usedSpellPower, stack->getBonus(Selector::typeSubtype(Bonus::SPELLCASTER, spell->id))->additionalInfo, *it); hi.healedHP = gs->curB->calculateHealedHP(spell, usedSpellPower, spellLvl, *it);
} }
else else
hi.healedHP = gs->curB->calculateHealedHP(caster, spell, *it); hi.healedHP = gs->curB->calculateHealedHP(caster, spell, *it);
@ -3809,16 +3817,20 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
} }
BattleStackAdded bsa; BattleStackAdded bsa;
bsa.pos = gs->curB->getAvaliableHex(creID, !(bool)casterSide); //TODO: unify it
bsa.amount = caster->getPrimSkillLevel(2) * VLC->spellh->spells[spellID]->powers[spellLvl] *
(100 + caster->valOfBonuses(Bonus::SPECIFIC_SPELL_DAMAGE, spellID)) / 100.0; //new feature - percentage bonus
bsa.creID = creID; bsa.creID = creID;
bsa.attacker = !(bool)casterSide; bsa.attacker = !(bool)casterSide;
bsa.summoned = true; bsa.summoned = true;
bsa.pos = gs->curB->getAvaliableHex(creID, !(bool)casterSide); //TODO: unify it
//TODO stack casting -> probably power will be zero; set the proper number of creatures manually
int percentBonus = caster ? caster->valOfBonuses(Bonus::SPECIFIC_SPELL_DAMAGE, spellID) : 0;
bsa.amount = usedSpellPower * VLC->spellh->spells[spellID]->powers[spellLvl] *
(100 + percentBonus) / 100.0; //new feature - percentage bonus
if(bsa.amount)
sendAndApply(&bsa); sendAndApply(&bsa);
else
complain("Summoning elementals didn't summon any!");
} }
break; break;
case Spells::REMOVE_OBSTACLE: case Spells::REMOVE_OBSTACLE:
@ -4605,18 +4617,17 @@ bool CGameHandler::dig( const CGHeroInstance *h )
} }
} }
if(h->diggingStatus() != CGHeroInstance::CAN_DIG) //checks for terrain and movement
COMPLAIN_RETF("Hero cannot dig (error code %d)!", h->diggingStatus());
//create a hole
NewObject no; NewObject no;
no.ID = 124; no.ID = 124;
no.pos = h->getPosition(); no.pos = h->getPosition();
no.subID = getTile(no.pos)->tertype; no.subID = getTile(no.pos)->tertype;
if(no.subID >= 8) //no digging on water / rock
{
complain("Cannot dig - wrong terrain type!");
return false;
}
sendAndApply(&no); sendAndApply(&no);
//take MPs
SetMovePoints smp; SetMovePoints smp;
smp.hid = h->id; smp.hid = h->id;
smp.val = 0; smp.val = 0;

View File

@ -59,7 +59,7 @@ public:
void addPlayer(ui8 player); void addPlayer(ui8 player);
PlayerStatus operator[](ui8 player); PlayerStatus operator[](ui8 player);
bool hasQueries(ui8 player); int getQueriesCount(ui8 player); //returns 0 if there is no such player
bool checkFlag(ui8 player, bool PlayerStatus::*flag); bool checkFlag(ui8 player, bool PlayerStatus::*flag);
void setFlag(ui8 player, bool PlayerStatus::*flag, bool val); void setFlag(ui8 player, bool PlayerStatus::*flag, bool val);
void addQuery(ui8 player, ui32 id); void addQuery(ui8 player, ui32 id);

View File

@ -125,7 +125,7 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings> <DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>VCMI_lib.lib;zlib.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>VCMI_lib.lib;zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -151,7 +151,7 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings> <DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>VCMI_lib.lib;zlib.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>VCMI_lib.lib;zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -182,7 +182,7 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings> <DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>VCMI_lib.lib;zlib.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>VCMI_lib.lib;zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -201,6 +201,9 @@
<ClCompile Include="StdInc.cpp"> <ClCompile Include="StdInc.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">StdInc.h</PrecompiledHeaderFile> <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">StdInc.h</PrecompiledHeaderFile>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='RD|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='RD|x64'">Create</PrecompiledHeader>
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>