1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Added VCAI and EmptyAI to the VS solution. Removed from it GeniusAI.

Fixed #329, #884, #885.
This commit is contained in:
Michał W. Urbańczyk 2012-02-29 01:31:48 +00:00
parent 9ce3c78387
commit f2642cb62c
9 changed files with 262 additions and 68 deletions

177
AI/EmptyAI/EmptyAI.vcxproj Normal file
View File

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="RD|Win32">
<Configuration>RD</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="RD|x64">
<Configuration>RD</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="CEmptyAI.cpp" />
<ClCompile Include="exp_funcs.cpp" />
<ClCompile Include="StdInc.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<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>
<ClInclude Include="CEmptyAI.h" />
<ClInclude Include="StdInc.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}</ProjectGuid>
<RootNamespace>EmptyAI</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\VCMI_global.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\VCMI_global.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\VCMI_global.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='RD|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\VCMI_global.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(SolutionDir)\AI\</OutDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)\AI\</OutDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'">
<OutDir>$(SolutionDir)$(Configuration)\bin\AI\</OutDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|x64'">
<OutDir>$(SolutionDir)$(Configuration)\bin\AI\</OutDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
<PreprocessorDefinitions>VCMI_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>$(OutDir)EmptyAI.dll</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
<PreprocessorDefinitions>VCMI_DLL;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>$(OutDir)EmptyAI.dll</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
<PreprocessorDefinitions>VCMI_DLL;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>$(OutDir)EmptyAI.dll</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RD|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
<PreprocessorDefinitions>VCMI_DLL;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>$(OutDir)EmptyAI.dll</OutputFile>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -464,13 +464,15 @@ void VCAI::gameOver(ui8 player, bool victory)
tlog0 << "VCAI: Player " << (int)player << " lost. It's me. What a disappointment! :(\n"; tlog0 << "VCAI: Player " << (int)player << " lost. It's me. What a disappointment! :(\n";
} }
//let's make Impossible difficulty finally standing to its name :> // //let's make Impossible difficulty finally standing to its name :>
if(myCb->getStartInfo()->difficulty == 4 && !victory) // if(myCb->getStartInfo()->difficulty == 4 && !victory)
{ // {
//play dirty: crash the whole engine to avoid lose // //play dirty: crash the whole engine to avoid lose
//that way AI is unbeatable! // //that way AI is unbeatable!
*(int*)NULL = 666; // *(int*)NULL = 666;
} // }
// TODO - at least write some insults on stdout
finish(); finish();
} }

View File

@ -7,8 +7,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VCMI_lib", "lib\VCMI_lib.vc
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VCMI_server", "server\VCMI_server.vcxproj", "{8AF697C3-465E-4910-B31B-576A9ECDB309}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VCMI_server", "server\VCMI_server.vcxproj", "{8AF697C3-465E-4910-B31B-576A9ECDB309}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "genius", "AI\GeniusAI\genius.vcxproj", "{B6A14ED9-E7C1-411B-A596-2FE90B3145B4}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StupidAI", "AI\StupidAI\StupidAI.vcxproj", "{15DABC90-234A-4B6B-9EEB-777C4768B82B}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StupidAI", "AI\StupidAI\StupidAI.vcxproj", "{15DABC90-234A-4B6B-9EEB-777C4768B82B}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
{B952FFC5-3039-4DE1-9F08-90ACDA483D8F} = {B952FFC5-3039-4DE1-9F08-90ACDA483D8F} {B952FFC5-3039-4DE1-9F08-90ACDA483D8F} = {B952FFC5-3039-4DE1-9F08-90ACDA483D8F}
@ -19,6 +17,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ERM", "Scripting\ERM\ERM.vc
{B952FFC5-3039-4DE1-9F08-90ACDA483D8F} = {B952FFC5-3039-4DE1-9F08-90ACDA483D8F} {B952FFC5-3039-4DE1-9F08-90ACDA483D8F} = {B952FFC5-3039-4DE1-9F08-90ACDA483D8F}
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VCAI", "AI\VCAI\VCAI.vcxproj", "{276C3DB0-7A6B-4417-8E5C-322B08633AAC}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32 Debug|Win32 = Debug|Win32
@ -51,14 +51,6 @@ Global
{8AF697C3-465E-4910-B31B-576A9ECDB309}.RD|Win32.Build.0 = RD|Win32 {8AF697C3-465E-4910-B31B-576A9ECDB309}.RD|Win32.Build.0 = RD|Win32
{8AF697C3-465E-4910-B31B-576A9ECDB309}.RD|x64.ActiveCfg = RD|x64 {8AF697C3-465E-4910-B31B-576A9ECDB309}.RD|x64.ActiveCfg = RD|x64
{8AF697C3-465E-4910-B31B-576A9ECDB309}.RD|x64.Build.0 = RD|x64 {8AF697C3-465E-4910-B31B-576A9ECDB309}.RD|x64.Build.0 = RD|x64
{B6A14ED9-E7C1-411B-A596-2FE90B3145B4}.Debug|Win32.ActiveCfg = Debug|Win32
{B6A14ED9-E7C1-411B-A596-2FE90B3145B4}.Debug|Win32.Build.0 = Debug|Win32
{B6A14ED9-E7C1-411B-A596-2FE90B3145B4}.Debug|x64.ActiveCfg = Debug|x64
{B6A14ED9-E7C1-411B-A596-2FE90B3145B4}.Debug|x64.Build.0 = Debug|x64
{B6A14ED9-E7C1-411B-A596-2FE90B3145B4}.RD|Win32.ActiveCfg = RD|Win32
{B6A14ED9-E7C1-411B-A596-2FE90B3145B4}.RD|Win32.Build.0 = RD|Win32
{B6A14ED9-E7C1-411B-A596-2FE90B3145B4}.RD|x64.ActiveCfg = RD|x64
{B6A14ED9-E7C1-411B-A596-2FE90B3145B4}.RD|x64.Build.0 = RD|x64
{15DABC90-234A-4B6B-9EEB-777C4768B82B}.Debug|Win32.ActiveCfg = Debug|Win32 {15DABC90-234A-4B6B-9EEB-777C4768B82B}.Debug|Win32.ActiveCfg = Debug|Win32
{15DABC90-234A-4B6B-9EEB-777C4768B82B}.Debug|Win32.Build.0 = Debug|Win32 {15DABC90-234A-4B6B-9EEB-777C4768B82B}.Debug|Win32.Build.0 = Debug|Win32
{15DABC90-234A-4B6B-9EEB-777C4768B82B}.Debug|x64.ActiveCfg = Debug|x64 {15DABC90-234A-4B6B-9EEB-777C4768B82B}.Debug|x64.ActiveCfg = Debug|x64
@ -75,6 +67,12 @@ Global
{8F202F43-106D-4F63-AD9D-B1D43E803E8C}.RD|Win32.Build.0 = RD|Win32 {8F202F43-106D-4F63-AD9D-B1D43E803E8C}.RD|Win32.Build.0 = RD|Win32
{8F202F43-106D-4F63-AD9D-B1D43E803E8C}.RD|x64.ActiveCfg = RD|x64 {8F202F43-106D-4F63-AD9D-B1D43E803E8C}.RD|x64.ActiveCfg = RD|x64
{8F202F43-106D-4F63-AD9D-B1D43E803E8C}.RD|x64.Build.0 = RD|x64 {8F202F43-106D-4F63-AD9D-B1D43E803E8C}.RD|x64.Build.0 = RD|x64
{276C3DB0-7A6B-4417-8E5C-322B08633AAC}.Debug|Win32.ActiveCfg = Debug|Win32
{276C3DB0-7A6B-4417-8E5C-322B08633AAC}.Debug|Win32.Build.0 = Debug|Win32
{276C3DB0-7A6B-4417-8E5C-322B08633AAC}.Debug|x64.ActiveCfg = Debug|Win32
{276C3DB0-7A6B-4417-8E5C-322B08633AAC}.RD|Win32.ActiveCfg = RD|Win32
{276C3DB0-7A6B-4417-8E5C-322B08633AAC}.RD|Win32.Build.0 = RD|Win32
{276C3DB0-7A6B-4417-8E5C-322B08633AAC}.RD|x64.ActiveCfg = RD|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -189,7 +189,7 @@ int main(int argc, char** argv)
("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") ("start", po::value<std::string>(), "starts game from saved StartInfo file")
("onlyAI", "runs without GUI, all players will be default AI") ("onlyAI", "runs without GUI, all players will be default AI")
("oneGoodAI", "puts one default AI and the rest will be GeniusAI") ("oneGoodAI", "puts one default AI and the rest will be EmptyAI")
("autoSkip", "automatically skip turns in GUI") ("autoSkip", "automatically skip turns in GUI")
("nointro,i", "skips intro movies"); ("nointro,i", "skips intro movies");

View File

@ -2582,11 +2582,9 @@ bool mapSorter::operator()(const CMapInfo *aaa, const CMapInfo *bbb)
return (a->victoryCondition.condition < b->victoryCondition.condition); return (a->victoryCondition.condition < b->victoryCondition.condition);
break; break;
case _name: //by name case _name: //by name
return (a->name<b->name); return boost::ilexicographical_compare(a->name, b->name);
break;
default: default:
return (a->name<b->name); return boost::ilexicographical_compare(a->name, b->name);
break;
} }
} }
else //if we are sorting campaigns else //if we are sorting campaigns
@ -2598,11 +2596,9 @@ bool mapSorter::operator()(const CMapInfo *aaa, const CMapInfo *bbb)
CGI->generaltexth->campaignRegionNames[ bbb->campaignHeader->mapVersion ].size(); CGI->generaltexth->campaignRegionNames[ bbb->campaignHeader->mapVersion ].size();
break; break;
case _name: //by name case _name: //by name
return aaa->campaignHeader->name < bbb->campaignHeader->name; return boost::ilexicographical_compare(aaa->campaignHeader->name, bbb->campaignHeader->name);
break;
default: default:
return aaa->campaignHeader->name < bbb->campaignHeader->name; return boost::ilexicographical_compare(aaa->campaignHeader->name, bbb->campaignHeader->name);
break;
} }
} }
} }

View File

@ -372,7 +372,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
{ {
std::string AItoGive = settings["server"]["playerAI"].String(); std::string AItoGive = settings["server"]["playerAI"].String();
if(!sensibleAILimit) if(!sensibleAILimit)
AItoGive = "GeniusAI"; AItoGive = "EmptyAI";
else else
sensibleAILimit--; sensibleAILimit--;
playerint[color] = static_cast<CGameInterface*>(CDynLibHandler::getNewAI(AItoGive)); playerint[color] = static_cast<CGameInterface*>(CDynLibHandler::getNewAI(AItoGive));

View File

@ -933,15 +933,16 @@ int BattleInfo::calculateSpellDuration( const CSpell * spell, const CGHeroInstan
} }
switch(spell->id) switch(spell->id)
{ {
case 56: //frenzy case Spells::FRENZY:
return 1; return 1;
default: //other spells default: //other spells
return caster->getPrimSkillLevel(2) + caster->valOfBonuses(Bonus::SPELL_DURATION); return caster->getPrimSkillLevel(PrimarySkill::SPELL_POWER) + caster->valOfBonuses(Bonus::SPELL_DURATION);
} }
} }
CStack * BattleInfo::generateNewStack(const CStackInstance &base, int stackID, bool attackerOwned, int slot, BattleHex position) const CStack * BattleInfo::generateNewStack(const CStackInstance &base, bool attackerOwned, int slot, BattleHex position) const
{ {
int stackID = getIdForNewStack();
int owner = attackerOwned ? sides[0] : sides[1]; int owner = attackerOwned ? sides[0] : sides[1];
assert((owner >= GameConstants::PLAYER_LIMIT) || assert((owner >= GameConstants::PLAYER_LIMIT) ||
(base.armyObj && base.armyObj->tempOwner == owner)); (base.armyObj && base.armyObj->tempOwner == owner));
@ -950,8 +951,9 @@ CStack * BattleInfo::generateNewStack(const CStackInstance &base, int stackID, b
ret->position = position; ret->position = position;
return ret; return ret;
} }
CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor &base, int stackID, bool attackerOwned, int slot, BattleHex position) const CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor &base, bool attackerOwned, int slot, BattleHex position) const
{ {
int stackID = getIdForNewStack();
int owner = attackerOwned ? sides[0] : sides[1]; int owner = attackerOwned ? sides[0] : sides[1];
CStack * ret = new CStack(&base, owner, stackID, attackerOwned, slot); CStack * ret = new CStack(&base, owner, stackID, attackerOwned, slot);
ret->position = position; ret->position = position;
@ -1425,25 +1427,28 @@ void BattleInfo::localInit()
b->attachTo(this); b->attachTo(this);
BOOST_FOREACH(CStack *s, stacks) BOOST_FOREACH(CStack *s, stacks)
{ localInitStack(s);
s->exportBonuses();
if(s->base) //stack originating from "real" stack in garrison -> attach to it
{
s->attachTo(const_cast<CStackInstance*>(s->base));
}
else //attach directly to obj to which stack belongs and creature type
{
CArmedInstance *army = belligerents[!s->attackerOwned];
s->attachTo(army);
assert(s->type);
s->attachTo(const_cast<CCreature*>(s->type));
}
s->postInit();
}
exportBonuses(); exportBonuses();
} }
void BattleInfo::localInitStack(CStack * s)
{
s->exportBonuses();
if(s->base) //stack originating from "real" stack in garrison -> attach to it
{
s->attachTo(const_cast<CStackInstance*>(s->base));
}
else //attach directly to obj to which stack belongs and creature type
{
CArmedInstance *army = belligerents[!s->attackerOwned];
s->attachTo(army);
assert(s->type);
s->attachTo(const_cast<CCreature*>(s->type));
}
s->postInit();
}
namespace CGH namespace CGH
{ {
using namespace std; using namespace std;
@ -1519,7 +1524,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const
else else
pos = attackerLoose[armies[0]->stacksCount()-1][k]; pos = attackerLoose[armies[0]->stacksCount()-1][k];
CStack * stack = curB->generateNewStack(*i->second, stacks.size(), true, i->first, pos); CStack * stack = curB->generateNewStack(*i->second, true, i->first, pos);
stacks.push_back(stack); stacks.push_back(stack);
} }
@ -1534,7 +1539,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const
else else
pos = defenderLoose[armies[1]->stacksCount()-1][k]; pos = defenderLoose[armies[1]->stacksCount()-1][k];
CStack * stack = curB->generateNewStack(*i->second, stacks.size(), false, i->first, pos); CStack * stack = curB->generateNewStack(*i->second, false, i->first, pos);
stacks.push_back(stack); stacks.push_back(stack);
} }
@ -1559,17 +1564,17 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const
{ {
if(heroes[0]->getArt(13)) //ballista if(heroes[0]->getArt(13)) //ballista
{ {
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(146, 1), stacks.size(), true, 255, 52); CStack * stack = curB->generateNewStack(CStackBasicDescriptor(146, 1), true, 255, 52);
stacks.push_back(stack); stacks.push_back(stack);
} }
if(heroes[0]->getArt(14)) //ammo cart if(heroes[0]->getArt(14)) //ammo cart
{ {
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(148, 1), stacks.size(), true, 255, 18); CStack * stack = curB->generateNewStack(CStackBasicDescriptor(148, 1), true, 255, 18);
stacks.push_back(stack); stacks.push_back(stack);
} }
if(heroes[0]->getArt(15)) //first aid tent if(heroes[0]->getArt(15)) //first aid tent
{ {
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(147, 1), stacks.size(), true, 255, 154); CStack * stack = curB->generateNewStack(CStackBasicDescriptor(147, 1), true, 255, 154);
stacks.push_back(stack); stacks.push_back(stack);
} }
} }
@ -1578,23 +1583,23 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const
//defending hero shouldn't receive ballista (bug #551) //defending hero shouldn't receive ballista (bug #551)
if(heroes[1]->getArt(13) && !town) //ballista if(heroes[1]->getArt(13) && !town) //ballista
{ {
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(146, 1), stacks.size(), false, 255, 66); CStack * stack = curB->generateNewStack(CStackBasicDescriptor(146, 1), false, 255, 66);
stacks.push_back(stack); stacks.push_back(stack);
} }
if(heroes[1]->getArt(14)) //ammo cart if(heroes[1]->getArt(14)) //ammo cart
{ {
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(148, 1), stacks.size(), false, 255, 32); CStack * stack = curB->generateNewStack(CStackBasicDescriptor(148, 1), false, 255, 32);
stacks.push_back(stack); stacks.push_back(stack);
} }
if(heroes[1]->getArt(15)) //first aid tent if(heroes[1]->getArt(15)) //first aid tent
{ {
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(147, 1), stacks.size(), false, 255, 168); CStack * stack = curB->generateNewStack(CStackBasicDescriptor(147, 1), false, 255, 168);
stacks.push_back(stack); stacks.push_back(stack);
} }
} }
if(town && heroes[0] && town->hasFort()) //catapult if(town && heroes[0] && town->hasFort()) //catapult
{ {
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(145, 1), stacks.size(), true, 255, 120); CStack * stack = curB->generateNewStack(CStackBasicDescriptor(145, 1), true, 255, 120);
stacks.push_back(stack); stacks.push_back(stack);
} }
} }
@ -1603,15 +1608,15 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const
if (curB->siege == 2 || curB->siege == 3) if (curB->siege == 2 || curB->siege == 3)
{ {
// keep tower // keep tower
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(149, 1), stacks.size(), false, 255, -2); CStack * stack = curB->generateNewStack(CStackBasicDescriptor(149, 1), false, 255, -2);
stacks.push_back(stack); stacks.push_back(stack);
if (curB->siege == 3) if (curB->siege == 3)
{ {
// lower tower + upper tower // lower tower + upper tower
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(149, 1), stacks.size(), false, 255, -4); CStack * stack = curB->generateNewStack(CStackBasicDescriptor(149, 1), false, 255, -4);
stacks.push_back(stack); stacks.push_back(stack);
stack = curB->generateNewStack(CStackBasicDescriptor(149, 1), stacks.size(), false, 255, -3); stack = curB->generateNewStack(CStackBasicDescriptor(149, 1), false, 255, -3);
stacks.push_back(stack); stacks.push_back(stack);
} }
} }
@ -2302,6 +2307,20 @@ ui8 BattleInfo::whatSide(int player) const
return -1; return -1;
} }
int BattleInfo::getIdForNewStack() const
{
if(stacks.size())
{
//stacks vector may be sorted not by ID and they may be not contiguous -> find stack with max ID
auto highestIDStack = *std::max_element(stacks.begin(), stacks.end(),
[](const CStack *a, const CStack *b) { return a->ID < b->ID; });
return highestIDStack->ID + 1;
}
return 0;
}
CStack::CStack(const CStackInstance *Base, int O, int I, bool AO, int S) CStack::CStack(const CStackInstance *Base, int O, int I, bool AO, int S)
: base(Base), ID(I), owner(O), slot(S), attackerOwned(AO), : base(Base), ID(I), owner(O), slot(S), attackerOwned(AO),
counterAttacks(1) counterAttacks(1)

View File

@ -108,8 +108,9 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode
std::set<BattleHex> getAttackedHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID); //calculates range of multi-hex attacks std::set<BattleHex> getAttackedHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID); //calculates range of multi-hex attacks
std::set<CStack*> getAdjacentCreatures (const CStack * stack) const; std::set<CStack*> getAdjacentCreatures (const CStack * stack) const;
static int calculateSpellDuration(const CSpell * spell, const CGHeroInstance * caster, int usedSpellPower); static int calculateSpellDuration(const CSpell * spell, const CGHeroInstance * caster, int usedSpellPower);
CStack * generateNewStack(const CStackInstance &base, int stackID, bool attackerOwned, int slot, BattleHex position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield CStack * generateNewStack(const CStackInstance &base, bool attackerOwned, int slot, BattleHex position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
CStack * generateNewStack(const CStackBasicDescriptor &base, int stackID, bool attackerOwned, int slot, BattleHex position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield CStack * generateNewStack(const CStackBasicDescriptor &base, bool attackerOwned, int slot, BattleHex position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
int getIdForNewStack() const; //suggest a currently unused ID that'd suitable for generating a new stack
ui32 getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell ui32 getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell
int hexToWallPart(BattleHex hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found int hexToWallPart(BattleHex hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
int lineToWallHex(int line) const; //returns hex with wall in given line int lineToWallHex(int line) const; //returns hex with wall in given line
@ -143,6 +144,8 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode
const CGHeroInstance * battleGetOwner(const CStack * stack) const; //returns hero that owns given stack; NULL if none const CGHeroInstance * battleGetOwner(const CStack * stack) const; //returns hero that owns given stack; NULL if none
si8 battleMinSpellLevel() const; //calculates minimum spell level possible to be cast on battlefield - takes into account artifacts of both heroes; if no effects are set, 0 is returned si8 battleMinSpellLevel() const; //calculates minimum spell level possible to be cast on battlefield - takes into account artifacts of both heroes; if no effects are set, 0 is returned
void localInit(); void localInit();
void localInitStack(CStack * s);
static BattleInfo * setupBattle( int3 tile, int terrain, int terType, const CArmedInstance *armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance *town ); static BattleInfo * setupBattle( int3 tile, int terrain, int terType, const CArmedInstance *armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance *town );
bool isInTacticRange( BattleHex dest ) const; bool isInTacticRange( BattleHex dest ) const;
int getSurrenderingCost(int player) const; int getSurrenderingCost(int player) const;

View File

@ -1288,15 +1288,14 @@ DLL_LINKAGE void BattleStackAdded::applyGs(CGameState *gs)
tlog2 << "No place found for new stack!\n"; tlog2 << "No place found for new stack!\n";
return; return;
} }
CStackInstance *csi = new CStackInstance(creID, amount);
csi->setArmyObj(gs->curB->belligerents[attacker ? 0 : 1]); CStackBasicDescriptor csbd(creID, amount);
int newStackID = gs->curB->stacks.size() ? gs->curB->stacks.back()->ID+1 : 0; //stacks IDs may not be contiguous, so we need to give after-last ID CStack * addedStack = gs->curB->generateNewStack(csbd, attacker, 255, pos); //TODO: netpacks?
CStack * summonedStack = gs->curB->generateNewStack(*csi, newStackID, attacker, 255, pos); //TODO: netpacks?
if (summoned) if (summoned)
summonedStack->state.insert(EBattleStackState::SUMMONED); addedStack->state.insert(EBattleStackState::SUMMONED);
summonedStack->attachTo(csi);
summonedStack->postInit(); gs->curB->localInitStack(addedStack);
gs->curB->stacks.push_back(summonedStack); //the stack is not "SUMMONED", it is permanent gs->curB->stacks.push_back(addedStack); //the stack is not "SUMMONED", it is permanent
} }
DLL_LINKAGE void BattleSetStackProperty::applyGs(CGameState *gs) DLL_LINKAGE void BattleSetStackProperty::applyGs(CGameState *gs)