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 += ")";
DbgBox(message.c_str());
BattleAction bact = m_battleLogic->MakeDecision(stack->ID);
assert(m_cb->battleGetStackByID(bact.stackNumber));
return bact;
return BattleAction::makeDefend(stack);
//
// 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 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 BattleAction activeStack(const CStack * stack);
void battleResultsApplied();

View File

@ -102,6 +102,19 @@ BattleAction CStupidAI::activeStack( const CStack * stack )
std::vector<int> dists = cb->battleGetDistances(stack);
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))
{
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);
}
}

View File

@ -107,7 +107,7 @@
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -124,7 +124,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -143,7 +143,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -160,13 +160,16 @@
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<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 Include="StupidAI.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="StdInc.h" />
<ClInclude Include="StupidAI.h" />
<ClInclude Include="..\..\Global.h" />
<ClInclude Include="..\..\Global.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -58,9 +58,7 @@ void CCallback::selectionMade(int selection, int asker)
{
QueryReply pack(asker,selection);
pack.player = player;
boost::unique_lock<boost::mutex> lock(*cl->serv->wmx);
*cl->serv << &pack;
cl->serv->sendPackToServer(pack, player);
}
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)
cl->waitingRequest.set(typeList.getTypeID(request));
cl->serv->sendPack(*request);
cl->serv->sendPackToServer(*request, player);
if(waitTillRealize)
{

View File

@ -172,7 +172,8 @@ void config::CConfigHandler::init()
const JsonNode config(GameConstants::DATA_DIR + "/config/resolutions.json");
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());
GUIOptions *current = &conf.guiOptions[curRes];
@ -249,6 +250,7 @@ void config::CConfigHandler::init()
cc.screenx = cc.resx;
cc.screeny = cc.resy;
}
cc.autoSkip = false;
cc.oneGoodAI = false;
SetResolution(cc.resx, cc.resy);
}

View File

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

View File

@ -93,6 +93,20 @@ void startGame(StartInfo * options, CConnection *serv = NULL);
#include <getopt.h>
#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()
{
CStopWatch tmh, pomtime;
@ -164,16 +178,17 @@ static void prog_version(void)
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("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("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
printf("\n");
printf("Usage:\n");
printf(" -h, --help display this help and exit\n");
printf(" -v, --version display version information and exit\n");
std::cout << opts;
// 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")
("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")
("oneGoodAI", "puts one default AI and the rest will be GeniusAI")
("autoSkip", "automatically skip turns in GUI")
("nointro,i", "skips intro movies");
po::variables_map vm;
@ -207,7 +226,7 @@ int main(int argc, char** argv)
po::notify(vm);
if(vm.count("help"))
{
prog_help(0);
prog_help(opts);
return 0;
}
if(vm.count("version"))
@ -269,8 +288,15 @@ int main(int argc, char** argv)
if(!vm.count("battle"))
{
//CCS->musich->playMusic(musicBase::mainMenu, -1);
GH.curInt = new CGPreGame; //will set CGP pointer to itself
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
else
startGameFromFile(vm["start"].as<std::string>());
}
else
{
@ -508,6 +534,22 @@ void processCommand(const std::string &message)
{
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
{
PlayerMessage pm(LOCPLINT->playerID,message);

View File

@ -2140,6 +2140,11 @@ CGPath * CPlayerInterface::getAndVerifyPath(const CGHeroInstance * h)
void CPlayerInterface::acceptTurn()
{
if(conf.cc.autoSkip)
{
while(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt()))
iw->close();
}
waitWhileDialog();
if(howManyPeople > 1)
@ -2171,24 +2176,47 @@ void CPlayerInterface::acceptTurn()
adventureInt->select(towns.front());
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)
{
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
CGI->mh->getTerrainDescr(h->getPosition(false), hlp, false);
int msgToShow = -1;
CGHeroInstance::ECanDig isDiggingPossible = h->diggingStatus();
if(hlp.length())
isDiggingPossible = CGHeroInstance::TILE_OCCUPIED; //TODO integrate with canDig
switch(isDiggingPossible)
{
const TerrainTile *t = cb->getTile(h->getPosition());
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.
else
cb->dig(h);
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)

View File

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

View File

@ -121,7 +121,7 @@ void CClient::waitForMoveAndSend(int color)
assert(vstd::contains(battleints, color));
BattleAction ba = battleints[color]->activeStack(gs->curB->getStack(gs->curB->activeStack, false));
MakeAction temp_action(ba);
*serv << &temp_action;
serv->sendPackToServer(temp_action, color);
return;
}HANDLE_EXCEPTION
tlog1 << "We should not be here!" << std::endl;
@ -169,7 +169,7 @@ void CClient::save(const std::string & fname)
}
SaveGame save_game(fname);
*serv << &save_game;
serv->sendPackToServer((CPackForClient&)save_game, getCurrentPlayer());
}
void CClient::endGame( bool closeConnection /*= true*/ )
@ -348,6 +348,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
}
int humanPlayers = 0;
int sensibleAILimit = conf.cc.oneGoodAI ? 1 : GameConstants::PLAYER_LIMIT;
for(std::map<int, PlayerSettings>::iterator it = gs->scenarioOps->playerInfos.begin();
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);
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
{
@ -515,7 +522,7 @@ void CClient::stopConnection()
tlog0 << "Connection has been requested to be closed.\n";
boost::unique_lock<boost::mutex>(*serv->wmx);
CloseServer close_server;
*serv << &close_server;
serv->sendPackToServer(close_server, 255);
tlog0 << "Sent closing signal to the server\n";
}
@ -579,7 +586,7 @@ void CClient::commitPackage( CPackForClient *pack )
CommitPackage cp;
cp.freePack = false;
cp.packToCommit = pack;
*serv << &cp;
serv->sendPackToServer(cp, 255);
}
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)
{
MakeAction ma(BattleAction::makeEndOFTacticPhase(battleInt->playerID));
serv->sendPack(ma);
serv->sendPackToServer(ma, battleInt->playerID);
}
} HANDLE_EXCEPTION
}

View File

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

View File

@ -136,6 +136,8 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<AssemblerOutput>NoListing</AssemblerOutput>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<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>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<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>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<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">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<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 Include="UIFramework\CCursorHandler.cpp" />
<ClCompile Include="UIFramework\CGuiHandler.cpp" />
@ -301,6 +310,7 @@
</ItemGroup>
<ItemGroup>
<None Include="..\ChangeLog" />
<None Include="ClassDiagram21.cd" />
<None Include="vcmi.ico" />
</ItemGroup>
<ItemGroup>

View File

@ -2203,7 +2203,7 @@ ESpellCastProblem::ESpellCastProblem BattleInfo::battleIsImmune(const CGHeroInst
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;
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
|| ( (*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);

View File

@ -135,7 +135,7 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode
TSpell getRandomBeneficialSpell(const CStack * subject) const;
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

View File

@ -210,13 +210,13 @@ ui64 CCreatureSet::getArmyStrength() const
{
ui64 ret = 0;
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;
}
ui64 CCreatureSet::getPower (TSlot slot) const
{
return getCreature(slot)->AIValue * getStackCount(slot);
return getStack(slot).getPower();
}
std::string CCreatureSet::getRoughAmount (TSlot slot) const
{
@ -942,6 +942,12 @@ std::string CStackInstance::getName() const
return (count > 1) ? type->namePl : type->nameSing;
}
ui64 CStackInstance::getPower() const
{
assert(type);
return type->AIValue * count;
}
CStackBasicDescriptor::CStackBasicDescriptor()
{
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 bonusToGraphics(Bonus *bonus) const; //file name of graphics from StackSkills , in future possibly others
ui64 getPower() const;
int getQuantityID() const;
std::string getQuantityTXT(bool capitalized = true) const;
int getExpRank() const;

View File

@ -92,12 +92,6 @@ class DLL_LINKAGE CGlobalAI : public CGameInterface // AI class (to derivate)
{
public:
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;
};

View File

@ -1720,6 +1720,9 @@ int CGameState::getPlayerRelations( ui8 color1, ui8 color2 )
{
if ( color1 == color2 )
return 2;
if(color1 == 255 || color2 == 255) //neutral player has no friends
return 0;
const TeamState * ts = getPlayerTeam(color1);
if (ts && vstd::contains(ts->players, color2))
return 1;
@ -2007,9 +2010,12 @@ bool CGameState::checkForVisitableDir( const int3 & src, const TerrainTile *pom,
int CGameState::victoryCheck( ui8 player ) const
{
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())
return -1;
}
if (p->enteredWinningCheatCode)
{ //cheater or tester, but has entered the code...
@ -2477,6 +2483,11 @@ CGPathNode::CGPathNode()
theNodeBefore = NULL;
}
bool CGPathNode::reachable() const
{
return turns < 255;
}
bool CPathsInfo::getPath( const int3 &dst, CGPath &out )
{
assert(isValid);
@ -2940,7 +2951,8 @@ bool CPathfinder::goodForLandSeaTransition()
return false;
//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;;
useEmbarkCost = 2;

View File

@ -217,7 +217,7 @@ struct CPathNode
bool visited;
};
struct CGPathNode
struct DLL_LINKAGE CGPathNode
{
enum EAccessibility
{
@ -233,7 +233,9 @@ struct CGPathNode
ui32 moveRemains;
CGPathNode * theNodeBefore;
int3 coord; //coordinates
CGPathNode();
bool reachable() const;
};
@ -306,7 +308,7 @@ struct DLL_LINKAGE DuelParameters
class CPathfinder : private CGameInfoCallback
{
public:
private:
bool useSubterraneanGates;
bool allowEmbarkAndDisembark;
CPathsInfo &out;
@ -323,19 +325,18 @@ public:
ui8 useEmbarkCost; //0 - usual movement; 1 - embark; 2 - disembark
int destTopVisObjID;
CPathfinder(CPathsInfo &_out, CGameState *_gs, const CGHeroInstance *_hero);;
CGPathNode *getNode(const int3 &coord);
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
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
}
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()
{
switch(ID)
@ -2392,6 +2411,11 @@ const CArmedInstance * CGTownInstance::getUpperArmy() const
return this;
}
bool CGTownInstance::hasBuilt(int buildingID) const
{
return vstd::contains(builtBuildings, buildingID);
}
void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const
{
if(visitors.find(h->id)==visitors.end())

View File

@ -123,11 +123,11 @@ public:
class DLL_LINKAGE IMarket
{
virtual int getMarketEfficiency() const =0;
public:
const CGObjectInstance *o;
IMarket(const CGObjectInstance *O);
virtual int getMarketEfficiency() const =0;
virtual bool allowsTrade(EMarketMode::EMarketMode mode) const;
virtual int availableUnits(EMarketMode::EMarketMode mode, int marketItemSerial) const; //-1 if unlimited
virtual std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const;
@ -256,6 +256,10 @@ public:
SCHOLAR, TACTICS, ARTILLERY, LEARNING, OFFENCE, ARMORER, INTELLIGENCE, SORCERY, RESISTANCE,
FIRST_AID
};
enum ECanDig
{
CAN_DIG, LACK_OF_MOVEMENT, WRONG_TERRAIN, TILE_OCCUPIED
};
//////////////////////////////////////////////////////////////////////////
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
CStackBasicDescriptor calculateNecromancy (const BattleResult &battleResult) 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;
bool hasFort() const;
bool hasCapitol() const;
bool hasBuilt(int buildingID) const;
int dailyIncome() const; //calculates daily income of this town
int spellsAtLevel(int level, bool checkGuild) const; //levels are counted from 1 (1 - 5)
void removeCapitols (ui8 owner) const;

View File

@ -240,10 +240,11 @@ CPack * CConnection::retreivePack()
return ret;
}
void CConnection::sendPack(const CPack &pack)
void CConnection::sendPackToServer(const CPack &pack, ui8 player)
{
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 )

View File

@ -916,7 +916,7 @@ public:
~CConnection(void);
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);

View File

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

View File

@ -190,6 +190,7 @@ public:
const CMapHeader * getMapHeader()const;
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;
bool isInTheMap(const int3 &pos) const;
//town
const CGTownInstance* getTown(int objid) const;

View File

@ -60,12 +60,14 @@ struct CPackForClient : public CPack
struct CPackForServer : public CPack
{
ui8 player;
CConnection *c;
CGameState* GS(CGameHandler *gh);
CPackForServer()
{
type = 2;
c = NULL;
player = 255;
};
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
ui32 packType; //type id of applied package
ui8 player;
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 )
{
CGHeroInstance *h = gs->getHero(id);
//bonus system
h->detachFrom(&gs->globalEffects);
h->attachTo(gs->getPlayer(player));
gs->map->removeBlockVisTiles(h,true);
h->setOwner(player);
h->movement = h->maxMovePoints(true);

View File

@ -78,6 +78,14 @@ namespace Res
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]
// 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)

View File

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

View File

@ -2222,3 +2222,8 @@ bool TerrainTile::hasFavourableWinds() const
{
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)
int topVisitableID() const; //returns ID of the top visitable ovject or -1 if there is none
bool isWater() const;
bool isCoastal() 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(txt) {complain(txt); return false;}
#define COMPLAIN_RETF(txt, FORMAT) {complain(boost::str(boost::format(txt) % FORMAT)); return false;}
#define NEW_ROUND BattleNextRound bnr;\
bnr.round = gs->curB->round + 1;\
sendAndApply(&bnr);
@ -67,7 +68,7 @@ template <typename T> class CApplyOnGH;
class CBaseForGHApply
{
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(){}
template<typename U> static CBaseForGHApply *getApplier(const U * t=NULL)
{
@ -78,10 +79,11 @@ public:
template <typename T> class CApplyOnGH : public CBaseForGHApply
{
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);
ptr->c = c;
ptr->player = player;
return ptr->applyGh(gh);
}
};
@ -121,7 +123,8 @@ void PlayerStatuses::addPlayer(ui8 player)
boost::unique_lock<boost::mutex> l(mx);
players[player];
}
bool PlayerStatuses::hasQueries(ui8 player)
int PlayerStatuses::getQueriesCount(ui8 player)
{
boost::unique_lock<boost::mutex> l(mx);
if(players.find(player) != players.end())
@ -130,9 +133,10 @@ bool PlayerStatuses::hasQueries(ui8 player)
}
else
{
throw std::string("No such player!");
return 0;
}
}
bool PlayerStatuses::checkFlag(ui8 player, bool PlayerStatus::*flag)
{
boost::unique_lock<boost::mutex> l(mx);
@ -624,24 +628,26 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
setThreadName(-1, "CGameHandler::handleConnection");
srand(time(NULL));
CPack *pack = NULL;
ui8 player = 255;
try
{
while(1)//server should never shut connection first //was: while(!end2)
{
{
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;
}
int packType = typeList.getTypeID(pack); //get the id of type
CBaseForGHApply *apply = applier->apps[packType]; //and appropriae applier object
if(packType != typeList.getTypeID<QueryReply>() &&
(packType != typeList.getTypeID<ArrangeStacks>() || !isAllowedArrangePack((ArrangeStacks*)pack)) && // for dialogs like garrison
states[getCurrentPlayer()].queries.size())
if(packType != typeList.getTypeID<QueryReply>()
&& (packType != typeList.getTypeID<ArrangeStacks>() || !isAllowedArrangePack((ArrangeStacks*)pack)) // for dialogs like garrison
&& 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;
applied.player = player;
applied.result = false;
applied.packType = packType;
{
@ -651,11 +657,12 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
}
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";
//send confirmation that we've applied the package
PackageApplied applied;
applied.player = player;
applied.result = result;
applied.packType = packType;
{
@ -669,6 +676,7 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
}
delete pack;
pack = NULL;
player = 255;
}
}
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
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
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);
}
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
hi.healedHP = gs->curB->calculateHealedHP(caster, spell, *it);
@ -3809,16 +3817,20 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
}
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.attacker = !(bool)casterSide;
bsa.summoned = true;
sendAndApply(&bsa);
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);
else
complain("Summoning elementals didn't summon any!");
}
break;
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;
no.ID = 124;
no.pos = h->getPosition();
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);
//take MPs
SetMovePoints smp;
smp.hid = h->id;
smp.val = 0;

View File

@ -59,7 +59,7 @@ public:
void addPlayer(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);
void setFlag(ui8 player, bool PlayerStatus::*flag, bool val);
void addQuery(ui8 player, ui32 id);

View File

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