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:
parent
91c0ce33f4
commit
046e54563c
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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">
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -503,4 +503,5 @@ public:
|
||||
void openCampaignScreen(std::string name);
|
||||
};
|
||||
|
||||
extern ISelectionScreenInfo *SEL;
|
||||
extern CGPreGame *CGP;
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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) );
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
||||
|
@ -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())
|
||||
|
@ -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;
|
||||
|
@ -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 )
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -189,7 +189,8 @@ public:
|
||||
int3 guardingCreaturePosition (int3 pos) 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
|
||||
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
|
||||
const CGTownInstance* getTown(int objid) const;
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -2222,3 +2222,8 @@ bool TerrainTile::hasFavourableWinds() const
|
||||
{
|
||||
return siodmyTajemniczyBajt & 128;
|
||||
}
|
||||
|
||||
bool TerrainTile::isWater() const
|
||||
{
|
||||
return tertype == water;
|
||||
}
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user