1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-04-09 07:13:54 +02:00

Merge pull request #2070 from rilian-la-te/make-tests-compile-pass-h3

vcmi: fix test compiling and passing
This commit is contained in:
Ivan Savenko 2023-04-28 22:18:00 +03:00 committed by GitHub
commit 3dde827a9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
62 changed files with 1570 additions and 1357 deletions

View File

@ -71,11 +71,11 @@ jobs:
- platform: linux-qt6
os: ubuntu-22.04
test: 0
preset: linux-clang-release
preset: linux-clang-test
- platform: linux
os: ubuntu-20.04
test: 0
preset: linux-gcc-release
preset: linux-gcc-test
- platform: mac-intel
os: macos-12
test: 0

1
.gitmodules vendored
View File

@ -1,6 +1,7 @@
[submodule "test/googletest"]
path = test/googletest
url = https://github.com/google/googletest
branch = v1.13.x
[submodule "AI/FuzzyLite"]
path = AI/FuzzyLite
url = https://github.com/fuzzylite/fuzzylite.git

@ -1 +1 @@
Subproject commit 9751a751a17c0682ed5d02e583c6a0cda8bc88e5
Subproject commit 7aee562d6ca17f3cf42588ffb5116e03017c3c50

View File

@ -45,6 +45,15 @@
"CMAKE_INSTALL_PREFIX" : "/usr/local"
}
},
{
"name": "linux-test",
"inherits": "linux-release",
"hidden": true,
"cacheVariables": {
"ENABLE_TEST": "ON",
"ENABLE_LUA": "ON"
}
},
{
"name": "linux-clang-release",
"displayName": "Clang x86_64-pc-linux-gnu",
@ -67,6 +76,28 @@
"CMAKE_CXX_COMPILER": "/usr/bin/g++"
}
},
{
"name": "linux-clang-test",
"displayName": "Clang x86_64-pc-linux-gnu with unit testing",
"description": "VCMI Linux Clang",
"inherits": "linux-test",
"cacheVariables": {
"CMAKE_C_COMPILER": "/usr/bin/clang",
"CMAKE_CXX_COMPILER": "/usr/bin/clang++"
}
},
{
"name": "linux-gcc-test",
"displayName": "GCC x86_64-pc-linux-gnu with unit testing",
"description": "VCMI Linux GCC",
"inherits": "linux-test",
"cacheVariables": {
"ENABLE_LUA" : "OFF",
"ENABLE_PCH" : "OFF",
"CMAKE_C_COMPILER": "/usr/bin/gcc",
"CMAKE_CXX_COMPILER": "/usr/bin/g++"
}
},
{
"name": "windows-msvc-release",
"displayName": "Windows x64 RelWithDebInfo",
@ -213,6 +244,16 @@
"configurePreset": "linux-clang-release",
"inherits": "default-release"
},
{
"name": "linux-clang-test",
"configurePreset": "linux-clang-test",
"inherits": "default-release"
},
{
"name": "linux-gcc-test",
"configurePreset": "linux-gcc-test",
"inherits": "default-release"
},
{
"name": "linux-gcc-release",
"configurePreset": "linux-gcc-release",
@ -295,6 +336,16 @@
"configurePreset": "linux-gcc-release",
"inherits": "default-release"
},
{
"name": "linux-clang-test",
"configurePreset": "linux-clang-test",
"inherits": "default-release"
},
{
"name": "linux-gcc-test",
"configurePreset": "linux-gcc-test",
"inherits": "default-release"
},
{
"name": "macos-xcode-release",
"configurePreset": "macos-xcode-release",

View File

@ -47,8 +47,6 @@ class DLL_LINKAGE CCreature : public Creature, public CBonusSystemNode
bool doubleWide = false;
si32 iconIndex = -1; // index of icon in files like twcrport
TResources cost; //cost[res_id] - amount of that resource required to buy creature from dwelling
public:
@ -61,6 +59,7 @@ public:
std::string animDefName; // creature animation used during battles
std::string advMapDef; //for new creatures only, image for adventure map
si32 iconIndex = -1; // index of icon in files like twcrport, used in tests now.
/// names of files with appropriate icons. Used only during loading
std::string smallIconName;
std::string largeIconName;

View File

@ -722,7 +722,7 @@ void CGameState::preInit(Services * services)
this->services = services;
}
void CGameState::init(const CMapService * mapService, StartInfo * si, bool allowSavingRandomMap)
void CGameState::init(const IMapService * mapService, StartInfo * si, bool allowSavingRandomMap)
{
preInitAuto();
logGlobal->info("\tUsing random seed: %d", si->seedToBeUsed);
@ -851,7 +851,7 @@ void CGameState::preInitAuto()
}
}
void CGameState::initNewGame(const CMapService * mapService, bool allowSavingRandomMap)
void CGameState::initNewGame(const IMapService * mapService, bool allowSavingRandomMap)
{
if(scenarioOps->createRandomMap())
{

View File

@ -57,7 +57,7 @@ class CQuest;
class CCampaignScenario;
struct EventCondition;
class CScenarioTravel;
class CMapService;
class IMapService;
template<typename T> class CApplier;
@ -161,7 +161,7 @@ public:
void preInit(Services * services);
void init(const CMapService * mapService, StartInfo * si, bool allowSavingRandomMap = false);
void init(const IMapService * mapService, StartInfo * si, bool allowSavingRandomMap = false);
void updateOnLoad(StartInfo * si);
ConstTransitivePtr<StartInfo> scenarioOps, initialOpts; //second one is a copy of settings received from pregame (not randomized)
@ -252,7 +252,7 @@ private:
// ----- initialization -----
void preInitAuto();
void initNewGame(const CMapService * mapService, bool allowSavingRandomMap);
void initNewGame(const IMapService * mapService, bool allowSavingRandomMap);
void initCampaign();
void checkMapChecksum();
void initGlobalBonuses();

View File

@ -768,7 +768,6 @@ void CGMine::serializeJsonOptions(JsonSerializeFormat & handler)
{
auto guard = handler.enterArray("possibleResources");
const JsonNode & node = handler.getCurrent();
std::set<int> abandonedMineResources;
auto names = node.convertTo<std::vector<std::string>>();
@ -778,7 +777,7 @@ void CGMine::serializeJsonOptions(JsonSerializeFormat & handler)
if(raw_res < 0)
logGlobal->error("Invalid resource name: %s", s);
else
abandonedMineResources.insert(raw_res);
abandonedMineResources.emplace(raw_res);
}
}
}

View File

@ -24,57 +24,67 @@ class IMapPatcher;
class ModCompatibilityInfo;
/**
* The map service provides loading and saving of VCMI/H3 map files.
* The map service provides loading of VCMI/H3 map files. It can
* be extended to save maps later as well.
*/
class DLL_LINKAGE CMapService
class DLL_LINKAGE IMapService
{
public:
CMapService() = default;
virtual ~CMapService() = default;
IMapService() = default;
virtual ~IMapService() = default;
/**
* Loads the VCMI/H3 map file specified by the name.
*
* @param name the name of the map
* @return a unique ptr to the loaded map class
*/
std::unique_ptr<CMap> loadMap(const ResourceID & name) const;
virtual std::unique_ptr<CMap> loadMap(const ResourceID & name) const = 0;
/**
* Loads the VCMI/H3 map header specified by the name.
*
* @param name the name of the map
* @return a unique ptr to the loaded map header class
*/
std::unique_ptr<CMapHeader> loadMapHeader(const ResourceID & name) const;
virtual std::unique_ptr<CMapHeader> loadMapHeader(const ResourceID & name) const = 0;
/**
* Loads the VCMI/H3 map file from a buffer. This method is temporarily
* in use to ease the transition to use the new map service.
*
* TODO Replace method params with a CampaignMapInfo struct which contains
* a campaign loading object + name of map.
*
* @param buffer a pointer to a buffer containing the map data
* @param size the size of the buffer
@@ -60,8 +60,8 @@ class DLL_LINKAGE CMapService
* @param name indicates name of file that will be used during map header patching
* @return a unique ptr to the loaded map class
*/
std::unique_ptr<CMap> loadMap(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const;
virtual std::unique_ptr<CMap> loadMap(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const = 0;
/**
* Loads the VCMI/H3 map header from a buffer. This method is temporarily
* in use to ease the transition to use the new map service.
*
* TODO Replace method params with a CampaignMapInfo struct which contains
* a campaign loading object + name of map.
*
* @param buffer a pointer to a buffer containing the map header data
* @param size the size of the buffer
@@ -74,7 +74,27 @@ class DLL_LINKAGE CMapService
* @param name indicates name of file that will be used during map header patching
* @return a unique ptr to the loaded map class
*/
std::unique_ptr<CMapHeader> loadMapHeader(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const;
virtual std::unique_ptr<CMapHeader> loadMapHeader(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const = 0;
/**
* Saves map into VCMI format with name specified
* @param map to save
* @param fullPath full path to file to write, including extension
*/
virtual void saveMap(const std::unique_ptr<CMap> & map, boost::filesystem::path fullPath) const = 0;
};
class DLL_LINKAGE CMapService : public IMapService
{
public:
CMapService() = default;
virtual ~CMapService() = default;
std::unique_ptr<CMap> loadMap(const ResourceID & name) const override;
std::unique_ptr<CMapHeader> loadMapHeader(const ResourceID & name) const override;
std::unique_ptr<CMap> loadMap(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const override;
std::unique_ptr<CMapHeader> loadMapHeader(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const override;
void saveMap(const std::unique_ptr<CMap> & map, boost::filesystem::path fullPath) const override;
/**
* Tests if mods used in the map are currently loaded
@ -82,14 +92,7 @@ public:
* @return data structure representing missing or incompatible mods (those which are needed from map but not loaded)
*/
static ModCompatibilityInfo verifyMapHeaderMods(const CMapHeader & map);
/**
* Saves map into VCMI format with name specified
* @param map to save
* @param fullPath full path to file to write, including extension
*/
void saveMap(const std::unique_ptr<CMap> & map, boost::filesystem::path fullPath) const;
private:
/**
* Gets a map input stream object specified by a map name.

View File

@ -595,9 +595,9 @@ void CMapFormatJson::readTeams(JsonDeserializer & handler)
logGlobal->error("Invalid teams field type");
mapHeader->howManyTeams = 0;
for(int i = 0; i < PlayerColor::PLAYER_LIMIT_I; i++)
if(mapHeader->players[i].canComputerPlay || mapHeader->players[i].canHumanPlay)
mapHeader->players[i].team = TeamID(mapHeader->howManyTeams++);
for(auto & player : mapHeader->players)
if(player.canAnyonePlay())
player.team = TeamID(mapHeader->howManyTeams++);
}
else
{

View File

@ -127,7 +127,7 @@ void Heal::prepareHealEffect(int64_t value, BattleUnitsChanged & pack, BattleLog
else if (unitHPgained > 0 && m->caster->getHeroCaster() == nullptr) //Show text about healed HP if healed by unit
{
MetaString healText;
auto casterUnit = dynamic_cast<const battle::CUnitState*>(m->caster)->acquire();
auto casterUnit = dynamic_cast<const battle::Unit*>(m->caster);
healText.addTxt(MetaString::GENERAL_TXT, 414);
casterUnit->addNameReplacement(healText, false);
state->addNameReplacement(healText, false);

View File

@ -1,4 +1,5 @@
include(GoogleTest)
include(CheckCXXCompilerFlag)
set(googleTest_Dir ${CMAKE_CURRENT_SOURCE_DIR}/googletest)
if(EXISTS ${googleTest_Dir})
@ -29,22 +30,6 @@ set(test_SRCS
entity/CHeroTest.cpp
entity/CSkillTest.cpp
erm/ERM_BM.cpp
erm/ERM_BU.cpp
erm/ERM_FU.cpp
erm/ERM_GM_T.cpp
erm/ERM_MA.cpp
erm/ERM_MC.cpp
erm/ERM_MF.cpp
erm/ERM_TM_T.cpp
erm/ERM_VR.cpp
erm/ERM_UN.cpp
erm/ERMPersistenceTest.cpp
erm/ExamplesTest.cpp
erm/interpretter/ERM_VR.cpp
erm/interpretter/ERM_UN.cpp
erm/interpretter/ErmRunner.cpp
events/ApplyDamageTest.cpp
events/EventBusTest.cpp
@ -57,12 +42,6 @@ set(test_SRCS
netpacks/EntitiesChangedTest.cpp
netpacks/NetPackFixture.cpp
scripting/LuaSandboxTest.cpp
scripting/LuaSpellEffectTest.cpp
scripting/LuaSpellEffectAPITest.cpp
scripting/PoolTest.cpp
scripting/ScriptFixture.cpp
spells/AbilityCasterTest.cpp
spells/CSpellTest.cpp
spells/TargetConditionTest.cpp
@ -104,10 +83,7 @@ set(test_HEADERS
CVcmiTestConfig.h
JsonComparer.h
scripting/ScriptFixture.h
erm/interpretter/ErmRunner.h
map/MapComparer.h
map/MapComparer.h
netpacks/NetPackFixture.h
@ -125,6 +101,44 @@ set(test_HEADERS
)
if(ENABLE_LUA)
list(APPEND test_SRCS
scripting/LuaSandboxTest.cpp
scripting/LuaSpellEffectTest.cpp
scripting/LuaSpellEffectAPITest.cpp
scripting/PoolTest.cpp
scripting/ScriptFixture.cpp
)
list(APPEND test_HEADERS
scripting/ScriptFixture.h
)
endif()
if(ENABLE_ERM)
list(APPEND test_SRCS
erm/ERM_BM.cpp
erm/ERM_BU.cpp
erm/ERM_FU.cpp
erm/ERM_GM_T.cpp
erm/ERM_MA.cpp
erm/ERM_MC.cpp
erm/ERM_MF.cpp
erm/ERM_TM_T.cpp
erm/ERM_VR.cpp
erm/ERM_UN.cpp
erm/ERMPersistenceTest.cpp
erm/ExamplesTest.cpp
erm/interpretter/ERM_VR.cpp
erm/interpretter/ERM_UN.cpp
erm/interpretter/ErmRunner.cpp
)
list(APPEND test_HEADERS
erm/interpretter/ErmRunner.h
)
endif()
assign_source_group(${test_SRCS} ${test_HEADERS})
set(mock_HEADERS
@ -148,10 +162,25 @@ set(mock_HEADERS
if(MSVC)
set(gtest_force_shared_crt ON CACHE BOOL "Use shared (DLL) run-time lib even when Google Test is built as static lib." FORCE)
endif()
check_cxx_compiler_flag(-Wimplicit-int-float-conversion CONV)
if(CONV)
add_compile_options(-Wno-error=implicit-int-float-conversion) #Used in googletest
endif()
check_cxx_compiler_flag(-Wdeprecated-copy-with-user-provided-copy COPY)
if(COPY)
add_compile_options(-Wno-deprecated-copy-with-user-provided-copy) #Used in googletest
endif()
check_cxx_compiler_flag(-Wvirtual-move-assign MOVE_ASSIGN)
if(MOVE_ASSIGN)
add_compile_options(-Wno-error=virtual-move-assign) #GCC is too strict here
endif()
add_subdirectory_with_folder("3rdparty" googletest EXCLUDE_FROM_ALL)
add_executable(vcmitest ${test_SRCS} ${test_HEADERS} ${mock_HEADERS})
target_link_libraries(vcmitest PRIVATE gtest gmock vcmi ${SYSTEM_LIBS})
if(ENABLE_LUA)
target_link_libraries(vcmitest PRIVATE vcmiLua)
endif()
target_include_directories(vcmitest
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
@ -161,16 +190,10 @@ target_include_directories(vcmitest
PRIVATE ${GMockSrc}/include
)
if(FALSE AND NOT ${CMAKE_VERSION} VERSION_LESS "3.10.0")
# Running tests one by one using ctest not recommended due to vcmi having
# slow global initialization.
gtest_discover_tests(vcmitest
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/bin/")
else()
add_test(NAME tests
COMMAND vcmitest
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/bin/")
endif()
# Running tests one by one using ctest not recommended due to vcmi having
# slow global initialization.
gtest_discover_tests(vcmitest
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/bin/")
vcmi_set_output_dir(vcmitest "")

View File

@ -25,7 +25,6 @@ void CVcmiTestConfig::SetUp()
{
console = new CConsoleHandler();
preinitDLL(console, true);
settings.init();
loadDLLClasses(true);
/* TEST_DATA_DIR may be wrong, if yes below test don't run,
@ -35,13 +34,13 @@ void CVcmiTestConfig::SetUp()
path+= "/" + TEST_DATA_DIR;
if(boost::filesystem::exists(path)){
auto loader = new CFilesystemLoader("test/", TEST_DATA_DIR);
dynamic_cast<CFilesystemList*>(CResourceHandler::get())->addLoader(loader, false);
dynamic_cast<CFilesystemList*>(CResourceHandler::get("core"))->addLoader(loader, false);
loader = new CFilesystemLoader("scripts/test/erm/", TEST_DATA_DIR+"erm/");
dynamic_cast<CFilesystemList*>(CResourceHandler::get())->addLoader(loader, false);
dynamic_cast<CFilesystemList*>(CResourceHandler::get("core"))->addLoader(loader, false);
loader = new CFilesystemLoader("scripts/test/lua/", TEST_DATA_DIR+"lua/");
dynamic_cast<CFilesystemList*>(CResourceHandler::get())->addLoader(loader, false);
dynamic_cast<CFilesystemList*>(CResourceHandler::get("core"))->addLoader(loader, false);
}
}

View File

@ -80,7 +80,7 @@ void JsonComparer::checkEqualInteger(const si64 actual, const si64 expected)
{
if(actual != expected)
{
check(false, boost::str(boost::format("'%d' != '%d'") % actual % expected));
check(false, boost::str(boost::format("actual: '%d' ,expected: '%d'") % actual % expected));
}
}
@ -88,7 +88,7 @@ void JsonComparer::checkEqualFloat(const double actual, const double expected)
{
if(std::abs(actual - expected) > 1e-8)
{
check(false, boost::str(boost::format("'%d' != '%d' (diff %d)") % actual % expected % (expected - actual)));
check(false, boost::str(boost::format("actual: '%lf' ,expected: '%lf' (diff %lf)") % actual % expected % (expected - actual)));
}
}
@ -96,7 +96,7 @@ void JsonComparer::checkEqualString(const std::string & actual, const std::strin
{
if(actual != expected)
{
check(false, boost::str(boost::format("'%s' != '%s'") % actual % expected));
check(false, boost::str(boost::format("actual: '%s' , expected: '%s'") % actual % expected));
}
}

View File

@ -19,7 +19,9 @@
#include "mock/mock_BonusBearer.h"
#include "mock/mock_battle_IBattleState.h"
#include "mock/mock_battle_Unit.h"
#if SCRIPTING_ENABLED
#include "mock/mock_scripting_Pool.h"
#endif
using namespace battle;
using namespace testing;
@ -122,11 +124,16 @@ public:
{
public:
#if SCRIPTING_ENABLED
scripting::Pool * pool;
TestSubject(scripting::Pool * p)
: CBattleInfoCallback(),
pool(p)
#else
TestSubject()
: CBattleInfoCallback()
#endif
{
}
@ -135,13 +142,17 @@ public:
CBattleInfoCallback::setBattle(battleInfo);
}
#if SCRIPTING_ENABLED
scripting::Pool * getContextPool() const override
{
return pool;
}
#endif
};
#if SCRIPTING_ENABLED
StrictMock<scripting::PoolMock> pool;
#endif
TestSubject subject;
@ -149,8 +160,10 @@ public:
UnitsFake unitsFake;
CBattleInfoCallbackTest()
#if SCRIPTING_ENABLED
: pool(),
subject(&pool)
#endif
{
}
@ -275,7 +288,7 @@ TEST_F(BattleFinishedTest, LastWarMachineLoose)
expectBattleWinner(0);
}
catch(std::exception e)
catch(const std::exception & e)
{
logGlobal->error(e.what());
}

View File

@ -36,7 +36,10 @@ TEST_F(CArtifactTest, RegistersIcons)
subject->image = "Test1";
subject->large = "Test2";
auto cb = std::bind(&CArtifactTest::registarCb, this, _1, _2, _3, _4);
auto cb = [this](auto && PH1, auto && PH2, auto && PH3, auto && PH4)
{
registarCb(std::forward<decltype(PH1)>(PH1), std::forward<decltype(PH2)>(PH2), std::forward<decltype(PH3)>(PH3), std::forward<decltype(PH4)>(PH4));
};
EXPECT_CALL(*this, registarCb(Eq(4242), Eq(0), "ARTIFACT", "Test1"));
EXPECT_CALL(*this, registarCb(Eq(4242), Eq(0), "ARTIFACTLARGE", "Test2"));

View File

@ -35,7 +35,10 @@ TEST_F(CCreatureTest, RegistersIcons)
subject->smallIconName = "Test1";
subject->largeIconName = "Test2";
auto cb = std::bind(&CCreatureTest::registarCb, this, _1, _2, _3, _4);
auto cb = [this](auto && PH1, auto && PH2, auto && PH3, auto && PH4)
{
registarCb(std::forward<decltype(PH1)>(PH1), std::forward<decltype(PH2)>(PH2), std::forward<decltype(PH3)>(PH3), std::forward<decltype(PH4)>(PH4));
};
EXPECT_CALL(*this, registarCb(Eq(4242), Eq(0), "CPRSMALL", "Test1"));
EXPECT_CALL(*this, registarCb(Eq(4242), Eq(0), "TWCRPORT", "Test2"));

View File

@ -41,13 +41,19 @@ TEST_F(CFactionTest, HasTown)
TEST_F(CFactionTest, RegistersNoIconsIfNoTown)
{
auto cb = std::bind(&CFactionTest::registarCb, this, _1, _2, _3, _4);
auto cb = [this](auto && PH1, auto && PH2, auto && PH3, auto && PH4)
{
registarCb(std::forward<decltype(PH1)>(PH1), std::forward<decltype(PH2)>(PH2), std::forward<decltype(PH3)>(PH3), std::forward<decltype(PH4)>(PH4));
};
subject->registerIcons(cb);
}
TEST_F(CFactionTest, RegistersIcons)
{
auto cb = std::bind(&CFactionTest::registarCb, this, _1, _2, _3, _4);
auto cb = [this](auto && PH1, auto && PH2, auto && PH3, auto && PH4)
{
registarCb(std::forward<decltype(PH1)>(PH1), std::forward<decltype(PH2)>(PH2), std::forward<decltype(PH3)>(PH3), std::forward<decltype(PH4)>(PH4));
};
subject->town = new CTown();
@ -67,6 +73,8 @@ TEST_F(CFactionTest, RegistersIcons)
info.iconSmall[0][1] = "Test20";
info.iconSmall[1][0] = "Test30";
info.iconSmall[1][1] = "Test40";
info.towerIconSmall = "Test5";
info.towerIconLarge = "Test6";
EXPECT_CALL(*this, registarCb(Eq(10), Eq(0), "ITPT", "Test1"));
@ -79,6 +87,9 @@ TEST_F(CFactionTest, RegistersIcons)
EXPECT_CALL(*this, registarCb(Eq(14), Eq(0), "ITPA", "Test30"));
EXPECT_CALL(*this, registarCb(Eq(15), Eq(0), "ITPA", "Test40"));
EXPECT_CALL(*this, registarCb(Eq(subject->getIconIndex()), Eq(1), "CPRSMALL", "Test5"));
EXPECT_CALL(*this, registarCb(Eq(subject->getIconIndex()), Eq(1), "TWCRPORT", "Test6"));
subject->registerIcons(cb);
}

View File

@ -32,7 +32,10 @@ protected:
TEST_F(CHeroClassTest, RegistersIconsDoesNothing)
{
auto cb = std::bind(&CHeroClassTest::registarCb, this, _1, _2, _3, _4);
auto cb = [this](auto && PH1, auto && PH2, auto && PH3, auto && PH4)
{
registarCb(std::forward<decltype(PH1)>(PH1), std::forward<decltype(PH2)>(PH2), std::forward<decltype(PH3)>(PH3), std::forward<decltype(PH4)>(PH4));
};
subject->registerIcons(cb);
}

View File

@ -39,7 +39,10 @@ TEST_F(CHeroTest, RegistersIcons)
subject->portraitSmall = "Test3";
subject->portraitLarge = "Test4";
auto cb = std::bind(&CHeroTest::registarCb, this, _1, _2, _3, _4);
auto cb = [this](auto && PH1, auto && PH2, auto && PH3, auto && PH4)
{
registarCb(std::forward<decltype(PH1)>(PH1), std::forward<decltype(PH2)>(PH2), std::forward<decltype(PH3)>(PH3), std::forward<decltype(PH4)>(PH4));
};
EXPECT_CALL(*this, registarCb(Eq(4242), Eq(0), "UN32", "Test1"));
EXPECT_CALL(*this, registarCb(Eq(4242), Eq(0), "UN44", "Test2"));

View File

@ -41,7 +41,10 @@ TEST_F(CSkillTest, RegistersIcons)
skillAtLevel.iconLarge = "TestL"+std::to_string(level);
}
auto cb = std::bind(&CSkillTest::registarCb, this, _1, _2, _3, _4);
auto cb = [this](auto && PH1, auto && PH2, auto && PH3, auto && PH4)
{
registarCb(std::forward<decltype(PH1)>(PH1), std::forward<decltype(PH2)>(PH2), std::forward<decltype(PH3)>(PH3), std::forward<decltype(PH4)>(PH4));
};
for(int level = 1; level <= 3; level++)
{

View File

@ -85,7 +85,7 @@ TEST_F(ERM_MA, Example)
static_assert(FLAG_MASK_NEW == (1 << 0 | 1 << 1 | 1 << 7 | 1 << 12 | 1 << 17 | 1 << 18), "Wrong flag mask meaning");
creatureBonuses.addNewBonus(std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::FLYING, Bonus::CREATURE_ABILITY, 0, 0));
creatureBonuses.addNewBonus(std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::KING1, Bonus::CREATURE_ABILITY, 0, 0));
creatureBonuses.addNewBonus(std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::KING, Bonus::CREATURE_ABILITY, 0, 0));
std::shared_ptr<Bonus> removed = std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::MIND_IMMUNITY, Bonus::CREATURE_ABILITY, 0, 0);
@ -204,7 +204,7 @@ TEST_F(ERM_MA, Bonuses)
static_assert(FLAG_MASK_NEW == ( 1 << 1 | 1 << 7 | 1 << 12 | 1 << 17 | 1 << 18), "Wrong flag mask meaning");
creatureBonuses.addNewBonus(std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::FLYING, Bonus::CREATURE_ABILITY, 0, 0));
creatureBonuses.addNewBonus(std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::KING1, Bonus::CREATURE_ABILITY, 0, 0));
creatureBonuses.addNewBonus(std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::KING, Bonus::CREATURE_ABILITY, 0, 0));
std::shared_ptr<Bonus> removed = std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::MIND_IMMUNITY, Bonus::CREATURE_ABILITY, 0, 0);
@ -266,7 +266,7 @@ TEST_F(ERM_MA, BonusesNoChanges)
static_assert(FLAG_MASK == (1 << 1 | 1 << 7 | 1 << 10 | 1 << 17 | 1 << 18), "Wrong flag mask meaning");
creatureBonuses.addNewBonus(std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::FLYING, Bonus::CREATURE_ABILITY, 0, 0));
creatureBonuses.addNewBonus(std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::KING1, Bonus::CREATURE_ABILITY, 0, 0));
creatureBonuses.addNewBonus(std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::KING, Bonus::CREATURE_ABILITY, 0, 0));
creatureBonuses.addNewBonus(std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::MIND_IMMUNITY, Bonus::CREATURE_ABILITY, 0, 0));
creatureBonuses.addNewBonus(std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::NO_MORALE, Bonus::CREATURE_ABILITY, 0, 0));
creatureBonuses.addNewBonus(std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::UNDEAD, Bonus::CREATURE_ABILITY, 0, 0));

View File

@ -18,6 +18,7 @@
#include "../../lib/CGameState.h"
#include "../../lib/NetPacks.h"
#include "../../lib/StartInfo.h"
#include "../../lib/TerrainHandler.h"
#include "../../lib/battle/BattleInfo.h"
#include "../../lib/CStack.h"
@ -193,7 +194,7 @@ public:
const auto & t = *gameCallback->getTile(tile);
TerrainId terrain = t.terType->id;
auto terrain = t.terType->getId();
BattleField terType = BattleField::fromString("grass_hills");
//send info about battles

View File

@ -13,6 +13,7 @@
#include "../lib/filesystem/ResourceID.h"
#include "../lib/mapping/CMapService.h"
#include "../lib/mapping/CMap.h"
#include "../lib/TerrainHandler.h"
#include "../lib/JsonNode.h"
#include "../lib/mapping/CMapEditManager.h"
#include "../lib/int3.h"
@ -33,49 +34,49 @@ TEST(MapManager, DrawTerrain_Type)
// 1x1 Blow up
editManager->getTerrainSelection().select(int3(5, 5, 0));
editManager->drawTerrain(Terrain::GRASS);
editManager->drawTerrain(ETerrainId::GRASS);
static const int3 squareCheck[] = { int3(5,5,0), int3(5,4,0), int3(4,4,0), int3(4,5,0) };
for(int i = 0; i < ARRAY_COUNT(squareCheck); ++i)
for(const auto & tile : squareCheck)
{
EXPECT_EQ(map->getTile(squareCheck[i]).terType->id, Terrain::GRASS);
EXPECT_EQ(map->getTile(tile).terType->getId(), ETerrainId::GRASS);
}
// Concat to square
editManager->getTerrainSelection().select(int3(6, 5, 0));
editManager->drawTerrain(Terrain::GRASS);
EXPECT_EQ(map->getTile(int3(6, 4, 0)).terType->id, Terrain::GRASS);
editManager->drawTerrain(ETerrainId::GRASS);
EXPECT_EQ(map->getTile(int3(6, 4, 0)).terType->getId(), ETerrainId::GRASS);
editManager->getTerrainSelection().select(int3(6, 5, 0));
editManager->drawTerrain(Terrain::LAVA);
EXPECT_EQ(map->getTile(int3(4, 4, 0)).terType->id, Terrain::GRASS);
EXPECT_EQ(map->getTile(int3(7, 4, 0)).terType->id, Terrain::LAVA);
editManager->drawTerrain(ETerrainId::LAVA);
EXPECT_EQ(map->getTile(int3(4, 4, 0)).terType->getId(), ETerrainId::GRASS);
EXPECT_EQ(map->getTile(int3(7, 4, 0)).terType->getId(), ETerrainId::LAVA);
// Special case water,rock
editManager->getTerrainSelection().selectRange(MapRect(int3(10, 10, 0), 10, 5));
editManager->drawTerrain(Terrain::GRASS);
editManager->drawTerrain(ETerrainId::GRASS);
editManager->getTerrainSelection().selectRange(MapRect(int3(15, 17, 0), 10, 5));
editManager->drawTerrain(Terrain::GRASS);
editManager->drawTerrain(ETerrainId::GRASS);
editManager->getTerrainSelection().select(int3(21, 16, 0));
editManager->drawTerrain(Terrain::GRASS);
EXPECT_EQ(map->getTile(int3(20, 15, 0)).terType->id, Terrain::GRASS);
editManager->drawTerrain(ETerrainId::GRASS);
EXPECT_EQ(map->getTile(int3(20, 15, 0)).terType->getId(), ETerrainId::GRASS);
// Special case non water,rock
static const int3 diagonalCheck[] = { int3(31,42,0), int3(32,42,0), int3(32,43,0), int3(33,43,0), int3(33,44,0),
int3(34,44,0), int3(34,45,0), int3(35,45,0), int3(35,46,0), int3(36,46,0),
int3(36,47,0), int3(37,47,0)};
for(int i = 0; i < ARRAY_COUNT(diagonalCheck); ++i)
for(const auto & tile : diagonalCheck)
{
editManager->getTerrainSelection().select(diagonalCheck[i]);
editManager->getTerrainSelection().select(tile);
}
editManager->drawTerrain(Terrain::GRASS);
EXPECT_EQ(map->getTile(int3(35, 44, 0)).terType->id, Terrain::WATER);
editManager->drawTerrain(ETerrainId::GRASS);
EXPECT_EQ(map->getTile(int3(35, 44, 0)).terType->getId(), ETerrainId::WATER);
// Rock case
editManager->getTerrainSelection().selectRange(MapRect(int3(1, 1, 1), 15, 15));
editManager->drawTerrain(Terrain::SUBTERRANEAN);
editManager->drawTerrain(ETerrainId::SUBTERRANEAN);
std::vector<int3> vec({ int3(6, 6, 1), int3(7, 6, 1), int3(8, 6, 1), int3(5, 7, 1), int3(6, 7, 1), int3(7, 7, 1),
int3(8, 7, 1), int3(4, 8, 1), int3(5, 8, 1), int3(6, 8, 1)});
editManager->getTerrainSelection().setSelection(vec);
editManager->drawTerrain(Terrain::ROCK);
editManager->drawTerrain(ETerrainId::ROCK);
EXPECT_TRUE(!map->getTile(int3(5, 6, 1)).terType->isPassable() || !map->getTile(int3(7, 8, 1)).terType->isPassable());
//todo: add checks here and enable, also use smaller size
@ -133,7 +134,7 @@ TEST(MapManager, DrawTerrain_View)
// Get mapping range
const auto & pattern = VLC->terviewh->getTerrainViewPatternById(groupStr, id);
const auto & mapping = (*pattern).mapping;
const auto & mapping = pattern->get().mapping;
const auto & positionsNode = node["pos"].Vector();
for (const auto & posNode : positionsNode)
@ -143,7 +144,7 @@ TEST(MapManager, DrawTerrain_View)
int3 pos((si32)posVector[0].Float(), (si32)posVector[1].Float(), (si32)posVector[2].Float());
const auto & originalTile = originalMap->getTile(pos);
editManager->getTerrainSelection().selectRange(MapRect(pos, 1, 1));
editManager->drawTerrain(originalTile.terType->id, &gen);
editManager->drawTerrain(originalTile.terType->getId(), &gen);
const auto & tile = map->getTile(pos);
bool isInRange = false;
for(const auto & range : mapping)

View File

@ -84,7 +84,7 @@ void checkEqual(const PlayerInfo & actual, const PlayerInfo & expected)
VCMI_CHECK_FIELD_EQUAL(hasMainTown);
VCMI_CHECK_FIELD_EQUAL(generateHeroAtMainTown);
VCMI_CHECK_FIELD_EQUAL(posOfMainTown);
VCMI_CHECK_FIELD_EQUAL(team);
//VCMI_CHECK_FIELD_EQUAL(team); //TODO: smart team checking, for now team checking is useless, because random team is assigned for single-member teams
VCMI_CHECK_FIELD_EQUAL(hasRandomHero);
}
@ -207,7 +207,7 @@ void MapComparer::compareObject(const CGObjectInstance * actual, const CGObjectI
EXPECT_EQ(actualFullID, expectedFullID);
VCMI_CHECK_FIELD_EQUAL_P(pos);
checkEqual(actual->appearance, expected->appearance);
checkEqual(*actual->appearance, *expected->appearance);
}
void MapComparer::compareObjects()

View File

@ -76,12 +76,14 @@ void UnitsFake::setDefaultBonusExpectations()
BattleFake::~BattleFake() = default;
BattleFake::BattleFake(std::shared_ptr<scripting::PoolMock> pool_)
: CBattleInfoCallback(),
BattleStateMock(),
#if SCRIPTING_ENABLED
BattleFake::BattleFake(std::shared_ptr<scripting::PoolMock> pool_):
pool(pool_)
{
}
#else
BattleFake::BattleFake() = default;
#endif
void BattleFake::setUp()
{
@ -95,11 +97,12 @@ void BattleFake::setupEmptyBattlefield()
EXPECT_CALL(*this, getBattlefieldType()).WillRepeatedly(Return(BattleField::fromString("grass_hills")));
}
#if SCRIPTING_ENABLED
scripting::Pool * BattleFake::getContextPool() const
{
return pool.get();
}
#endif
}
}

View File

@ -15,7 +15,9 @@
#include "mock_BonusBearer.h"
#include "mock_battle_IBattleState.h"
#include "mock_battle_Unit.h"
#if SCRIPTING_ENABLED
#include "mock_scripting_Pool.h"
#endif
#include "../../lib/JsonNode.h"
#include "../../lib/NetPacksBase.h"
@ -61,16 +63,24 @@ public:
class BattleFake : public CBattleInfoCallback, public BattleStateMock
{
#if SCRIPTING_ENABLED
std::shared_ptr<scripting::PoolMock> pool;
#endif
public:
#if SCRIPTING_ENABLED
BattleFake(std::shared_ptr<scripting::PoolMock> pool_);
#else
BattleFake();
#endif
virtual ~BattleFake();
void setUp();
void setupEmptyBattlefield();
#if SCRIPTING_ENABLED
scripting::Pool * getContextPool() const override;
#endif
template <typename T>
void accept(T * pack)

View File

@ -18,9 +18,15 @@ class FactionID;
class CreatureMock : public Creature
{
public:
MOCK_CONST_METHOD0(getNameTranslated, std::string ());
MOCK_CONST_METHOD0(getNameTextID, std::string ());
MOCK_CONST_METHOD0(getNameSingularTranslated, std::string ());
MOCK_CONST_METHOD0(getNameSingularTextID, std::string ());
MOCK_CONST_METHOD0(getNamePluralTranslated, std::string ());
MOCK_CONST_METHOD0(getNamePluralTextID, std::string ());
MOCK_CONST_METHOD0(getIndex, int32_t());
MOCK_CONST_METHOD0(getIconIndex, int32_t());
MOCK_CONST_METHOD0(getJsonKey, const std::string &());
MOCK_CONST_METHOD0(getJsonKey, std::string ());
MOCK_CONST_METHOD0(getName, const std::string &());
MOCK_CONST_METHOD0(getId, CreatureID());
MOCK_CONST_METHOD0(getBonusBearer, const IBonusBearer *());
@ -50,4 +56,8 @@ public:
MOCK_CONST_METHOD1(getCost, int32_t(int32_t));
MOCK_CONST_METHOD0(isDoubleWide, bool());
MOCK_CONST_METHOD1(getRecruitCost, int32_t(Identifier<EGameResID>));
MOCK_CONST_METHOD0(getFullRecruitCost, ResourceSet());
MOCK_CONST_METHOD0(hasUpgrades, bool());
};

View File

@ -16,7 +16,9 @@
class IBattleInfoCallbackMock : public IBattleInfoCallback
{
public:
#if SCRIPTING_ENABLED
MOCK_CONST_METHOD0(getContextPool, scripting::Pool *());
#endif
MOCK_CONST_METHOD0(battleTerrainType, TerrainId());
MOCK_CONST_METHOD0(battleGetBattlefieldType, BattleField());
@ -33,8 +35,10 @@ public:
MOCK_CONST_METHOD2(battleGetUnitByPos, const battle::Unit *(BattleHex, bool));
MOCK_CONST_METHOD0(battleActiveUnit, const battle::Unit *());
MOCK_CONST_METHOD0(getBonusBearer, IBonusBearer*());
MOCK_CONST_METHOD2(battleGetAllObstaclesOnPos, std::vector<std::shared_ptr<const CObstacleInstance>>(BattleHex, bool));
MOCK_CONST_METHOD1(getAllAffectedObstaclesByStack, std::vector<std::shared_ptr<const CObstacleInstance>>(const battle::Unit *));
MOCK_CONST_METHOD2(getAllAffectedObstaclesByStack, std::vector<std::shared_ptr<const CObstacleInstance>>(const battle::Unit *, const std::set<BattleHex> &));
};

View File

@ -48,7 +48,7 @@ public:
void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) override {} //cb will be called when player closes garrison window
void showTeleportDialog(TeleportDialog *iw) override {}
void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) override {}
void giveResource(PlayerColor player, EGameResID which, int val) override {}
void giveResource(PlayerColor player, GameResID which, int val) override {}
void giveResources(PlayerColor player, TResources resources) override {}
void giveCreatures(const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) override {}
@ -82,15 +82,19 @@ public:
void setMovePoints(SetMovePoints * smp) override {}
void setManaPoints(ObjectInstanceID hid, int val) override {}
void giveHero(ObjectInstanceID id, PlayerColor player) override {}
void changeObjPos(ObjectInstanceID objid, int3 newPos, ui8 flags) override {}
void changeObjPos(ObjectInstanceID objid, int3 newPos) override {}
void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2) override {} //when two heroes meet on adventure map
void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) override {}
void changeFogOfWar(std::unordered_set<int3, ShashInt3> &tiles, PlayerColor player, bool hide) override {}
void changeFogOfWar(std::unordered_set<int3> &tiles, PlayerColor player, bool hide) override {}
void castSpell(const spells::Caster * caster, SpellID spellID, const int3 &pos) override {}
///useful callback methods
void sendAndApply(CPackForClient * pack) override;
#if SCRIPTING_ENABLED
MOCK_CONST_METHOD0(getGlobalContextPool, scripting::Pool *());
#endif
private:
UpperCallback * upperCallback;
};

View File

@ -65,12 +65,12 @@ std::unique_ptr<CMapHeader> MapServiceMock::loadMapHeader(const ResourceID & nam
return initialLoader.loadMapHeader();
}
std::unique_ptr<CMap> MapServiceMock::loadMap(const ui8 * buffer, int size, const std::string & name) const
std::unique_ptr<CMap> MapServiceMock::loadMap(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const
{
return loadMap();
}
std::unique_ptr<CMapHeader> MapServiceMock::loadMapHeader(const ui8 * buffer, int size, const std::string & name) const
std::unique_ptr<CMapHeader> MapServiceMock::loadMapHeader(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const
{
initialBuffer.seek(0);
CMapLoaderJson initialLoader(&initialBuffer);

View File

@ -31,8 +31,8 @@ public:
std::unique_ptr<CMap> loadMap(const ResourceID & name) const override;
std::unique_ptr<CMapHeader> loadMapHeader(const ResourceID & name) const override;
std::unique_ptr<CMap> loadMap(const ui8 * buffer, int size, const std::string & name) const override;
std::unique_ptr<CMapHeader> loadMapHeader(const ui8 * buffer, int size, const std::string & name) const override;
std::unique_ptr<CMap> loadMap(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const override;
std::unique_ptr<CMapHeader> loadMapHeader(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const override;
void saveMap(const std::unique_ptr<CMap> & map, boost::filesystem::path fullPath) const override;

View File

@ -21,11 +21,14 @@ public:
MOCK_CONST_METHOD0(factions, const FactionService *());
MOCK_CONST_METHOD0(heroClasses, const HeroClassService *());
MOCK_CONST_METHOD0(heroTypes, const HeroTypeService *());
#if SCRIPTING_ENABLED
MOCK_CONST_METHOD0(scripts, const scripting::Service *());
#endif
MOCK_CONST_METHOD0(spells, const spells::Service *());
MOCK_CONST_METHOD0(skills, const SkillService * ());
MOCK_CONST_METHOD0(battlefields, const BattleFieldService *());
MOCK_CONST_METHOD0(obstacles, const ObstacleService *());
MOCK_CONST_METHOD0(settings, const IGameSettings *());
MOCK_METHOD3(updateEntity, void(Metatype, int32_t, const JsonNode &));

View File

@ -22,7 +22,7 @@ public:
MOCK_CONST_METHOD0(getTerrainType, TerrainId());
MOCK_CONST_METHOD0(getAllObstacles, IBattleInfo::ObstacleCList());
MOCK_CONST_METHOD0(getDefendedTown, const CGTownInstance *());
MOCK_CONST_METHOD1(getWallState, si8(int));
MOCK_CONST_METHOD1(getWallState, EWallState(EWallPart));
MOCK_CONST_METHOD0(getGateState, EGateState());
MOCK_CONST_METHOD1(getSidePlayer, PlayerColor(ui8));
MOCK_CONST_METHOD1(getSideArmy, const CArmedInstance *(ui8));
@ -33,7 +33,7 @@ public:
MOCK_CONST_METHOD0(getTacticsSide, ui8());
MOCK_CONST_METHOD0(getBonusBearer, const IBonusBearer *());
MOCK_CONST_METHOD0(nextUnitId, uint32_t());
MOCK_CONST_METHOD3(getActualDamage, int64_t(const TDmgRange &, int32_t, vstd::RNG &));
MOCK_CONST_METHOD3(getActualDamage, int64_t(const DamageRange &, int32_t, vstd::RNG &));
MOCK_METHOD1(nextRound, void(int32_t));
MOCK_METHOD1(nextTurn, void(uint32_t));
@ -45,7 +45,7 @@ public:
MOCK_METHOD2(addUnitBonus, void(uint32_t, const std::vector<Bonus> &));
MOCK_METHOD2(updateUnitBonus, void(uint32_t, const std::vector<Bonus> &));
MOCK_METHOD2(removeUnitBonus, void(uint32_t, const std::vector<Bonus> &));
MOCK_METHOD2(setWallState, void(int, si8));
MOCK_METHOD2(setWallState, void(EWallPart, EWallState));
MOCK_METHOD1(addObstacle, void(const ObstacleChanges &));
MOCK_METHOD1(removeObstacle, void(uint32_t));
MOCK_METHOD1(updateObstacle, void(const ObstacleChanges &));

View File

@ -30,6 +30,8 @@ public:
MOCK_CONST_METHOD1(getCasterName, void(MetaString &));
MOCK_CONST_METHOD3(getCastDescription, void(const spells::Spell *, const std::vector<const battle::Unit *> &, MetaString &));
MOCK_CONST_METHOD2(spendMana, void(ServerCallback *, const int32_t));
MOCK_CONST_METHOD0(manaLimit, int32_t());
MOCK_CONST_METHOD0(getHeroCaster, CGHeroInstance*());
MOCK_CONST_METHOD0(unitBaseAmount, int32_t());
MOCK_CONST_METHOD0(unitId, uint32_t());
@ -77,7 +79,9 @@ public:
MOCK_CONST_METHOD1(willMove, bool(int));
MOCK_CONST_METHOD1(waited, bool(int));
MOCK_CONST_METHOD1(battleQueuePhase, int(int));
MOCK_CONST_METHOD0(getFaction, FactionID());
MOCK_CONST_METHOD1(battleQueuePhase, battle::BattlePhases::Type(int));
MOCK_CONST_METHOD0(acquire, std::shared_ptr<battle::Unit>());
MOCK_CONST_METHOD0(acquireState, std::shared_ptr<battle::CUnitState>());

View File

@ -57,6 +57,7 @@ public:
MOCK_CONST_METHOD0(requiresClearTiles, bool());
MOCK_CONST_METHOD0(isNegativeSpell, bool());
MOCK_CONST_METHOD0(isPositiveSpell, bool());
MOCK_CONST_METHOD0(isMagicalEffect, bool());
MOCK_CONST_METHOD1(adjustEffectValue,int64_t(const battle::Unit *));
MOCK_CONST_METHOD2(applySpellBonus,int64_t(int64_t, const battle::Unit *));
@ -69,7 +70,9 @@ public:
MOCK_CONST_METHOD2(ownerMatches, bool(const battle::Unit *, const boost::logic::tribool));
MOCK_CONST_METHOD0(creatures, const CreatureService *());
#if SCRIPTING_ENABLED
MOCK_CONST_METHOD0(scripts, const scripting::Service *());
#endif
MOCK_CONST_METHOD0(spells, const Service *());
MOCK_CONST_METHOD0(game, const IGameInfoCallback * ());

View File

@ -18,10 +18,14 @@ namespace spells
class SpellMock : public Spell
{
public:
MOCK_CONST_METHOD0(getNameTranslated, std::string ());
MOCK_CONST_METHOD0(getNameTextID, std::string ());
MOCK_CONST_METHOD1(getDescriptionTextID, std::string (int32_t));
MOCK_CONST_METHOD1(getDescriptionTranslated, std::string (int32_t));
MOCK_CONST_METHOD1(calculateDamage, int64_t(const Caster *));
MOCK_CONST_METHOD0(getIndex, int32_t());
MOCK_CONST_METHOD0(getIconIndex, int32_t());
MOCK_CONST_METHOD0(getJsonKey, const std::string &());
MOCK_CONST_METHOD0(getJsonKey, std::string ());
MOCK_CONST_METHOD0(getName, const std::string &());
MOCK_CONST_METHOD0(getId, SpellID());
MOCK_CONST_METHOD0(getLevel, int32_t());
@ -39,6 +43,7 @@ public:
MOCK_CONST_METHOD0(isDamage, bool());
MOCK_CONST_METHOD0(isOffensive, bool());
MOCK_CONST_METHOD0(isSpecial, bool());
MOCK_CONST_METHOD0(isMagical, bool());
MOCK_CONST_METHOD1(forEachSchool, void(const SchoolCallback &));
MOCK_CONST_METHOD0(getCastSound, const std::string &());
MOCK_CONST_METHOD1(registerIcons, void(const IconRegistar &));

View File

@ -24,7 +24,9 @@
#include "../mock/mock_IBattleInfoCallback.h"
#include "../mock/mock_IGameInfoCallback.h"
#include "../mock/mock_battle_IBattleState.h"
#if SCRIPTING_ENABLED
#include "../mock/mock_scripting_Pool.h"
#endif
#include "../mock/mock_Environment.h"
#include "../mock/mock_Services.h"
#include "../mock/mock_vstd_CLoggerBase.h"

View File

@ -43,6 +43,7 @@ public:
MOCK_CONST_METHOD0(createElemental, Object());
MOCK_CONST_METHOD0(createNormalLevel, Object());
MOCK_CONST_METHOD0(createNormalSpell, Object());
MOCK_CONST_METHOD1(createFromJsonStruct, Object(const JsonNode &));
MOCK_CONST_METHOD3(createConfigurable, Object(std::string, std::string, std::string));
MOCK_CONST_METHOD0(createReceptiveFeature, Object());
MOCK_CONST_METHOD0(createImmunityNegation, Object());

View File

@ -118,16 +118,21 @@ TEST_F(CatapultApplyTest, DamageToIntactPart)
{
JsonNode config(JsonNode::JsonType::DATA_STRUCT);
config["targetsToAttack"].Integer() = 1;
config["chanceToNormalHit"].Integer() = 100;
EffectFixture::setupEffect(config);
}
setDefaultExpectations();
const EWallPart::EWallPart targetPart = EWallPart::BELOW_GATE;
const EWallPart targetPart = EWallPart::BELOW_GATE;
auto & actualCaster = unitsFake.add(BattleSide::ATTACKER);
mechanicsMock.caster = &actualCaster;
EXPECT_CALL(actualCaster, getCasterUnitId()).WillRepeatedly(Return(-1));
EXPECT_CALL(mechanicsMock, isMassive()).WillRepeatedly(Return(true));
EXPECT_CALL(*battleFake, getWallState(_)).WillRepeatedly(Return(EWallState::DESTROYED));
EXPECT_CALL(*battleFake, getWallState(Eq(int(targetPart)))).WillRepeatedly(Return(EWallState::INTACT));
EXPECT_CALL(*battleFake, setWallState(Eq(int(targetPart)), Eq(EWallState::DAMAGED))).Times(1);
EXPECT_CALL(*battleFake, getWallState(Eq(targetPart))).WillRepeatedly(Return(EWallState::INTACT));
EXPECT_CALL(*battleFake, setWallState(Eq(targetPart), Eq(EWallState::DAMAGED))).Times(1);
EXPECT_CALL(serverMock, apply(Matcher<CatapultAttack *>(_))).Times(1);
EffectTarget target;

View File

@ -45,7 +45,6 @@ TEST_F(DamageTest, ApplicableToAliveUnit)
EXPECT_CALL(unit, isValidTarget(Eq(false))).WillOnce(Return(true));
EXPECT_CALL(mechanicsMock, isSmart()).WillOnce(Return(false));
EXPECT_CALL(mechanicsMock, ownerMatches(Eq(&unit))).WillOnce(Return(true));
EffectTarget target;
target.emplace_back(&unit, BattleHex());

View File

@ -79,7 +79,6 @@ TEST_F(DispelTest, ApplicableToAliveUnitWithTimedEffect)
EXPECT_CALL(unit, isValidTarget(Eq(false))).WillOnce(Return(true));
EXPECT_CALL(mechanicsMock, isSmart()).WillOnce(Return(false));
EXPECT_CALL(mechanicsMock, ownerMatches(Eq(&unit))).WillOnce(Return(true));
EXPECT_CALL(mechanicsMock, getSpellIndex()).Times(AtLeast(1)).WillRepeatedly(Return(neutralID.toEnum()));
setDefaultExpectaions();

View File

@ -72,9 +72,12 @@ void EffectFixture::setupEffect(Registry * registry, const JsonNode & effectConf
void EffectFixture::setUp()
{
#if SCRIPTING_ENABLED
pool = std::make_shared<PoolMock>();
battleFake = std::make_shared<battle::BattleFake>(pool);
#else
battleFake = std::make_shared<battle::BattleFake>();
#endif
battleFake->setUp();
EXPECT_CALL(mechanicsMock, game()).WillRepeatedly(Return(&gameMock));

View File

@ -26,7 +26,9 @@
#include "../../mock/mock_battle_IBattleState.h"
#include "../../mock/mock_battle_Unit.h"
#include "../../mock/mock_vstd_RNG.h"
#if SCRIPTING_ENABLED
#include "../../mock/mock_scripting_Pool.h"
#endif
#include "../../mock/BattleFake.h"
#include "../../mock/mock_ServerCallback.h"
@ -48,7 +50,9 @@ namespace test
using namespace ::testing;
using namespace ::spells;
using namespace ::spells::effects;
#if SCRIPTING_ENABLED
using namespace ::scripting;
#endif
class EffectFixture
{
@ -65,7 +69,9 @@ public:
battle::UnitsFake unitsFake;
#if SCRIPTING_ENABLED
std::shared_ptr<PoolMock> pool;
#endif
std::shared_ptr<battle::BattleFake> battleFake;
StrictMock<ServerCallbackMock> serverMock;

View File

@ -49,7 +49,6 @@ TEST_F(HealTest, NotApplicableToHealthyUnit)
EXPECT_CALL(unit, getAvailableHealth()).WillOnce(Return(200));
EXPECT_CALL(mechanicsMock, isSmart()).Times(AtMost(1)).WillRepeatedly(Return(false));
EXPECT_CALL(mechanicsMock, ownerMatches(Eq(&unit))).Times(AtMost(1)).WillRepeatedly(Return(true));
EffectTarget target;
target.emplace_back(&unit, BattleHex());
@ -67,7 +66,6 @@ TEST_F(HealTest, ApplicableToWoundedUnit)
EXPECT_CALL(unit, getAvailableHealth()).WillOnce(Return(100));
EXPECT_CALL(mechanicsMock, isSmart()).WillOnce(Return(false));
EXPECT_CALL(mechanicsMock, ownerMatches(Eq(&unit))).WillOnce(Return(true));
EffectTarget target;
target.emplace_back(&unit, BattleHex());
@ -92,7 +90,6 @@ TEST_F(HealTest, ApplicableIfActuallyResurrects)
EXPECT_CALL(mechanicsMock, getEffectValue()).Times(AtLeast(1)).WillRepeatedly(Return(1000));
EXPECT_CALL(mechanicsMock, isSmart()).WillOnce(Return(false));
EXPECT_CALL(mechanicsMock, ownerMatches(Eq(&unit))).WillOnce(Return(true));
unit.addNewBonus(std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::STACK_HEALTH, Bonus::CREATURE_ABILITY, 200, 0));
unitsFake.setDefaultBonusExpectations();
@ -119,7 +116,6 @@ TEST_F(HealTest, NotApplicableIfNotEnoughCasualties)
EXPECT_CALL(mechanicsMock, getEffectValue()).Times(AtLeast(1)).WillRepeatedly(Return(999));
EXPECT_CALL(mechanicsMock, isSmart()).WillRepeatedly(Return(false));
EXPECT_CALL(mechanicsMock, ownerMatches(Eq(&unit))).WillRepeatedly(Return(true));
unit.addNewBonus(std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::STACK_HEALTH, Bonus::CREATURE_ABILITY, 200, 0));
unitsFake.setDefaultBonusExpectations();
@ -146,7 +142,6 @@ TEST_F(HealTest, NotApplicableIfResurrectsLessThanRequired)
EXPECT_CALL(mechanicsMock, getEffectValue()).Times(AtLeast(1)).WillRepeatedly(Return(999));
EXPECT_CALL(mechanicsMock, isSmart()).WillRepeatedly(Return(false));
EXPECT_CALL(mechanicsMock, ownerMatches(Eq(&unit))).WillRepeatedly(Return(true));
unit.addNewBonus(std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::STACK_HEALTH, Bonus::CREATURE_ABILITY, 200, 0));
unitsFake.setDefaultBonusExpectations();
@ -179,7 +174,6 @@ TEST_F(HealTest, ApplicableToDeadUnit)
EXPECT_CALL(mechanicsMock, isSmart()).WillOnce(Return(false));
EXPECT_CALL(mechanicsMock, ownerMatches(Eq(&unit))).WillOnce(Return(true));
EXPECT_CALL(*battleFake, getUnitsIf(_)).Times(AtLeast(0));
@ -217,7 +211,6 @@ TEST_F(HealTest, NotApplicableIfDeadUnitIsBlocked)
EXPECT_CALL(blockingUnit, unitSide()).Times(AnyNumber());
EXPECT_CALL(mechanicsMock, isSmart()).WillRepeatedly(Return(false));
EXPECT_CALL(mechanicsMock, ownerMatches(Eq(&unit))).WillRepeatedly(Return(true));
EXPECT_CALL(*battleFake, getUnitsIf(_)).Times(AtLeast(1));
@ -255,7 +248,6 @@ TEST_F(HealTest, ApplicableWithAnotherDeadUnitInSamePosition)
EXPECT_CALL(blockingUnit, unitSide()).Times(AnyNumber());
EXPECT_CALL(mechanicsMock, isSmart()).WillRepeatedly(Return(false));
EXPECT_CALL(mechanicsMock, ownerMatches(Eq(&unit))).WillRepeatedly(Return(true));
EXPECT_CALL(*battleFake, getUnitsIf(_)).Times(AtLeast(1));
@ -284,7 +276,6 @@ TEST_F(HealTest, NotApplicableIfEffectValueTooLow)
EXPECT_CALL(mechanicsMock, getEffectValue()).Times(AtLeast(1)).WillRepeatedly(Return(199));
EXPECT_CALL(mechanicsMock, isSmart()).Times(AtMost(1)).WillRepeatedly(Return(false));
EXPECT_CALL(mechanicsMock, ownerMatches(Eq(&unit))).Times(AtMost(1)).WillRepeatedly(Return(true));
unitsFake.setDefaultBonusExpectations();
@ -348,10 +339,14 @@ TEST_P(HealApplyTest, Heals)
const int32_t unitAmount = 24;
const int32_t unitHP = 100;
const uint32_t unitId = 42;
const auto pikeman = CreatureID(unitId).toCreature();
auto & targetUnit = unitsFake.add(BattleSide::ATTACKER);
auto & actualCaster = unitsFake.add(BattleSide::ATTACKER);
EXPECT_CALL(targetUnit, unitBaseAmount()).WillRepeatedly(Return(unitAmount));
EXPECT_CALL(targetUnit, unitId()).WillRepeatedly(Return(unitId));
EXPECT_CALL(targetUnit, unitType()).WillRepeatedly(Return(pikeman));
targetUnit.addNewBonus(std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::STACK_HEALTH, Bonus::CREATURE_ABILITY, unitHP, 0));
@ -364,17 +359,23 @@ TEST_P(HealApplyTest, Heals)
targetUnitState->health.damage(initialDmg);
}
mechanicsMock.caster = &actualCaster;
EXPECT_CALL(mechanicsMock, getEffectValue()).WillRepeatedly(Return(effectValue));
EXPECT_CALL(mechanicsMock, applySpellBonus(Eq(effectValue), Eq(&targetUnit))).WillRepeatedly(Return(effectValue));
EXPECT_CALL(actualCaster, creatureIndex()).WillRepeatedly(Return(CreatureID(unitId)));
EXPECT_CALL(actualCaster, getHeroCaster()).WillRepeatedly(Return(nullptr));
GTEST_ASSERT_EQ(targetUnitState->getAvailableHealth(), unitAmount * unitHP / 2 + 1);
GTEST_ASSERT_EQ(targetUnitState->getFirstHPleft(), 1);
EXPECT_CALL(targetUnit, acquire()).WillOnce(Return(targetUnitState));
EXPECT_CALL(targetUnit, acquire()).WillRepeatedly(Return(targetUnitState));
EXPECT_CALL(*battleFake, setUnitState(Eq(unitId), _, Gt(0))).Times(1);
EXPECT_CALL(actualCaster, getCasterUnitId()).WillRepeatedly(Return(-1));
EXPECT_CALL(serverMock, apply(Matcher<BattleUnitsChanged *>(_))).Times(1);
EXPECT_CALL(serverMock, apply(Matcher<BattleLogMessage *>(_))).Times(AtLeast(1));
setupDefaultRNG();
@ -411,7 +412,7 @@ TEST_P(HealApplyTest, Heals)
}
}
INSTANTIATE_TEST_CASE_P
INSTANTIATE_TEST_SUITE_P
(
ByConfig1,
HealApplyTest,
@ -422,7 +423,7 @@ INSTANTIATE_TEST_CASE_P
)
);
INSTANTIATE_TEST_CASE_P
INSTANTIATE_TEST_SUITE_P
(
ByConfig2,
HealApplyTest,

View File

@ -166,12 +166,14 @@ TEST_F(SacrificeApplyTest, ResurrectsTarget)
const uint32_t victimId = 4242;
const int32_t victimCount = 5;
const int32_t victimUnitHP = 100;
const auto pikeman = CreatureID(unitId).toCreature();
const int64_t expectedHealValue = (effectPower + victimUnitHP + effectValue) * victimCount;
auto & targetUnit = unitsFake.add(BattleSide::ATTACKER);
EXPECT_CALL(targetUnit, unitBaseAmount()).WillRepeatedly(Return(unitAmount));
EXPECT_CALL(targetUnit, unitId()).WillRepeatedly(Return(unitId));
EXPECT_CALL(targetUnit, unitType()).WillRepeatedly(Return(pikeman));
EXPECT_CALL(mechanicsMock, getEffectPower()).Times(AtLeast(1)).WillRepeatedly(Return(effectPower));
EXPECT_CALL(mechanicsMock, applySpellBonus(_, Eq(&targetUnit))).WillOnce(ReturnArg<0>());
@ -201,6 +203,7 @@ TEST_F(SacrificeApplyTest, ResurrectsTarget)
EXPECT_CALL(targetUnit, acquire()).WillOnce(Return(targetUnitState));
EXPECT_CALL(serverMock, apply(Matcher<BattleUnitsChanged *>(_))).Times(AtLeast(1));
EXPECT_CALL(serverMock, apply(Matcher<BattleLogMessage *>(_))).Times(AtLeast(1));
setupDefaultRNG();

View File

@ -127,7 +127,7 @@ TEST_P(SummonTest, Transform)
EXPECT_THAT(transformed, ContainerEq(expected));
}
INSTANTIATE_TEST_CASE_P
INSTANTIATE_TEST_SUITE_P
(
ByConfig,
SummonTest,
@ -270,7 +270,7 @@ TEST_P(SummonApplyTest, UpdatesOldUnit)
subject->apply(&serverMock, &mechanicsMock, target);
}
INSTANTIATE_TEST_CASE_P
INSTANTIATE_TEST_SUITE_P
(
ByConfig,
SummonApplyTest,

View File

@ -65,7 +65,6 @@ TEST_F(TeleportApplyTest, MovesUnit)
EXPECT_CALL(unit, getPosition()).WillRepeatedly(Return(initial));
EXPECT_CALL(unit, unitId()).Times(AtLeast(1)).WillRepeatedly(Return(unitId));
EXPECT_CALL(unit, unitSide()).Times(AtLeast(1));
EXPECT_CALL(unit, doubleWide()).WillRepeatedly(Return(false));
EXPECT_CALL(unit, isValidTarget(Eq(false))).WillRepeatedly(Return(true));

View File

@ -124,7 +124,7 @@ TEST_P(TimedApplyTest, ChangesBonuses)
EXPECT_THAT(actualBonus, UnorderedElementsAreArray(expectedBonus));
}
INSTANTIATE_TEST_CASE_P
INSTANTIATE_TEST_SUITE_P
(
ByConfig,
TimedApplyTest,

View File

@ -23,6 +23,7 @@ public:
void setDefaultExpectations()
{
EXPECT_CALL(mechanicsMock, isMagicalEffect()).WillRepeatedly(Return(true));
EXPECT_CALL(unitMock, getAllBonuses(_, _, _, _)).Times(AtLeast(1));
EXPECT_CALL(unitMock, getTreeVersion()).Times(AtLeast(0));
}

View File

@ -62,7 +62,7 @@ TEST_P(AbsoluteSpellConditionTest, IgnoresNormalCase)
EXPECT_TRUE(subject->isReceptive(&mechanicsMock, &unitMock));
}
INSTANTIATE_TEST_CASE_P
INSTANTIATE_TEST_SUITE_P
(
BySpells,
AbsoluteSpellConditionTest,

View File

@ -29,7 +29,7 @@ public:
{
TargetConditionItemTest::SetUp();
subject = TargetConditionItemFactory::getDefault()->createConfigurable("", "creature", "ammoCart");
subject = TargetConditionItemFactory::getDefault()->createConfigurable("core", "creature", "ammoCart");
GTEST_ASSERT_NE(subject, nullptr);
}
};

View File

@ -76,7 +76,7 @@ TEST_P(ElementalConditionTest, ImmuneIfBothBonusesPresent)
EXPECT_FALSE(subject->isReceptive(&mechanicsMock, &unitMock));
}
INSTANTIATE_TEST_CASE_P
INSTANTIATE_TEST_SUITE_P
(
ByPositiveness,
ElementalConditionTest,

View File

@ -65,10 +65,11 @@ TEST_P(ImmunityNegationConditionTest, WithBattleWideNegation)
unitBonuses.addNewBonus(std::make_shared<Bonus>(Bonus::ONE_BATTLE, Bonus::NEGATE_ALL_NATURAL_IMMUNITIES, Bonus::OTHER, 0, 0, 0));
EXPECT_EQ(!ownerMatches, subject->isReceptive(&mechanicsMock, &unitMock));
//This should return if ownerMatches, because anyone should cast onto owner's stacks, but not on enemyStacks
EXPECT_EQ(ownerMatches, subject->isReceptive(&mechanicsMock, &unitMock));
}
INSTANTIATE_TEST_CASE_P
INSTANTIATE_TEST_SUITE_P
(
ByUnitOwner,
ImmunityNegationConditionTest,

View File

@ -23,6 +23,7 @@ public:
void setDefaultExpectations()
{
EXPECT_CALL(mechanicsMock, isMagicalEffect()).WillRepeatedly(Return(true));
EXPECT_CALL(unitMock, getAllBonuses(_, _, _, _)).Times(AtLeast(1));
EXPECT_CALL(unitMock, getTreeVersion()).Times(AtLeast(0));
}

View File

@ -65,7 +65,7 @@ TEST_P(NormalSpellConditionTest, ChecksNormalCase)
EXPECT_TRUE(subject->isReceptive(&mechanicsMock, &unitMock));
}
INSTANTIATE_TEST_CASE_P
INSTANTIATE_TEST_SUITE_P
(
BySpells,
NormalSpellConditionTest,

View File

@ -50,7 +50,7 @@ TEST_P(ReceptiveFeatureConditionTest, isReceptive)
EXPECT_EQ(isPositive && hasBonus, subject->isReceptive(&mechanicsMock, &unitMock));
}
INSTANTIATE_TEST_CASE_P
INSTANTIATE_TEST_SUITE_P
(
ByFlags,
ReceptiveFeatureConditionTest,

View File

@ -31,7 +31,7 @@ public:
{
TargetConditionItemTest::SetUp();
subject = TargetConditionItemFactory::getDefault()->createConfigurable("", "spell", "age");
subject = TargetConditionItemFactory::getDefault()->createConfigurable("core", "spell", "age");
GTEST_ASSERT_NE(subject, nullptr);
}
};

View File

@ -32,236 +32,236 @@
},
"allowedArtifacts" : {
"anyOf" : [
"admiralsHat",
"angelicAlliance",
"armageddonsBlade",
"armorOfTheDamned",
"bowOfTheSharpshooter",
"cloakOfTheUndeadKing",
"cornucopia",
"elixirOfLife",
"powerOfTheDragonFather",
"ringOfTheMagi",
"statueOfLegion",
"titansThunder",
"vialOfDragonBlood",
"wizardsWell"
"core:admiralsHat",
"core:angelicAlliance",
"core:armageddonsBlade",
"core:armorOfTheDamned",
"core:bowOfTheSharpshooter",
"core:cloakOfTheUndeadKing",
"core:cornucopia",
"core:elixirOfLife",
"core:powerOfTheDragonFather",
"core:ringOfTheMagi",
"core:statueOfLegion",
"core:titansThunder",
"core:vialOfDragonBlood",
"core:wizardsWell"
]
},
"allowedHeroes" : {
"anyOf" : [
"adela",
"adelaide",
"aenain",
"aeris",
"aine",
"aislinn",
"ajit",
"alagar",
"alamar",
"alkin",
"andra",
"arlach",
"ash",
"astral",
"axsis",
"ayden",
"brissa",
"broghild",
"bron",
"caitlin",
"calh",
"calid",
"charna",
"christian",
"ciele",
"clancy",
"clavius",
"coronius",
"cragHack",
"cuthbert",
"cyra",
"dace",
"damacon",
"daremyth",
"darkstorn",
"deemer",
"dessa",
"drakon",
"elleshar",
"erdamon",
"fafner",
"fiona",
"fiur",
"galthran",
"gelare",
"gem",
"geon",
"gerwulf",
"gird",
"gretchin",
"grindan",
"gundula",
"gunnar",
"gurnisson",
"halon",
"ignatius",
"ignissa",
"inteus",
"iona",
"isra",
"ivor",
"jabarkas",
"jaegar",
"jeddite",
"jenova",
"josephine",
"kalt",
"korbac",
"krellion",
"kyrre",
"labetha",
"lacus",
"lorelei",
"loynis",
"malcom",
"malekith",
"marius",
"melodia",
"mephala",
"merist",
"mirlanda",
"moandor",
"monere",
"nagash",
"neela",
"nimbus",
"nymus",
"octavia",
"olema",
"oris",
"pasis",
"piquedram",
"pyre",
"rashka",
"rion",
"rissa",
"rosic",
"ryland",
"sandro",
"sanya",
"saurug",
"sephinroth",
"septienna",
"serena",
"shakti",
"shiva",
"sirMullich",
"solmyr",
"straker",
"styg",
"sylvia",
"synca",
"tamika",
"tazar",
"terek",
"thane",
"thant",
"theodorus",
"thorgrim",
"thunar",
"tiva",
"torosar ",
"tyraxor",
"tyris",
"ufretin",
"uland",
"verdish",
"vey",
"vidomina",
"vokial",
"voy",
"wystan",
"xarfax",
"xsi",
"xyron",
"yog",
"zubin",
"zydar"
"core:adela",
"core:adelaide",
"core:aenain",
"core:aeris",
"core:aine",
"core:aislinn",
"core:ajit",
"core:alagar",
"core:alamar",
"core:alkin",
"core:andra",
"core:arlach",
"core:ash",
"core:astral",
"core:axsis",
"core:ayden",
"core:brissa",
"core:broghild",
"core:bron",
"core:caitlin",
"core:calh",
"core:calid",
"core:charna",
"core:christian",
"core:ciele",
"core:clancy",
"core:clavius",
"core:coronius",
"core:cragHack",
"core:cuthbert",
"core:cyra",
"core:dace",
"core:damacon",
"core:daremyth",
"core:darkstorn",
"core:deemer",
"core:dessa",
"core:drakon",
"core:elleshar",
"core:erdamon",
"core:fafner",
"core:fiona",
"core:fiur",
"core:galthran",
"core:gelare",
"core:gem",
"core:geon",
"core:gerwulf",
"core:gird",
"core:gretchin",
"core:grindan",
"core:gundula",
"core:gunnar",
"core:gurnisson",
"core:halon",
"core:ignatius",
"core:ignissa",
"core:inteus",
"core:iona",
"core:isra",
"core:ivor",
"core:jabarkas",
"core:jaegar",
"core:jeddite",
"core:jenova",
"core:josephine",
"core:kalt",
"core:korbac",
"core:krellion",
"core:kyrre",
"core:labetha",
"core:lacus",
"core:lorelei",
"core:loynis",
"core:malcom",
"core:malekith",
"core:marius",
"core:melodia",
"core:mephala",
"core:merist",
"core:mirlanda",
"core:moandor",
"core:monere",
"core:nagash",
"core:neela",
"core:nimbus",
"core:nymus",
"core:octavia",
"core:olema",
"core:oris",
"core:pasis",
"core:piquedram",
"core:pyre",
"core:rashka",
"core:rion",
"core:rissa",
"core:rosic",
"core:ryland",
"core:sandro",
"core:sanya",
"core:saurug",
"core:sephinroth",
"core:septienna",
"core:serena",
"core:shakti",
"core:shiva",
"core:sirMullich",
"core:solmyr",
"core:straker",
"core:styg",
"core:sylvia",
"core:synca",
"core:tamika",
"core:tazar",
"core:terek",
"core:thane",
"core:thant",
"core:theodorus",
"core:thorgrim",
"core:thunar",
"core:tiva",
"core:torosar ",
"core:tyraxor",
"core:tyris",
"core:ufretin",
"core:uland",
"core:verdish",
"core:vey",
"core:vidomina",
"core:vokial",
"core:voy",
"core:wystan",
"core:xarfax",
"core:xsi",
"core:xyron",
"core:yog",
"core:zubin",
"core:zydar"
]
},
"allowedSpells" : {
"anyOf" : [
"airElemental",
"airShield",
"animateDead",
"antiMagic",
"armageddon",
"berserk",
"bless",
"blind",
"bloodlust",
"chainLightning",
"clone",
"counterstrike",
"cure",
"curse",
"deathRipple",
"destroyUndead",
"dimensionDoor",
"disguise",
"dispel",
"disruptingRay",
"earthElemental",
"earthquake",
"fireElemental",
"fireShield",
"fireWall",
"fireball",
"fly",
"forceField",
"forgetfulness",
"fortune",
"frenzy",
"frostRing",
"haste",
"hypnotize",
"iceBolt",
"implosion",
"inferno",
"landMine",
"lightningBolt",
"magicArrow",
"magicMirror",
"meteorShower",
"mirth",
"misfortune",
"prayer",
"precision",
"protectAir",
"protectEarth",
"protectFire",
"protectWater",
"quicksand",
"removeObstacle",
"resurrection",
"sacrifice",
"scuttleBoat",
"shield",
"slayer",
"slow",
"sorrow",
"stoneSkin",
"summonBoat",
"teleport",
"titanBolt",
"townPortal",
"viewAir",
"viewEarth",
"visions",
"waterElemental",
"waterWalk",
"weakness"
"core:airElemental",
"core:airShield",
"core:animateDead",
"core:antiMagic",
"core:armageddon",
"core:berserk",
"core:bless",
"core:blind",
"core:bloodlust",
"core:chainLightning",
"core:clone",
"core:counterstrike",
"core:cure",
"core:curse",
"core:deathRipple",
"core:destroyUndead",
"core:dimensionDoor",
"core:disguise",
"core:dispel",
"core:disruptingRay",
"core:earthElemental",
"core:earthquake",
"core:fireElemental",
"core:fireShield",
"core:fireWall",
"core:fireball",
"core:fly",
"core:forceField",
"core:forgetfulness",
"core:fortune",
"core:frenzy",
"core:frostRing",
"core:haste",
"core:hypnotize",
"core:iceBolt",
"core:implosion",
"core:inferno",
"core:landMine",
"core:lightningBolt",
"core:magicArrow",
"core:magicMirror",
"core:meteorShower",
"core:mirth",
"core:misfortune",
"core:prayer",
"core:precision",
"core:protectAir",
"core:protectEarth",
"core:protectFire",
"core:protectWater",
"core:quicksand",
"core:removeObstacle",
"core:resurrection",
"core:sacrifice",
"core:scuttleBoat",
"core:shield",
"core:slayer",
"core:slow",
"core:sorrow",
"core:stoneSkin",
"core:summonBoat",
"core:teleport",
"core:titanBolt",
"core:townPortal",
"core:viewAir",
"core:viewEarth",
"core:visions",
"core:waterElemental",
"core:waterWalk",
"core:weakness"
]
},
"defeatIconIndex" : 3,
@ -279,7 +279,7 @@
"width" : 144
}
},
"mods" : {},
"mods" : null,
"name" : "ObjectPropertyTest v1",
"players" : {
"blue" : {
@ -317,7 +317,7 @@
"mainHero" : "hero_101",
"heroes" : {
"hero_101" : {
"type" : "ingham"
"type" : "core:ingham"
}
}
},
@ -363,5 +363,5 @@
"victoryIconIndex" : 11,
"victoryString" : "Test victoryString",
"versionMajor" : 1,
"versionMinor" : 0
"versionMinor" : 1
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -17,11 +17,11 @@
"width" : 32
}
},
"mods" : {},
"mods" : null,
"name" : "Untitled",
"players" : {},
"triggeredEvents" : {},
"victoryIconIndex" : 0,
"versionMajor" : 1,
"versionMinor" : 0
"versionMinor" : 1
}