mirror of
https://github.com/vcmi/vcmi.git
synced 2025-04-15 11:46:56 +02:00
some work on new filesystem, not tested
- one more new file - removed duplicating code - filesystem parser is now recursive - decompression should be possible if decompressed size is unknown - autotools and cmake update
This commit is contained in:
parent
4bd8a5a15b
commit
a72a294a46
@ -2,7 +2,6 @@ project(vcmiclient)
|
|||||||
cmake_minimum_required(VERSION 2.6)
|
cmake_minimum_required(VERSION 2.6)
|
||||||
|
|
||||||
include_directories(${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib)
|
include_directories(${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib)
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/BattleInterface ${CMAKE_CURRENT_SOURCE_DIR}/UIFramework)
|
|
||||||
include_directories(${SDL_INCLUDE_DIR} ${SDLIMAGE_INCLUDE_DIR} ${SDLMIXER_INCLUDE_DIR} ${SDLTTF_INCLUDE_DIR})
|
include_directories(${SDL_INCLUDE_DIR} ${SDLIMAGE_INCLUDE_DIR} ${SDLMIXER_INCLUDE_DIR} ${SDLTTF_INCLUDE_DIR})
|
||||||
include_directories(${Boost_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIR} ${FFMPEG_INCLUDE_DIR})
|
include_directories(${Boost_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIR} ${FFMPEG_INCLUDE_DIR})
|
||||||
|
|
||||||
|
@ -1,10 +1,19 @@
|
|||||||
project(libvcmi)
|
project(libvcmi)
|
||||||
cmake_minimum_required(VERSION 2.6)
|
cmake_minimum_required(VERSION 2.6)
|
||||||
|
|
||||||
include_directories(${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIRECTORY})
|
include_directories(${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIRECTORY} ${CMAKE_HOME_DIRECTORY}/lib)
|
||||||
include_directories(${SDL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
|
include_directories(${SDL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
|
||||||
|
|
||||||
set(lib_SRCS
|
set(lib_SRCS
|
||||||
|
Filesystem/CBinaryReader.cpp
|
||||||
|
Filesystem/CFilesystemLoader.cpp
|
||||||
|
Filesystem/CMemoryStream.cpp
|
||||||
|
Filesystem/CFileInfo.cpp
|
||||||
|
Filesystem/CLodArchiveLoader.cpp
|
||||||
|
Filesystem/CResourceLoader.cpp
|
||||||
|
Filesystem/CFileInputStream.cpp
|
||||||
|
Filesystem/CLodStream.cpp
|
||||||
|
Filesystem/ISimpleResourceLoader.cpp
|
||||||
BattleAction.cpp
|
BattleAction.cpp
|
||||||
BattleHex.cpp
|
BattleHex.cpp
|
||||||
BattleState.cpp
|
BattleState.cpp
|
||||||
|
@ -3,6 +3,25 @@
|
|||||||
#include <SDL_endian.h>
|
#include <SDL_endian.h>
|
||||||
#include "CInputStream.h"
|
#include "CInputStream.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||||
|
template <typename CData>
|
||||||
|
CData readLE(CData data)
|
||||||
|
{
|
||||||
|
auto dataPtr = (char*)&data;
|
||||||
|
std::reverse(dataPtr, dataPtr + sizeof(data));
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
template <typename CData>
|
||||||
|
CData readLE(CData data)
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
CBinaryReader::CBinaryReader() : stream(nullptr)
|
CBinaryReader::CBinaryReader() : stream(nullptr)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -28,101 +47,37 @@ si64 CBinaryReader::read(ui8 * data, si64 size)
|
|||||||
return stream->read(data, size);
|
return stream->read(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
ui8 CBinaryReader::readUInt8()
|
template <typename CData>
|
||||||
|
CData CBinaryReader::readInteger()
|
||||||
{
|
{
|
||||||
ui8 val;
|
CData val;
|
||||||
si64 b = stream->read(&val, 1);
|
si64 b = stream->read(reinterpret_cast<unsigned char *>(&val), sizeof(val));
|
||||||
if(b < 1)
|
if(b < sizeof(val))
|
||||||
{
|
{
|
||||||
throw std::runtime_error(getEndOfStreamExceptionMsg(1));
|
throw std::runtime_error(getEndOfStreamExceptionMsg(sizeof(val)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return val;
|
return readLE(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
si8 CBinaryReader::readInt8()
|
//FIXME: any way to do this without macro?
|
||||||
{
|
#define INSTANTIATE(datatype, methodname) \
|
||||||
si8 val;
|
datatype CBinaryReader::methodname() \
|
||||||
si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 1);
|
{ return readInteger<datatype>(); }
|
||||||
if(b < 1)
|
|
||||||
{
|
|
||||||
throw std::runtime_error(getEndOfStreamExceptionMsg(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
return val;
|
// While it is certanly possible to leave only template method
|
||||||
}
|
// but typing template parameter every time can be annoying
|
||||||
|
// and templates parameters can't be resolved by return type
|
||||||
|
INSTANTIATE(ui8, readUInt8)
|
||||||
|
INSTANTIATE(si8, readInt8)
|
||||||
|
INSTANTIATE(ui16, readUInt16)
|
||||||
|
INSTANTIATE(si16, readInt16)
|
||||||
|
INSTANTIATE(ui32, readUInt32)
|
||||||
|
INSTANTIATE(si32, readInt32)
|
||||||
|
INSTANTIATE(ui64, readUInt64)
|
||||||
|
INSTANTIATE(si64, readInt64)
|
||||||
|
|
||||||
ui16 CBinaryReader::readUInt16()
|
#undef INSTANTIATE
|
||||||
{
|
|
||||||
ui16 val;
|
|
||||||
si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 2);
|
|
||||||
if(b < 2)
|
|
||||||
{
|
|
||||||
throw std::runtime_error(getEndOfStreamExceptionMsg(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
return SDL_SwapLE16(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
si16 CBinaryReader::readInt16()
|
|
||||||
{
|
|
||||||
si16 val;
|
|
||||||
si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 2);
|
|
||||||
if(b < 2)
|
|
||||||
{
|
|
||||||
throw std::runtime_error(getEndOfStreamExceptionMsg(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
return SDL_SwapLE16(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
ui32 CBinaryReader::readUInt32()
|
|
||||||
{
|
|
||||||
ui32 val;
|
|
||||||
si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 4);
|
|
||||||
if(b < 4)
|
|
||||||
{
|
|
||||||
throw std::runtime_error(getEndOfStreamExceptionMsg(4));
|
|
||||||
}
|
|
||||||
|
|
||||||
return SDL_SwapLE32(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
si32 CBinaryReader::readInt32()
|
|
||||||
{
|
|
||||||
si32 val;
|
|
||||||
si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 4);
|
|
||||||
if(b < 4)
|
|
||||||
{
|
|
||||||
throw std::runtime_error(getEndOfStreamExceptionMsg(4));
|
|
||||||
}
|
|
||||||
|
|
||||||
return SDL_SwapLE32(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
ui64 CBinaryReader::readUInt64()
|
|
||||||
{
|
|
||||||
ui64 val;
|
|
||||||
si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 8);
|
|
||||||
if(b < 8)
|
|
||||||
{
|
|
||||||
throw std::runtime_error(getEndOfStreamExceptionMsg(8));
|
|
||||||
}
|
|
||||||
|
|
||||||
return SDL_SwapLE64(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
si64 CBinaryReader::readInt64()
|
|
||||||
{
|
|
||||||
si64 val;
|
|
||||||
si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 8);
|
|
||||||
if(b < 8)
|
|
||||||
{
|
|
||||||
throw std::runtime_error(getEndOfStreamExceptionMsg(8));
|
|
||||||
}
|
|
||||||
|
|
||||||
return SDL_SwapLE64(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CBinaryReader::getEndOfStreamExceptionMsg(long bytesToRead) const
|
std::string CBinaryReader::getEndOfStreamExceptionMsg(long bytesToRead) const
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,16 @@ class CInputStream;
|
|||||||
*/
|
*/
|
||||||
class DLL_LINKAGE CBinaryReader : public boost::noncopyable
|
class DLL_LINKAGE CBinaryReader : public boost::noncopyable
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Reads any integer. Advances the read pointer by its size.
|
||||||
|
*
|
||||||
|
* @return read integer.
|
||||||
|
*
|
||||||
|
* @throws std::runtime_error if the end of the stream was reached unexpectedly
|
||||||
|
*/
|
||||||
|
template <typename CData>
|
||||||
|
CData readInteger();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Default c-tor.
|
* Default c-tor.
|
||||||
|
@ -80,7 +80,7 @@ std::time_t CFileInfo::getDate() const
|
|||||||
return boost::filesystem::last_write_time(name);
|
return boost::filesystem::last_write_time(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<std::list<CFileInfo> > CFileInfo::listFiles(const std::string & extensionFilter /*= ""*/) const
|
std::unique_ptr<std::list<CFileInfo> > CFileInfo::listFiles(size_t depth, const std::string & extensionFilter /*= ""*/) const
|
||||||
{
|
{
|
||||||
std::unique_ptr<std::list<CFileInfo> > fileListPtr;
|
std::unique_ptr<std::list<CFileInfo> > fileListPtr;
|
||||||
|
|
||||||
@ -88,13 +88,20 @@ std::unique_ptr<std::list<CFileInfo> > CFileInfo::listFiles(const std::string &
|
|||||||
{
|
{
|
||||||
std::list<CFileInfo> * fileList = new std::list<CFileInfo>;
|
std::list<CFileInfo> * fileList = new std::list<CFileInfo>;
|
||||||
|
|
||||||
boost::filesystem::directory_iterator enddir;
|
boost::filesystem::recursive_directory_iterator enddir;
|
||||||
for(boost::filesystem::directory_iterator it(name); it != enddir; ++it)
|
for(boost::filesystem::recursive_directory_iterator it(name); it != enddir; ++it)
|
||||||
{
|
{
|
||||||
if(extensionFilter == "" || it->path().extension() == extensionFilter)
|
if (boost::filesystem::is_directory(it->status()))
|
||||||
{
|
{
|
||||||
CFileInfo file(it->path().string());
|
it.no_push(depth >= it.level());
|
||||||
fileList->push_back(file);
|
}
|
||||||
|
if(boost::filesystem::is_regular(it->status()))
|
||||||
|
{
|
||||||
|
if(extensionFilter == "" || it->path().extension() == extensionFilter)
|
||||||
|
{
|
||||||
|
CFileInfo file(it->path().string());
|
||||||
|
fileList->push_back(file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ public:
|
|||||||
* @return a list of pathnames denoting the files and directories in the directory denoted by this pathname as a unique ptr.
|
* @return a list of pathnames denoting the files and directories in the directory denoted by this pathname as a unique ptr.
|
||||||
* The array will be empty if the directory is empty. Ptr is null if the directory doesn't exist or if it isn't a directory.
|
* The array will be empty if the directory is empty. Ptr is null if the directory doesn't exist or if it isn't a directory.
|
||||||
*/
|
*/
|
||||||
std::unique_ptr<std::list<CFileInfo> > listFiles(const std::string & extensionFilter = "") const;
|
std::unique_ptr<std::list<CFileInfo> > listFiles(size_t depth, const std::string & extensionFilter = "") const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Contains the original URI(not modified) e.g. ./dir/foo.txt */
|
/** Contains the original URI(not modified) e.g. ./dir/foo.txt */
|
||||||
|
@ -9,23 +9,23 @@ CFilesystemLoader::CFilesystemLoader()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CFilesystemLoader::CFilesystemLoader(const std::string & baseDirectory)
|
CFilesystemLoader::CFilesystemLoader(const std::string & baseDirectory, size_t depth)
|
||||||
{
|
{
|
||||||
open(baseDirectory);
|
open(baseDirectory, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFilesystemLoader::CFilesystemLoader(const CFileInfo & baseDirectory)
|
CFilesystemLoader::CFilesystemLoader(const CFileInfo & baseDirectory, size_t depth)
|
||||||
{
|
{
|
||||||
open(baseDirectory);
|
open(baseDirectory, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFilesystemLoader::open(const std::string & baseDirectory)
|
void CFilesystemLoader::open(const std::string & baseDirectory, size_t depth)
|
||||||
{
|
{
|
||||||
// Indexes all files in the directory and store them
|
// Indexes all files in the directory and store them
|
||||||
this->baseDirectory = baseDirectory;
|
this->baseDirectory = baseDirectory;
|
||||||
CFileInfo directory(baseDirectory);
|
CFileInfo directory(baseDirectory);
|
||||||
std::unique_ptr<std::list<CFileInfo> > fileList = directory.listFiles();
|
std::unique_ptr<std::list<CFileInfo> > fileList = directory.listFiles(depth);
|
||||||
if(fileList == nullptr)
|
if(fileList)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Directory " + baseDirectory + " not available.");
|
throw std::runtime_error("Directory " + baseDirectory + " not available.");
|
||||||
}
|
}
|
||||||
@ -33,9 +33,9 @@ void CFilesystemLoader::open(const std::string & baseDirectory)
|
|||||||
this->fileList = std::move(*fileList);
|
this->fileList = std::move(*fileList);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFilesystemLoader::open(const CFileInfo & baseDirectory)
|
void CFilesystemLoader::open(const CFileInfo & baseDirectory, size_t depth)
|
||||||
{
|
{
|
||||||
open(baseDirectory.getName());
|
open(baseDirectory.getName(), depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CInputStream> CFilesystemLoader::load(const std::string & resourceName) const
|
std::unique_ptr<CInputStream> CFilesystemLoader::load(const std::string & resourceName) const
|
||||||
|
@ -31,10 +31,11 @@ public:
|
|||||||
* Ctor.
|
* Ctor.
|
||||||
*
|
*
|
||||||
* @param baseDirectory Specifies the base directory and their sub-directories which should be indexed.
|
* @param baseDirectory Specifies the base directory and their sub-directories which should be indexed.
|
||||||
|
* @param depth - recursion depth of subdirectories search. 0 = no recursion
|
||||||
*
|
*
|
||||||
* @throws std::runtime_error if the base directory is not a directory or if it is not available
|
* @throws std::runtime_error if the base directory is not a directory or if it is not available
|
||||||
*/
|
*/
|
||||||
explicit CFilesystemLoader(const std::string & baseDirectory);
|
explicit CFilesystemLoader(const std::string & baseDirectory, size_t depth = 16);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ctor.
|
* Ctor.
|
||||||
@ -43,7 +44,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @throws std::runtime_error if the base directory is not a directory or if it is not available
|
* @throws std::runtime_error if the base directory is not a directory or if it is not available
|
||||||
*/
|
*/
|
||||||
explicit CFilesystemLoader(const CFileInfo & baseDirectory);
|
explicit CFilesystemLoader(const CFileInfo & baseDirectory, size_t depth = 16);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a base directory to be read and indexed.
|
* Opens a base directory to be read and indexed.
|
||||||
@ -52,7 +53,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @throws std::runtime_error if the base directory is not a directory or if it is not available
|
* @throws std::runtime_error if the base directory is not a directory or if it is not available
|
||||||
*/
|
*/
|
||||||
void open(const std::string & baseDirectory);
|
void open(const std::string & baseDirectory, size_t depth);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a base directory to be read and indexed.
|
* Opens a base directory to be read and indexed.
|
||||||
@ -61,7 +62,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @throws std::runtime_error if the base directory is not a directory or if it is not available
|
* @throws std::runtime_error if the base directory is not a directory or if it is not available
|
||||||
*/
|
*/
|
||||||
void open(const CFileInfo & baseDirectory);
|
void open(const CFileInfo & baseDirectory, size_t depth);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a resource with the given resource name.
|
* Loads a resource with the given resource name.
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include "CLodArchiveLoader.h"
|
#include "CLodArchiveLoader.h"
|
||||||
#include "CFileInputStream.h"
|
#include "CFileInputStream.h"
|
||||||
#include <zlib.h>
|
|
||||||
|
|
||||||
CLodStream::CLodStream()
|
CLodStream::CLodStream()
|
||||||
{
|
{
|
||||||
@ -48,87 +47,22 @@ si64 CLodStream::read(ui8 * data, si64 size)
|
|||||||
assert(size >= archiveEntry->realSize);
|
assert(size >= archiveEntry->realSize);
|
||||||
|
|
||||||
// Read the compressed data into a buffer
|
// Read the compressed data into a buffer
|
||||||
ui8 * comp = new ui8[archiveEntry->size];
|
auto comp = std::unique_ptr<ui8[]>(new ui8[archiveEntry->size]);
|
||||||
fileStream.read(comp, archiveEntry->size);
|
fileStream.read(comp.get(), archiveEntry->size);
|
||||||
|
|
||||||
// Decompress the file
|
// Decompress the file
|
||||||
if(!decompressFile(comp, archiveEntry->size, archiveEntry->realSize, data))
|
data = CLodArchiveLoader::decompressFile(comp.get(), archiveEntry->size, archiveEntry->realSize).first;
|
||||||
|
|
||||||
|
if (!data)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("File decompression wasn't successful. Resource name: " + archiveEntry->name);
|
throw std::runtime_error("File decompression wasn't successful. Resource name: " + archiveEntry->name);
|
||||||
}
|
}
|
||||||
delete[] comp;
|
|
||||||
|
|
||||||
// We're reading the total size always
|
// We're reading the total size always
|
||||||
return archiveEntry->realSize;
|
return archiveEntry->realSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CLodStream::decompressFile(ui8 * in, int size, int realSize, ui8 * out)
|
|
||||||
{
|
|
||||||
const int WBITS = 15;
|
|
||||||
const int FCHUNK = 50000;
|
|
||||||
|
|
||||||
int ret;
|
|
||||||
unsigned have;
|
|
||||||
z_stream strm;
|
|
||||||
int latPosOut = 0;
|
|
||||||
|
|
||||||
// Allocate inflate state
|
|
||||||
strm.zalloc = Z_NULL;
|
|
||||||
strm.zfree = Z_NULL;
|
|
||||||
strm.opaque = Z_NULL;
|
|
||||||
strm.avail_in = 0;
|
|
||||||
strm.next_in = Z_NULL;
|
|
||||||
ret = inflateInit2(&strm, WBITS);
|
|
||||||
if (ret != Z_OK)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int chunkNumber = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if(size < chunkNumber * FCHUNK)
|
|
||||||
break;
|
|
||||||
strm.avail_in = std::min(FCHUNK, size - chunkNumber * FCHUNK);
|
|
||||||
if (strm.avail_in == 0)
|
|
||||||
break;
|
|
||||||
strm.next_in = in + chunkNumber * FCHUNK;
|
|
||||||
|
|
||||||
// Run inflate() on input until output buffer not full
|
|
||||||
do
|
|
||||||
{
|
|
||||||
strm.avail_out = realSize - latPosOut;
|
|
||||||
strm.next_out = out + latPosOut;
|
|
||||||
ret = inflate(&strm, Z_NO_FLUSH);
|
|
||||||
|
|
||||||
bool breakLoop = false;
|
|
||||||
switch (ret)
|
|
||||||
{
|
|
||||||
case Z_STREAM_END:
|
|
||||||
breakLoop = true;
|
|
||||||
break;
|
|
||||||
case Z_NEED_DICT:
|
|
||||||
ret = Z_DATA_ERROR;
|
|
||||||
case Z_DATA_ERROR:
|
|
||||||
case Z_MEM_ERROR:
|
|
||||||
(void)inflateEnd(&strm);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(breakLoop)
|
|
||||||
break;
|
|
||||||
|
|
||||||
have = realSize - latPosOut - strm.avail_out;
|
|
||||||
latPosOut += have;
|
|
||||||
} while (strm.avail_out == 0);
|
|
||||||
|
|
||||||
++chunkNumber;
|
|
||||||
} while (ret != Z_STREAM_END);
|
|
||||||
|
|
||||||
// Clean up and return
|
|
||||||
(void)inflateEnd(&strm);
|
|
||||||
return ret == Z_STREAM_END ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
si64 CLodStream::seek(si64 position)
|
si64 CLodStream::seek(si64 position)
|
||||||
{
|
{
|
||||||
return fileStream.seek(archiveEntry->offset + position);
|
return fileStream.seek(archiveEntry->offset + position);
|
||||||
|
@ -96,15 +96,6 @@ public:
|
|||||||
void close();
|
void close();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
|
||||||
* Decompresses an archive entry.
|
|
||||||
*
|
|
||||||
* @param in A pointer to the compressed data array
|
|
||||||
* @param size The size of the compressed data array
|
|
||||||
* @param realSize The size of the decompressed real size of the entry
|
|
||||||
* @param out
|
|
||||||
*/
|
|
||||||
bool decompressFile(ui8 * in, int size, int realSize, ui8 * out);
|
|
||||||
|
|
||||||
/** The file stream for reading from the LOD archive. */
|
/** The file stream for reading from the LOD archive. */
|
||||||
CFileInputStream fileStream;
|
CFileInputStream fileStream;
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
CResourceLoader * CResourceLoaderFactory::resourceLoader = nullptr;
|
CResourceLoader * CResourceLoaderFactory::resourceLoader = nullptr;
|
||||||
|
|
||||||
ResourceIdentifier::ResourceIdentifier() : type(EResType::OTHER)
|
ResourceIdentifier::ResourceIdentifier()
|
||||||
|
:type(EResType::OTHER)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceIdentifier::ResourceIdentifier(const std::string & name, EResType type) : name(name), type(type)
|
ResourceIdentifier::ResourceIdentifier(const std::string & name, EResType type) : name(name), type(type)
|
||||||
@ -38,28 +38,29 @@ void ResourceIdentifier::setType(EResType type)
|
|||||||
|
|
||||||
CResourceLoader::CResourceLoader()
|
CResourceLoader::CResourceLoader()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CResourceLoader::~CResourceLoader()
|
CResourceLoader::~CResourceLoader()
|
||||||
{
|
{
|
||||||
// Delete all loader objects
|
// Delete all loader objects
|
||||||
for(auto it = loaders.begin(); it != loaders.end(); ++it)
|
BOOST_FOREACH ( ISimpleResourceLoader* it, loaders)
|
||||||
{
|
{
|
||||||
delete *it;
|
delete it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CInputStream> CResourceLoader::load(const ResourceIdentifier & resourceIdent) const
|
std::unique_ptr<CInputStream> CResourceLoader::load(const ResourceIdentifier & resourceIdent) const
|
||||||
{
|
{
|
||||||
if(!existsResource(resourceIdent))
|
auto resource = resources.find(resourceIdent);
|
||||||
|
|
||||||
|
if(resource == resources.end())
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Resource with name " + resourceIdent.getName() + " and type "
|
throw std::runtime_error("Resource with name " + resourceIdent.getName() + " and type "
|
||||||
+ EResTypeHelper::getEResTypeAsString(resourceIdent.getType()) + " wasn't found.");
|
+ EResTypeHelper::getEResTypeAsString(resourceIdent.getType()) + " wasn't found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the last added resource(most overriden)
|
// get the last added resource(most overriden)
|
||||||
const ResourceLocator & locator = resources.at(resourceIdent).back();
|
const ResourceLocator & locator = resource->second.back();
|
||||||
|
|
||||||
// load the resource and return it
|
// load the resource and return it
|
||||||
return locator.getLoader()->load(locator.getResourceName());
|
return locator.getLoader()->load(locator.getResourceName());
|
||||||
@ -68,14 +69,7 @@ std::unique_ptr<CInputStream> CResourceLoader::load(const ResourceIdentifier & r
|
|||||||
bool CResourceLoader::existsResource(const ResourceIdentifier & resourceIdent) const
|
bool CResourceLoader::existsResource(const ResourceIdentifier & resourceIdent) const
|
||||||
{
|
{
|
||||||
// Check if resource is registered
|
// Check if resource is registered
|
||||||
if(resources.find(resourceIdent) != resources.end())
|
return resources.find(resourceIdent) != resources.end();
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CResourceLoader::addLoader(ISimpleResourceLoader * loader)
|
void CResourceLoader::addLoader(ISimpleResourceLoader * loader)
|
||||||
@ -85,9 +79,8 @@ void CResourceLoader::addLoader(ISimpleResourceLoader * loader)
|
|||||||
// Get entries and add them to the resources list
|
// Get entries and add them to the resources list
|
||||||
const std::list<std::string> & entries = loader->getEntries();
|
const std::list<std::string> & entries = loader->getEntries();
|
||||||
|
|
||||||
for(auto it = entries.begin(); it != entries.end(); ++it)
|
BOOST_FOREACH (const std::string & entry, entries)
|
||||||
{
|
{
|
||||||
std::string entry = *it;
|
|
||||||
CFileInfo file(entry);
|
CFileInfo file(entry);
|
||||||
|
|
||||||
// Create identifier and locator and add them to the resources list
|
// Create identifier and locator and add them to the resources list
|
||||||
@ -137,118 +130,68 @@ EResType EResTypeHelper::getTypeFromExtension(std::string extension)
|
|||||||
{
|
{
|
||||||
boost::to_upper(extension);
|
boost::to_upper(extension);
|
||||||
|
|
||||||
if(extension == ".TXT" || extension == ".JSON")
|
static const std::map<std::string, EResType> stringToRes =
|
||||||
{
|
boost::assign::map_list_of
|
||||||
return EResType::TEXT;
|
(".TXT", EResType::TEXT)
|
||||||
}
|
(".JSON", EResType::TEXT)
|
||||||
else if(extension == ".DEF" || extension == ".JSON")
|
(".DEF", EResType::ANIMATION)
|
||||||
{
|
(".MSK", EResType::MASK)
|
||||||
return EResType::ANIMATION;
|
(".MSG", EResType::MASK)
|
||||||
}
|
(".H3C", EResType::CAMPAIGN)
|
||||||
else if(extension == ".MSK" || extension == ".MSG")
|
(".H3M", EResType::MAP)
|
||||||
{
|
(".FNT", EResType::FONT)
|
||||||
return EResType::MASK;
|
(".BMP", EResType::IMAGE)
|
||||||
}
|
(".JPG", EResType::IMAGE)
|
||||||
else if(extension == ".H3C")
|
(".PCX", EResType::IMAGE)
|
||||||
{
|
(".PNG", EResType::IMAGE)
|
||||||
return EResType::CAMPAIGN;
|
(".TGA", EResType::IMAGE)
|
||||||
}
|
(".WAV", EResType::SOUND)
|
||||||
else if(extension == ".H3M")
|
(".SMK", EResType::VIDEO)
|
||||||
{
|
(".BIK", EResType::VIDEO)
|
||||||
return EResType::MAP;
|
(".MJPG", EResType::VIDEO)
|
||||||
}
|
(".MP3", EResType::MUSIC)
|
||||||
else if(extension == ".FNT")
|
(".OGG", EResType::MUSIC)
|
||||||
{
|
(".LOD", EResType::ARCHIVE)
|
||||||
return EResType::FONT;
|
(".VID", EResType::ARCHIVE)
|
||||||
}
|
(".SND", EResType::ARCHIVE)
|
||||||
else if(extension == ".BMP" || extension == ".JPG" || extension == ".PCX" || extension == ".PNG" || extension == ".TGA")
|
(".VCGM1", EResType::CLIENT_SAVEGAME)
|
||||||
{
|
(".VLGM1", EResType::LIB_SAVEGAME)
|
||||||
return EResType::IMAGE;
|
(".VSGM1", EResType::SERVER_SAVEGAME);
|
||||||
}
|
|
||||||
else if(extension == ".WAV")
|
auto iter = stringToRes.find(extension);
|
||||||
{
|
if (iter == stringToRes.end())
|
||||||
return EResType::SOUND;
|
|
||||||
}
|
|
||||||
else if(extension == ".SMK" || extension == ".BIK")
|
|
||||||
{
|
|
||||||
return EResType::VIDEO;
|
|
||||||
}
|
|
||||||
else if(extension == ".MP3" || extension == ".OGG")
|
|
||||||
{
|
|
||||||
return EResType::MUSIC;
|
|
||||||
}
|
|
||||||
else if(extension == ".ZIP" || extension == ".TAR.GZ" || extension == ".LOD" || extension == ".VID" || extension == ".SND")
|
|
||||||
{
|
|
||||||
return EResType::ARCHIVE;
|
|
||||||
}
|
|
||||||
else if(extension == ".VLGM1")
|
|
||||||
{
|
|
||||||
return EResType::SAVEGAME;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return EResType::OTHER;
|
return EResType::OTHER;
|
||||||
}
|
return iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EResTypeHelper::getEResTypeAsString(EResType type)
|
std::string EResTypeHelper::getEResTypeAsString(EResType type)
|
||||||
{
|
{
|
||||||
if(type == EResType::ANIMATION)
|
|
||||||
{
|
|
||||||
return "ANIMATION";
|
|
||||||
}
|
|
||||||
else if(type == EResType::ANY)
|
|
||||||
{
|
|
||||||
return "ANY";
|
|
||||||
}
|
|
||||||
else if(type == EResType::ARCHIVE)
|
|
||||||
{
|
|
||||||
return "ARCHIVE";
|
|
||||||
}
|
|
||||||
else if(type == EResType::CAMPAIGN)
|
|
||||||
{
|
|
||||||
return "CAMPAIGN";
|
|
||||||
}
|
|
||||||
else if(type == EResType::FONT)
|
|
||||||
{
|
|
||||||
return "FONT";
|
|
||||||
}
|
|
||||||
else if(type == EResType::IMAGE)
|
|
||||||
{
|
|
||||||
return "IMAGE";
|
|
||||||
}
|
|
||||||
else if(type == EResType::MAP)
|
|
||||||
{
|
|
||||||
return "MAP";
|
|
||||||
}
|
|
||||||
else if(type == EResType::MASK)
|
|
||||||
{
|
|
||||||
return "MASK";
|
|
||||||
}
|
|
||||||
else if(type == EResType::MUSIC)
|
|
||||||
{
|
|
||||||
return "MUSIC";
|
|
||||||
}
|
|
||||||
else if(type == EResType::OTHER)
|
|
||||||
{
|
|
||||||
return "OTHER";
|
|
||||||
}
|
|
||||||
else if(type == EResType::SAVEGAME)
|
|
||||||
{
|
|
||||||
return "SAVEGAME";
|
|
||||||
}
|
|
||||||
else if(type == EResType::SOUND)
|
|
||||||
{
|
|
||||||
return "SOUND";
|
|
||||||
}
|
|
||||||
else if(type == EResType::TEXT)
|
|
||||||
{
|
|
||||||
return "TEXT";
|
|
||||||
}
|
|
||||||
else if(type == EResType::VIDEO)
|
|
||||||
{
|
|
||||||
return "VIDEO";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
#define MAP_ENUM(value) (EResType::value, "value")
|
||||||
|
|
||||||
|
static const std::map<EResType, std::string> stringToRes = boost::assign::map_list_of
|
||||||
|
MAP_ENUM(ANY)
|
||||||
|
MAP_ENUM(TEXT)
|
||||||
|
MAP_ENUM(ANIMATION)
|
||||||
|
MAP_ENUM(MASK)
|
||||||
|
MAP_ENUM(CAMPAIGN)
|
||||||
|
MAP_ENUM(MAP)
|
||||||
|
MAP_ENUM(FONT)
|
||||||
|
MAP_ENUM(IMAGE)
|
||||||
|
MAP_ENUM(VIDEO)
|
||||||
|
MAP_ENUM(SOUND)
|
||||||
|
MAP_ENUM(MUSIC)
|
||||||
|
MAP_ENUM(ARCHIVE)
|
||||||
|
MAP_ENUM(CLIENT_SAVEGAME)
|
||||||
|
MAP_ENUM(LIB_SAVEGAME)
|
||||||
|
MAP_ENUM(SERVER_SAVEGAME)
|
||||||
|
MAP_ENUM(OTHER);
|
||||||
|
|
||||||
|
#undef MAP_ENUM
|
||||||
|
|
||||||
|
auto iter = stringToRes.find(type);
|
||||||
|
assert(iter != stringToRes.end());
|
||||||
|
|
||||||
|
return iter->second;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ class ISimpleResourceLoader;
|
|||||||
*
|
*
|
||||||
* Supported file extensions:
|
* Supported file extensions:
|
||||||
*
|
*
|
||||||
* Text: .json
|
* Text: .txt .json
|
||||||
* Animation: .def
|
* Animation: .def
|
||||||
* Mask: .msk
|
* Mask: .msk
|
||||||
* Campaign: .h3c
|
* Campaign: .h3c
|
||||||
@ -29,10 +29,10 @@ class ISimpleResourceLoader;
|
|||||||
* Font: .fnt
|
* Font: .fnt
|
||||||
* Image: .bmp, .jpg, .pcx, .png, .tga
|
* Image: .bmp, .jpg, .pcx, .png, .tga
|
||||||
* Sound: .wav
|
* Sound: .wav
|
||||||
* Video: .smk, .bik
|
* Video: .smk, .bik .mjpg
|
||||||
* Music: .mp3, .ogg
|
* Music: .mp3, .ogg
|
||||||
* Archive: .lod, .snd, .vid, .zip, .tar.gz
|
* Archive: .lod, .snd, .vid
|
||||||
* Savegame: .vlgm1
|
* Savegame: .v*gm1
|
||||||
*/
|
*/
|
||||||
enum EResType
|
enum EResType
|
||||||
{
|
{
|
||||||
@ -48,7 +48,9 @@ enum EResType
|
|||||||
SOUND,
|
SOUND,
|
||||||
MUSIC,
|
MUSIC,
|
||||||
ARCHIVE,
|
ARCHIVE,
|
||||||
SAVEGAME,
|
CLIENT_SAVEGAME,
|
||||||
|
LIB_SAVEGAME,
|
||||||
|
SERVER_SAVEGAME,
|
||||||
OTHER
|
OTHER
|
||||||
};
|
};
|
||||||
|
|
||||||
|
103
lib/Filesystem/ISimpleResourceLoader.cpp
Normal file
103
lib/Filesystem/ISimpleResourceLoader.cpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
#include "StdInc.h"
|
||||||
|
#include "ISimpleResourceLoader.h"
|
||||||
|
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
std::pair<ui8*, size_t> ISimpleResourceLoader::decompressFile(ui8 * in, size_t size, size_t realSize)
|
||||||
|
{
|
||||||
|
std::pair<ui8*, size_t> retError(nullptr, 0);
|
||||||
|
|
||||||
|
if (realSize == 0)
|
||||||
|
realSize = 16 * 1024;
|
||||||
|
|
||||||
|
std::unique_ptr<ui8[]> out(new ui8[realSize]);
|
||||||
|
|
||||||
|
const int WBITS = 15;
|
||||||
|
const int FCHUNK = 50000;
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
z_stream strm;
|
||||||
|
int lastPosOut = 0;
|
||||||
|
|
||||||
|
// Allocate inflate state
|
||||||
|
strm.zalloc = Z_NULL;
|
||||||
|
strm.zfree = Z_NULL;
|
||||||
|
strm.opaque = Z_NULL;
|
||||||
|
strm.avail_in = 0;
|
||||||
|
strm.next_in = Z_NULL;
|
||||||
|
ret = inflateInit2(&strm, WBITS);
|
||||||
|
if (ret != Z_OK)
|
||||||
|
return retError;
|
||||||
|
|
||||||
|
int chunkNumber = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(size < chunkNumber * FCHUNK)
|
||||||
|
break;
|
||||||
|
strm.avail_in = std::min<size_t>(FCHUNK, size - chunkNumber * FCHUNK);
|
||||||
|
if (strm.avail_in == 0)
|
||||||
|
break;
|
||||||
|
strm.next_in = in + chunkNumber * FCHUNK;
|
||||||
|
|
||||||
|
// Run inflate() on input until output buffer not full
|
||||||
|
do
|
||||||
|
{
|
||||||
|
strm.avail_out = realSize - lastPosOut;
|
||||||
|
strm.next_out = out.get() + lastPosOut;
|
||||||
|
ret = inflate(&strm, Z_NO_FLUSH);
|
||||||
|
|
||||||
|
bool breakLoop = false;
|
||||||
|
switch (ret)
|
||||||
|
{
|
||||||
|
case Z_STREAM_END:
|
||||||
|
breakLoop = true;
|
||||||
|
break;
|
||||||
|
case Z_NEED_DICT:
|
||||||
|
ret = Z_DATA_ERROR;
|
||||||
|
case Z_DATA_ERROR:
|
||||||
|
inflateEnd(&strm);
|
||||||
|
return retError;
|
||||||
|
case Z_MEM_ERROR:
|
||||||
|
{
|
||||||
|
//not enough memory. Allocate bigger buffer and try again
|
||||||
|
realSize *= 2;
|
||||||
|
std::unique_ptr<ui8[]> newOut(new ui8[realSize]);
|
||||||
|
std::copy(out.get(), out.get() + strm.total_out, newOut.get());
|
||||||
|
out.reset(newOut.release());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(breakLoop)
|
||||||
|
break;
|
||||||
|
|
||||||
|
lastPosOut = realSize - strm.avail_out;
|
||||||
|
}
|
||||||
|
while (strm.avail_out == 0);
|
||||||
|
|
||||||
|
++chunkNumber;
|
||||||
|
}
|
||||||
|
while (ret != Z_STREAM_END);
|
||||||
|
|
||||||
|
// Clean up and return
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
ret = inflateEnd(&strm);
|
||||||
|
|
||||||
|
switch (ret)
|
||||||
|
{
|
||||||
|
case Z_STREAM_END:
|
||||||
|
//TODO: trim buffer? may be too time consuming
|
||||||
|
return std::make_pair(out.release(), realSize - strm.avail_out);
|
||||||
|
case Z_BUF_ERROR:
|
||||||
|
{
|
||||||
|
//not enough memory. Allocate bigger buffer and try again
|
||||||
|
realSize *= 2;
|
||||||
|
std::unique_ptr<ui8[]> newOut(new ui8[realSize]);
|
||||||
|
std::copy(out.get(), out.get() + strm.total_out, newOut.get());
|
||||||
|
out.reset(newOut.release());
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return retError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,16 @@
|
|||||||
class DLL_LINKAGE ISimpleResourceLoader
|
class DLL_LINKAGE ISimpleResourceLoader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* Decompresses an archive entry.
|
||||||
|
*
|
||||||
|
* @param in A pointer to the compressed data array
|
||||||
|
* @param size The size of the compressed data array
|
||||||
|
* @param realSize The size of the decompressed real size of the entry or 0 if not known (slower)
|
||||||
|
* @returns pair(decompressed data, size)
|
||||||
|
*/
|
||||||
|
static std::pair<ui8*, size_t> decompressFile(ui8 * in, size_t size, size_t realSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dtor.
|
* Dtor.
|
||||||
*/
|
*/
|
||||||
|
@ -15,6 +15,7 @@ libvcmi_la_SOURCES = \
|
|||||||
Filesystem/CLodStream.cpp \
|
Filesystem/CLodStream.cpp \
|
||||||
Filesystem/CMemoryStream.cpp \
|
Filesystem/CMemoryStream.cpp \
|
||||||
Filesystem/CResourceLoader.cpp \
|
Filesystem/CResourceLoader.cpp \
|
||||||
|
Filesystem/ISimpleResourceLoader.cpp \
|
||||||
BattleAction.cpp \
|
BattleAction.cpp \
|
||||||
BattleAction.h \
|
BattleAction.h \
|
||||||
BattleState.cpp \
|
BattleState.cpp \
|
||||||
|
@ -90,22 +90,22 @@ am_libvcmi_la_OBJECTS = libvcmi_la-CBinaryReader.lo \
|
|||||||
libvcmi_la-CFilesystemLoader.lo \
|
libvcmi_la-CFilesystemLoader.lo \
|
||||||
libvcmi_la-CLodArchiveLoader.lo libvcmi_la-CLodStream.lo \
|
libvcmi_la-CLodArchiveLoader.lo libvcmi_la-CLodStream.lo \
|
||||||
libvcmi_la-CMemoryStream.lo libvcmi_la-CResourceLoader.lo \
|
libvcmi_la-CMemoryStream.lo libvcmi_la-CResourceLoader.lo \
|
||||||
libvcmi_la-BattleAction.lo libvcmi_la-BattleState.lo \
|
libvcmi_la-ISimpleResourceLoader.lo libvcmi_la-BattleAction.lo \
|
||||||
libvcmi_la-CArtHandler.lo libvcmi_la-CBuildingHandler.lo \
|
libvcmi_la-BattleState.lo libvcmi_la-CArtHandler.lo \
|
||||||
libvcmi_la-CCampaignHandler.lo libvcmi_la-CConsoleHandler.lo \
|
libvcmi_la-CBuildingHandler.lo libvcmi_la-CCampaignHandler.lo \
|
||||||
libvcmi_la-CCreatureHandler.lo libvcmi_la-CCreatureSet.lo \
|
libvcmi_la-CConsoleHandler.lo libvcmi_la-CCreatureHandler.lo \
|
||||||
libvcmi_la-CDefObjInfoHandler.lo libvcmi_la-CFileUtility.lo \
|
libvcmi_la-CCreatureSet.lo libvcmi_la-CDefObjInfoHandler.lo \
|
||||||
libvcmi_la-CGameInterface.lo libvcmi_la-CGameState.lo \
|
libvcmi_la-CFileUtility.lo libvcmi_la-CGameInterface.lo \
|
||||||
libvcmi_la-CGeneralTextHandler.lo libvcmi_la-CHeroHandler.lo \
|
libvcmi_la-CGameState.lo libvcmi_la-CGeneralTextHandler.lo \
|
||||||
libvcmi_la-CLodHandler.lo libvcmi_la-CLogger.lo \
|
libvcmi_la-CHeroHandler.lo libvcmi_la-CLodHandler.lo \
|
||||||
libvcmi_la-CMapInfo.lo libvcmi_la-CObjectHandler.lo \
|
libvcmi_la-CLogger.lo libvcmi_la-CMapInfo.lo \
|
||||||
libvcmi_la-CObstacleInstance.lo libvcmi_la-CSpellHandler.lo \
|
libvcmi_la-CObjectHandler.lo libvcmi_la-CObstacleInstance.lo \
|
||||||
libvcmi_la-CTownHandler.lo libvcmi_la-CThreadHelper.lo \
|
libvcmi_la-CSpellHandler.lo libvcmi_la-CTownHandler.lo \
|
||||||
libvcmi_la-Connection.lo libvcmi_la-HeroBonus.lo \
|
libvcmi_la-CThreadHelper.lo libvcmi_la-Connection.lo \
|
||||||
libvcmi_la-IGameCallback.lo libvcmi_la-JsonNode.lo \
|
libvcmi_la-HeroBonus.lo libvcmi_la-IGameCallback.lo \
|
||||||
libvcmi_la-NetPacksLib.lo libvcmi_la-ResourceSet.lo \
|
libvcmi_la-JsonNode.lo libvcmi_la-NetPacksLib.lo \
|
||||||
libvcmi_la-BattleHex.lo libvcmi_la-VCMI_Lib.lo \
|
libvcmi_la-ResourceSet.lo libvcmi_la-BattleHex.lo \
|
||||||
libvcmi_la-map.lo
|
libvcmi_la-VCMI_Lib.lo libvcmi_la-map.lo
|
||||||
libvcmi_la_OBJECTS = $(am_libvcmi_la_OBJECTS)
|
libvcmi_la_OBJECTS = $(am_libvcmi_la_OBJECTS)
|
||||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||||
@ -308,6 +308,7 @@ libvcmi_la_SOURCES = \
|
|||||||
Filesystem/CLodStream.cpp \
|
Filesystem/CLodStream.cpp \
|
||||||
Filesystem/CMemoryStream.cpp \
|
Filesystem/CMemoryStream.cpp \
|
||||||
Filesystem/CResourceLoader.cpp \
|
Filesystem/CResourceLoader.cpp \
|
||||||
|
Filesystem/ISimpleResourceLoader.cpp \
|
||||||
BattleAction.cpp \
|
BattleAction.cpp \
|
||||||
BattleAction.h \
|
BattleAction.h \
|
||||||
BattleState.cpp \
|
BattleState.cpp \
|
||||||
@ -487,6 +488,7 @@ distclean-compile:
|
|||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-Connection.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-Connection.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-HeroBonus.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-HeroBonus.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-IGameCallback.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-IGameCallback.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-ISimpleResourceLoader.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-JsonNode.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-JsonNode.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-NetPacksLib.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-NetPacksLib.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-ResourceSet.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-ResourceSet.Plo@am__quote@
|
||||||
@ -570,6 +572,13 @@ libvcmi_la-CResourceLoader.lo: Filesystem/CResourceLoader.cpp
|
|||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -c -o libvcmi_la-CResourceLoader.lo `test -f 'Filesystem/CResourceLoader.cpp' || echo '$(srcdir)/'`Filesystem/CResourceLoader.cpp
|
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -c -o libvcmi_la-CResourceLoader.lo `test -f 'Filesystem/CResourceLoader.cpp' || echo '$(srcdir)/'`Filesystem/CResourceLoader.cpp
|
||||||
|
|
||||||
|
libvcmi_la-ISimpleResourceLoader.lo: Filesystem/ISimpleResourceLoader.cpp
|
||||||
|
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-ISimpleResourceLoader.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-ISimpleResourceLoader.Tpo -c -o libvcmi_la-ISimpleResourceLoader.lo `test -f 'Filesystem/ISimpleResourceLoader.cpp' || echo '$(srcdir)/'`Filesystem/ISimpleResourceLoader.cpp
|
||||||
|
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-ISimpleResourceLoader.Tpo $(DEPDIR)/libvcmi_la-ISimpleResourceLoader.Plo
|
||||||
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='Filesystem/ISimpleResourceLoader.cpp' object='libvcmi_la-ISimpleResourceLoader.lo' libtool=yes @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -c -o libvcmi_la-ISimpleResourceLoader.lo `test -f 'Filesystem/ISimpleResourceLoader.cpp' || echo '$(srcdir)/'`Filesystem/ISimpleResourceLoader.cpp
|
||||||
|
|
||||||
libvcmi_la-BattleAction.lo: BattleAction.cpp
|
libvcmi_la-BattleAction.lo: BattleAction.cpp
|
||||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-BattleAction.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-BattleAction.Tpo -c -o libvcmi_la-BattleAction.lo `test -f 'BattleAction.cpp' || echo '$(srcdir)/'`BattleAction.cpp
|
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-BattleAction.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-BattleAction.Tpo -c -o libvcmi_la-BattleAction.lo `test -f 'BattleAction.cpp' || echo '$(srcdir)/'`BattleAction.cpp
|
||||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-BattleAction.Tpo $(DEPDIR)/libvcmi_la-BattleAction.Plo
|
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-BattleAction.Tpo $(DEPDIR)/libvcmi_la-BattleAction.Plo
|
||||||
|
@ -64,7 +64,7 @@ template <typename T> class CApplyOnGH;
|
|||||||
class CBaseForGHApply
|
class CBaseForGHApply
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual bool applyOnGH(CGameHandler *gh, CConnection *c, void *pack, ui8 player) const =0;
|
virtual bool applyOnGH(CGameHandler *gh, CConnection *c, void *pack, ui8 player) const =0;
|
||||||
virtual ~CBaseForGHApply(){}
|
virtual ~CBaseForGHApply(){}
|
||||||
template<typename U> static CBaseForGHApply *getApplier(const U * t=NULL)
|
template<typename U> static CBaseForGHApply *getApplier(const U * t=NULL)
|
||||||
{
|
{
|
||||||
@ -201,14 +201,14 @@ void CGameHandler::levelUpHero(int ID, int skill)
|
|||||||
void CGameHandler::levelUpHero(int ID)
|
void CGameHandler::levelUpHero(int ID)
|
||||||
{
|
{
|
||||||
CGHeroInstance *hero = static_cast<CGHeroInstance *>(gs->map->objects[ID].get());
|
CGHeroInstance *hero = static_cast<CGHeroInstance *>(gs->map->objects[ID].get());
|
||||||
|
|
||||||
// required exp for at least 1 lvl-up hasn't been reached
|
// required exp for at least 1 lvl-up hasn't been reached
|
||||||
if (hero->exp < VLC->heroh->reqExp(hero->level+1))
|
if (hero->exp < VLC->heroh->reqExp(hero->level+1))
|
||||||
{
|
{
|
||||||
afterBattleCallback();
|
afterBattleCallback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//give prim skill
|
//give prim skill
|
||||||
tlog5 << hero->name <<" got level "<<hero->level<<std::endl;
|
tlog5 << hero->name <<" got level "<<hero->level<<std::endl;
|
||||||
int r = rand()%100, pom=0, x=0;
|
int r = rand()%100, pom=0, x=0;
|
||||||
@ -219,7 +219,7 @@ void CGameHandler::levelUpHero(int ID)
|
|||||||
if(r<pom)
|
if(r<pom)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tlog5 << "The hero gets the primary skill with the no. " << x << " with a probability of " << r << "%." << std::endl;
|
tlog5 << "The hero gets the primary skill with the no. " << x << " with a probability of " << r << "%." << std::endl;
|
||||||
SetPrimSkill sps;
|
SetPrimSkill sps;
|
||||||
sps.id = ID;
|
sps.id = ID;
|
||||||
sps.which = x;
|
sps.which = x;
|
||||||
@ -427,7 +427,7 @@ void CGameHandler::changePrimSkill(int ID, int which, si64 val, bool abs)
|
|||||||
sps.abs = abs;
|
sps.abs = abs;
|
||||||
sps.val = val;
|
sps.val = val;
|
||||||
sendAndApply(&sps);
|
sendAndApply(&sps);
|
||||||
|
|
||||||
//only for exp - hero may level up
|
//only for exp - hero may level up
|
||||||
if (which == 4)
|
if (which == 4)
|
||||||
{
|
{
|
||||||
@ -492,7 +492,7 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
|
|||||||
if(bEndArmy1->tempOwner<GameConstants::PLAYER_LIMIT)
|
if(bEndArmy1->tempOwner<GameConstants::PLAYER_LIMIT)
|
||||||
states.setFlag(bEndArmy1->tempOwner, &PlayerStatus::engagedIntoBattle, false);
|
states.setFlag(bEndArmy1->tempOwner, &PlayerStatus::engagedIntoBattle, false);
|
||||||
if(bEndArmy2 && bEndArmy2->tempOwner<GameConstants::PLAYER_LIMIT)
|
if(bEndArmy2 && bEndArmy2->tempOwner<GameConstants::PLAYER_LIMIT)
|
||||||
states.setFlag(bEndArmy2->tempOwner, &PlayerStatus::engagedIntoBattle, false);
|
states.setFlag(bEndArmy2->tempOwner, &PlayerStatus::engagedIntoBattle, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//end battle, remove all info, free memory
|
//end battle, remove all info, free memory
|
||||||
@ -683,7 +683,7 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
|
|||||||
afterBattleCallback();
|
afterBattleCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (necroSlot != -1)
|
if (necroSlot != -1)
|
||||||
{
|
{
|
||||||
winnerHero->showNecromancyDialog(raisedStack);
|
winnerHero->showNecromancyDialog(raisedStack);
|
||||||
addToSlot(StackLocation(winnerHero, necroSlot), raisedStack.type, raisedStack.count);
|
addToSlot(StackLocation(winnerHero, necroSlot), raisedStack.type, raisedStack.count);
|
||||||
@ -701,7 +701,7 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
|
|||||||
{
|
{
|
||||||
visitObjectOnTile(*getTile(winnerHero->getPosition()), winnerHero);
|
visitObjectOnTile(*getTile(winnerHero->getPosition()), winnerHero);
|
||||||
}
|
}
|
||||||
visitObjectAfterVictory = false;
|
visitObjectAfterVictory = false;
|
||||||
|
|
||||||
winLoseHandle(1<<sides[0] | 1<<sides[1]); //handle victory/loss of engaged players
|
winLoseHandle(1<<sides[0] | 1<<sides[1]); //handle victory/loss of engaged players
|
||||||
|
|
||||||
@ -767,7 +767,7 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
|
|||||||
bat.flags |= BattleAttack::BALLISTA_DOUBLE_DMG;
|
bat.flags |= BattleAttack::BALLISTA_DOUBLE_DMG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// only primary target
|
// only primary target
|
||||||
applyBattleEffects(bat, att, def, distance, false);
|
applyBattleEffects(bat, att, def, distance, false);
|
||||||
|
|
||||||
if (!bat.shot()) //multiple-hex attack - only in meele
|
if (!bat.shot()) //multiple-hex attack - only in meele
|
||||||
@ -865,7 +865,7 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
|
|||||||
boost::unique_lock<boost::mutex> lock(*c.rmx);
|
boost::unique_lock<boost::mutex> lock(*c.rmx);
|
||||||
c >> player >> requestID >> pack; //get the package
|
c >> player >> requestID >> pack; //get the package
|
||||||
packType = typeList.getTypeID(pack); //get the id of type
|
packType = typeList.getTypeID(pack); //get the id of type
|
||||||
|
|
||||||
tlog5 << boost::format("Received client message (request %d by player %d) of type with ID=%d (%s).\n")
|
tlog5 << boost::format("Received client message (request %d by player %d) of type with ID=%d (%s).\n")
|
||||||
% requestID % (int)player % packType % typeid(*pack).name();
|
% requestID % (int)player % packType % typeid(*pack).name();
|
||||||
}
|
}
|
||||||
@ -912,7 +912,7 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
|
|||||||
tlog1 << e.what() << std::endl;
|
tlog1 << e.what() << std::endl;
|
||||||
end2 = true;
|
end2 = true;
|
||||||
}
|
}
|
||||||
//HANDLE_EXCEPTION(end2 = true);
|
HANDLE_EXCEPTION(end2 = true);
|
||||||
|
|
||||||
tlog1 << "Ended handling connection\n";
|
tlog1 << "Ended handling connection\n";
|
||||||
}
|
}
|
||||||
@ -1010,15 +1010,15 @@ startWalking:
|
|||||||
for(; v >= tilesToMove; --v)
|
for(; v >= tilesToMove; --v)
|
||||||
{
|
{
|
||||||
BattleHex hex = path.first[v];
|
BattleHex hex = path.first[v];
|
||||||
tiles.push_back(hex);
|
tiles.push_back(hex);
|
||||||
|
|
||||||
if((obstacle = battleGetObstacleOnPos(hex, false)))
|
if((obstacle = battleGetObstacleOnPos(hex, false)))
|
||||||
{
|
{
|
||||||
//we walked onto something, so we finalize this portion of stack movement check into obstacle
|
//we walked onto something, so we finalize this portion of stack movement check into obstacle
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tiles.size() > 0)
|
if (tiles.size() > 0)
|
||||||
{
|
{
|
||||||
//commit movement
|
//commit movement
|
||||||
@ -1064,7 +1064,7 @@ CGameHandler::CGameHandler(void)
|
|||||||
IObjectInterface::cb = this;
|
IObjectInterface::cb = this;
|
||||||
applier = new CApplier<CBaseForGHApply>;
|
applier = new CApplier<CBaseForGHApply>;
|
||||||
registerTypes3(*applier);
|
registerTypes3(*applier);
|
||||||
visitObjectAfterVictory = false;
|
visitObjectAfterVictory = false;
|
||||||
battleEndCallback = NULL;
|
battleEndCallback = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1110,18 +1110,18 @@ void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=fa
|
|||||||
ssi.tid = town->id;
|
ssi.tid = town->id;
|
||||||
ssi.creatures = town->creatures;
|
ssi.creatures = town->creatures;
|
||||||
ssi.creatures[GameConstants::CREATURES_PER_TOWN].second.clear();//remove old one
|
ssi.creatures[GameConstants::CREATURES_PER_TOWN].second.clear();//remove old one
|
||||||
|
|
||||||
const std::vector<ConstTransitivePtr<CGDwelling> > &dwellings = p->dwellings;
|
const std::vector<ConstTransitivePtr<CGDwelling> > &dwellings = p->dwellings;
|
||||||
if (dwellings.empty())//no dwellings - just remove
|
if (dwellings.empty())//no dwellings - just remove
|
||||||
{
|
{
|
||||||
sendAndApply(&ssi);
|
sendAndApply(&ssi);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui32 dwellpos = rand()%dwellings.size();//take random dwelling
|
ui32 dwellpos = rand()%dwellings.size();//take random dwelling
|
||||||
ui32 creapos = rand()%dwellings[dwellpos]->creatures.size();//for multi-creature dwellings like Golem Factory
|
ui32 creapos = rand()%dwellings[dwellpos]->creatures.size();//for multi-creature dwellings like Golem Factory
|
||||||
ui32 creature = dwellings[dwellpos]->creatures[creapos].second[0];
|
ui32 creature = dwellings[dwellpos]->creatures[creapos].second[0];
|
||||||
|
|
||||||
if (clear)
|
if (clear)
|
||||||
ssi.creatures[GameConstants::CREATURES_PER_TOWN].first = std::max((ui32)1, (VLC->creh->creatures[creature]->growth)/2);
|
ssi.creatures[GameConstants::CREATURES_PER_TOWN].first = std::max((ui32)1, (VLC->creh->creatures[creature]->growth)/2);
|
||||||
else
|
else
|
||||||
@ -1142,7 +1142,7 @@ void CGameHandler::newTurn()
|
|||||||
bool firstTurn = !getDate(0);
|
bool firstTurn = !getDate(0);
|
||||||
bool newWeek = getDate(1) == 7; //day numbers are confusing, as day was not yet switched
|
bool newWeek = getDate(1) == 7; //day numbers are confusing, as day was not yet switched
|
||||||
bool newMonth = getDate(4) == 28;
|
bool newMonth = getDate(4) == 28;
|
||||||
|
|
||||||
std::map<ui8, si32> hadGold;//starting gold - for buildings like dwarven treasury
|
std::map<ui8, si32> hadGold;//starting gold - for buildings like dwarven treasury
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
|
|
||||||
@ -1204,13 +1204,13 @@ void CGameHandler::newTurn()
|
|||||||
|
|
||||||
for ( std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
|
for ( std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
|
||||||
{
|
{
|
||||||
if(i->first == 255)
|
if(i->first == 255)
|
||||||
continue;
|
continue;
|
||||||
else if(i->first >= GameConstants::PLAYER_LIMIT)
|
else if(i->first >= GameConstants::PLAYER_LIMIT)
|
||||||
assert(0); //illegal player number!
|
assert(0); //illegal player number!
|
||||||
|
|
||||||
std::pair<ui8,si32> playerGold(i->first,i->second.resources[Res::GOLD]);
|
std::pair<ui8,si32> playerGold(i->first,i->second.resources[Res::GOLD]);
|
||||||
hadGold.insert(playerGold);
|
hadGold.insert(playerGold);
|
||||||
|
|
||||||
if(newWeek) //new heroes in tavern
|
if(newWeek) //new heroes in tavern
|
||||||
{
|
{
|
||||||
@ -1248,10 +1248,10 @@ void CGameHandler::newTurn()
|
|||||||
if(h->visitedTown && vstd::contains(h->visitedTown->builtBuildings,0)) //if hero starts turn in town with mage guild
|
if(h->visitedTown && vstd::contains(h->visitedTown->builtBuildings,0)) //if hero starts turn in town with mage guild
|
||||||
hth.mana = std::max(h->mana, h->manaLimit()); //restore all mana
|
hth.mana = std::max(h->mana, h->manaLimit()); //restore all mana
|
||||||
else
|
else
|
||||||
hth.mana = std::max((si32)(0), std::max(h->mana, std::min((si32)(h->mana + h->manaRegain()), h->manaLimit())));
|
hth.mana = std::max((si32)(0), std::max(h->mana, std::min((si32)(h->mana + h->manaRegain()), h->manaLimit())));
|
||||||
|
|
||||||
n.heroes.insert(hth);
|
n.heroes.insert(hth);
|
||||||
|
|
||||||
if(!firstTurn) //not first day
|
if(!firstTurn) //not first day
|
||||||
{
|
{
|
||||||
n.res[i->first][Res::GOLD] += h->valOfBonuses(Selector::typeSubtype(Bonus::SECONDARY_SKILL_PREMY, CGHeroInstance::ESTATES)); //estates
|
n.res[i->first][Res::GOLD] += h->valOfBonuses(Selector::typeSubtype(Bonus::SECONDARY_SKILL_PREMY, CGHeroInstance::ESTATES)); //estates
|
||||||
@ -1265,7 +1265,7 @@ void CGameHandler::newTurn()
|
|||||||
}
|
}
|
||||||
// townID, creatureID, amount
|
// townID, creatureID, amount
|
||||||
std::map<si32, std::map<si32, si32> > newCreas;//creatures that needs to be added by town events
|
std::map<si32, std::map<si32, si32> > newCreas;//creatures that needs to be added by town events
|
||||||
|
|
||||||
BOOST_FOREACH(CGTownInstance *t, gs->map->towns)
|
BOOST_FOREACH(CGTownInstance *t, gs->map->towns)
|
||||||
{
|
{
|
||||||
ui8 player = t->tempOwner;
|
ui8 player = t->tempOwner;
|
||||||
@ -1336,7 +1336,7 @@ void CGameHandler::newTurn()
|
|||||||
|
|
||||||
n.res[player][Res::GOLD] += t->dailyIncome();
|
n.res[player][Res::GOLD] += t->dailyIncome();
|
||||||
}
|
}
|
||||||
if(vstd::contains(t->builtBuildings, EBuilding::GRAIL) && t->subID == 2)
|
if(vstd::contains(t->builtBuildings, EBuilding::GRAIL) && t->subID == 2)
|
||||||
{
|
{
|
||||||
// Skyship, probably easier to handle same as Veil of darkness
|
// Skyship, probably easier to handle same as Veil of darkness
|
||||||
//do it every new day after veils apply
|
//do it every new day after veils apply
|
||||||
@ -1355,7 +1355,7 @@ void CGameHandler::newTurn()
|
|||||||
|
|
||||||
if(newMonth)
|
if(newMonth)
|
||||||
{
|
{
|
||||||
SetAvailableArtifacts saa;
|
SetAvailableArtifacts saa;
|
||||||
saa.id = -1;
|
saa.id = -1;
|
||||||
pickAllowedArtsSet(saa.arts);
|
pickAllowedArtsSet(saa.arts);
|
||||||
sendAndApply(&saa);
|
sendAndApply(&saa);
|
||||||
@ -1484,10 +1484,10 @@ void CGameHandler::run(bool resume)
|
|||||||
boost::unique_lock<boost::recursive_mutex> lock(gsm);
|
boost::unique_lock<boost::recursive_mutex> lock(gsm);
|
||||||
connections[pom] = cc;
|
connections[pom] = cc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tlog0 << std::endl;
|
tlog0 << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(std::set<CConnection*>::iterator i = conns.begin(); i!=conns.end();i++)
|
for(std::set<CConnection*>::iterator i = conns.begin(); i!=conns.end();i++)
|
||||||
{
|
{
|
||||||
std::set<int> pom;
|
std::set<int> pom;
|
||||||
@ -1519,10 +1519,10 @@ void CGameHandler::run(bool resume)
|
|||||||
for(; i != gs->players.end(); i++)
|
for(; i != gs->players.end(); i++)
|
||||||
{
|
{
|
||||||
if((i->second.towns.size()==0 && i->second.heroes.size()==0)
|
if((i->second.towns.size()==0 && i->second.heroes.size()==0)
|
||||||
|| i->first>=GameConstants::PLAYER_LIMIT
|
|| i->first>=GameConstants::PLAYER_LIMIT
|
||||||
|| i->second.status)
|
|| i->second.status)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
states.setFlag(i->first,&PlayerStatus::makingTurn,true);
|
states.setFlag(i->first,&PlayerStatus::makingTurn,true);
|
||||||
|
|
||||||
@ -1537,7 +1537,7 @@ void CGameHandler::run(bool resume)
|
|||||||
while(states.players[i->first].makingTurn && !end2)
|
while(states.players[i->first].makingTurn && !end2)
|
||||||
{
|
{
|
||||||
static time_duration p = milliseconds(200);
|
static time_duration p = milliseconds(200);
|
||||||
states.cv.timed_wait(lock,p);
|
states.cv.timed_wait(lock,p);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1667,9 +1667,9 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
|
|||||||
|
|
||||||
//check if destination tile is available
|
//check if destination tile is available
|
||||||
|
|
||||||
//it's a rock or blocked and not visitable tile
|
//it's a rock or blocked and not visitable tile
|
||||||
//OR hero is on land and dest is water and (there is not present only one object - boat)
|
//OR hero is on land and dest is water and (there is not present only one object - boat)
|
||||||
if(((t.tertype == TerrainTile::rock || (t.blocked && !t.visitable && !h->hasBonusOfType(Bonus::FLYING_MOVEMENT) ))
|
if(((t.tertype == TerrainTile::rock || (t.blocked && !t.visitable && !h->hasBonusOfType(Bonus::FLYING_MOVEMENT) ))
|
||||||
&& complain("Cannot move hero, destination tile is blocked!"))
|
&& complain("Cannot move hero, destination tile is blocked!"))
|
||||||
|| ((!h->boat && !h->canWalkOnSea() && t.tertype == TerrainTile::water && (t.visitableObjects.size() < 1 || (t.visitableObjects.back()->ID != 8 && t.visitableObjects.back()->ID != GameConstants::HEROI_TYPE))) //hero is not on boat/water walking and dst water tile doesn't contain boat/hero (objs visitable from land) -> we test back cause boat may be on top of another object (#276)
|
|| ((!h->boat && !h->canWalkOnSea() && t.tertype == TerrainTile::water && (t.visitableObjects.size() < 1 || (t.visitableObjects.back()->ID != 8 && t.visitableObjects.back()->ID != GameConstants::HEROI_TYPE))) //hero is not on boat/water walking and dst water tile doesn't contain boat/hero (objs visitable from land) -> we test back cause boat may be on top of another object (#276)
|
||||||
&& complain("Cannot move hero, destination tile is on water!"))
|
&& complain("Cannot move hero, destination tile is on water!"))
|
||||||
@ -1710,7 +1710,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
|
|||||||
if(!instant)
|
if(!instant)
|
||||||
{
|
{
|
||||||
if( (distance(h->pos,dst) >= 1.5 && complain("Tiles are not neighboring!"))
|
if( (distance(h->pos,dst) >= 1.5 && complain("Tiles are not neighboring!"))
|
||||||
|| (h->movement < cost && h->movement < 100 && complain("Not enough move points!")))
|
|| (h->movement < cost && h->movement < 100 && complain("Not enough move points!")))
|
||||||
{
|
{
|
||||||
sendAndApply(&tmh);
|
sendAndApply(&tmh);
|
||||||
return false;
|
return false;
|
||||||
@ -1731,7 +1731,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
|
|||||||
if(blockvis)//interaction with blocking object (like resources)
|
if(blockvis)//interaction with blocking object (like resources)
|
||||||
{
|
{
|
||||||
tmh.result = TryMoveHero::BLOCKING_VISIT;
|
tmh.result = TryMoveHero::BLOCKING_VISIT;
|
||||||
sendAndApply(&tmh);
|
sendAndApply(&tmh);
|
||||||
//failed to move to that tile but we visit object
|
//failed to move to that tile but we visit object
|
||||||
if(t.visitableObjects.size())
|
if(t.visitableObjects.size())
|
||||||
objectVisited(t.visitableObjects.back(), h);
|
objectVisited(t.visitableObjects.back(), h);
|
||||||
@ -1772,7 +1772,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
|
|||||||
{
|
{
|
||||||
CGHeroInstance *dh = static_cast<CGHeroInstance *>(obj);
|
CGHeroInstance *dh = static_cast<CGHeroInstance *>(obj);
|
||||||
|
|
||||||
if( gameState()->getPlayerRelations(dh->tempOwner, h->tempOwner))
|
if( gameState()->getPlayerRelations(dh->tempOwner, h->tempOwner))
|
||||||
{
|
{
|
||||||
heroExchange(h->id, dh->id);
|
heroExchange(h->id, dh->id);
|
||||||
return true;
|
return true;
|
||||||
@ -1792,12 +1792,12 @@ bool CGameHandler::teleportHero(si32 hid, si32 dstid, ui8 source, ui8 asker/* =
|
|||||||
{
|
{
|
||||||
const CGHeroInstance *h = getHero(hid);
|
const CGHeroInstance *h = getHero(hid);
|
||||||
const CGTownInstance *t = getTown(dstid);
|
const CGTownInstance *t = getTown(dstid);
|
||||||
|
|
||||||
if ( !h || !t || h->getOwner() != gs->currentPlayer )
|
if ( !h || !t || h->getOwner() != gs->currentPlayer )
|
||||||
tlog1<<"Invalid call to teleportHero!";
|
tlog1<<"Invalid call to teleportHero!";
|
||||||
|
|
||||||
const CGTownInstance *from = h->visitedTown;
|
const CGTownInstance *from = h->visitedTown;
|
||||||
if(((h->getOwner() != t->getOwner())
|
if(((h->getOwner() != t->getOwner())
|
||||||
&& complain("Cannot teleport hero to another player"))
|
&& complain("Cannot teleport hero to another player"))
|
||||||
|| ((!from || from->subID!=3 || !vstd::contains(from->builtBuildings, EBuilding::SPECIAL_3))
|
|| ((!from || from->subID!=3 || !vstd::contains(from->builtBuildings, EBuilding::SPECIAL_3))
|
||||||
&& complain("Hero must be in town with Castle gate for teleporting"))
|
&& complain("Hero must be in town with Castle gate for teleporting"))
|
||||||
@ -1824,7 +1824,7 @@ void CGameHandler::setOwner(int objid, ui8 owner)
|
|||||||
const CGTownInstance * town = getTown(objid);
|
const CGTownInstance * town = getTown(objid);
|
||||||
if (town->subID == 5 && vstd::contains(town->builtBuildings, 22))
|
if (town->subID == 5 && vstd::contains(town->builtBuildings, 22))
|
||||||
setPortalDwelling(town, true, false);
|
setPortalDwelling(town, true, false);
|
||||||
|
|
||||||
if (!gs->getPlayer(owner)->towns.size())//player lost last town
|
if (!gs->getPlayer(owner)->towns.size())//player lost last town
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
@ -1833,7 +1833,7 @@ void CGameHandler::setOwner(int objid, ui8 owner)
|
|||||||
sendAndApply(&iw);
|
sendAndApply(&iw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const CGObjectInstance * obj = getObj(objid);
|
const CGObjectInstance * obj = getObj(objid);
|
||||||
const PlayerState * p = gs->getPlayer(owner);
|
const PlayerState * p = gs->getPlayer(owner);
|
||||||
|
|
||||||
@ -1898,7 +1898,7 @@ void CGameHandler::giveCreatures(const CArmedInstance *obj, const CGHeroInstance
|
|||||||
for (TSlots::const_iterator stack = creatures.Slots().begin(); stack != creatures.Slots().end(); stack++)
|
for (TSlots::const_iterator stack = creatures.Slots().begin(); stack != creatures.Slots().end(); stack++)
|
||||||
{
|
{
|
||||||
addToSlot(StackLocation(obj, obj->getSlotFor(stack->second->type)), stack->second->type, stack->second->count);
|
addToSlot(StackLocation(obj, obj->getSlotFor(stack->second->type)), stack->second->type, stack->second->count);
|
||||||
}
|
}
|
||||||
|
|
||||||
tryJoiningArmy(obj, h, remove, true);
|
tryJoiningArmy(obj, h, remove, true);
|
||||||
}
|
}
|
||||||
@ -1998,8 +1998,8 @@ void CGameHandler::startBattleI(const CArmedInstance *army1, const CArmedInstanc
|
|||||||
void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb, bool creatureBank )
|
void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb, bool creatureBank )
|
||||||
{
|
{
|
||||||
startBattleI(army1, army2, tile,
|
startBattleI(army1, army2, tile,
|
||||||
army1->ID == GameConstants::HEROI_TYPE ? static_cast<const CGHeroInstance*>(army1) : NULL,
|
army1->ID == GameConstants::HEROI_TYPE ? static_cast<const CGHeroInstance*>(army1) : NULL,
|
||||||
army2->ID == GameConstants::HEROI_TYPE ? static_cast<const CGHeroInstance*>(army2) : NULL,
|
army2->ID == GameConstants::HEROI_TYPE ? static_cast<const CGHeroInstance*>(army2) : NULL,
|
||||||
creatureBank, cb);
|
creatureBank, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2092,16 +2092,16 @@ void CGameHandler::useScholarSkill(si32 fromHero, si32 toHero)
|
|||||||
for(std::set<ui32>::const_iterator it=h2->spells.begin(); it!=h2->spells.end();it++)
|
for(std::set<ui32>::const_iterator it=h2->spells.begin(); it!=h2->spells.end();it++)
|
||||||
if ( h1Lvl >= VLC->spellh->spells[*it]->level && !vstd::contains(h1->spells, *it))
|
if ( h1Lvl >= VLC->spellh->spells[*it]->level && !vstd::contains(h1->spells, *it))
|
||||||
cs2.spells.insert(*it);
|
cs2.spells.insert(*it);
|
||||||
|
|
||||||
if (cs1.spells.size() || cs2.spells.size())//create a message
|
if (cs1.spells.size() || cs2.spells.size())//create a message
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = h1->tempOwner;
|
iw.player = h1->tempOwner;
|
||||||
iw.components.push_back(Component(Component::SEC_SKILL, 18, ScholarLevel, 0));
|
iw.components.push_back(Component(Component::SEC_SKILL, 18, ScholarLevel, 0));
|
||||||
|
|
||||||
iw.text.addTxt(MetaString::GENERAL_TXT, 139);//"%s, who has studied magic extensively,
|
iw.text.addTxt(MetaString::GENERAL_TXT, 139);//"%s, who has studied magic extensively,
|
||||||
iw.text.addReplacement(h1->name);
|
iw.text.addReplacement(h1->name);
|
||||||
|
|
||||||
if (cs2.spells.size())//if found new spell - apply
|
if (cs2.spells.size())//if found new spell - apply
|
||||||
{
|
{
|
||||||
iw.text.addTxt(MetaString::GENERAL_TXT, 140);//learns
|
iw.text.addTxt(MetaString::GENERAL_TXT, 140);//learns
|
||||||
@ -2215,7 +2215,7 @@ void CGameHandler::sendAndApply(CGarrisonOperationPack * info)
|
|||||||
{
|
{
|
||||||
sendAndApply((CPackForClient*)info);
|
sendAndApply((CPackForClient*)info);
|
||||||
if(gs->map->victoryCondition.condition == EVictoryConditionType::GATHERTROOP)
|
if(gs->map->victoryCondition.condition == EVictoryConditionType::GATHERTROOP)
|
||||||
winLoseHandle();
|
winLoseHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
// void CGameHandler::sendAndApply( SetGarrisons * info )
|
// void CGameHandler::sendAndApply( SetGarrisons * info )
|
||||||
@ -2280,7 +2280,7 @@ void CGameHandler::save( const std::string &fname )
|
|||||||
|
|
||||||
void CGameHandler::close()
|
void CGameHandler::close()
|
||||||
{
|
{
|
||||||
tlog0 << "We have been requested to close.\n";
|
tlog0 << "We have been requested to close.\n";
|
||||||
|
|
||||||
if(gs->initialOpts->mode == StartInfo::DUEL)
|
if(gs->initialOpts->mode == StartInfo::DUEL)
|
||||||
{
|
{
|
||||||
@ -2321,7 +2321,7 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
|
|||||||
{
|
{
|
||||||
if (( s1->getCreature(p1) != s2->getCreature(p2) && complain("Cannot merge different creatures stacks!"))
|
if (( s1->getCreature(p1) != s2->getCreature(p2) && complain("Cannot merge different creatures stacks!"))
|
||||||
|| (((s1->tempOwner != player && s1->tempOwner != 254) && s2->getStackCount(p2)) && complain("Can't take troops from another player!")))
|
|| (((s1->tempOwner != player && s1->tempOwner != 254) && s2->getStackCount(p2)) && complain("Can't take troops from another player!")))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
moveStack(sl1, sl2);
|
moveStack(sl1, sl2);
|
||||||
}
|
}
|
||||||
@ -2349,9 +2349,9 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
|
|||||||
|| (s1->getCreature(p1) != s2->getCreature(p2) && complain("Cannot rebalance different creatures stacks!"))
|
|| (s1->getCreature(p1) != s2->getCreature(p2) && complain("Cannot rebalance different creatures stacks!"))
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
moveStack(sl1, sl2, val - s2->getStackCount(p2));
|
moveStack(sl1, sl2, val - s2->getStackCount(p2));
|
||||||
//S2.slots[p2]->count = val;
|
//S2.slots[p2]->count = val;
|
||||||
//S1.slots[p1]->count = total - val;
|
//S1.slots[p1]->count = total - val;
|
||||||
@ -2361,7 +2361,7 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
|
|||||||
if(s1->getStackCount(p1) < val)//not enough creatures
|
if(s1->getStackCount(p1) < val)//not enough creatures
|
||||||
{
|
{
|
||||||
complain("Cannot split that stack, not enough creatures!");
|
complain("Cannot split that stack, not enough creatures!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2419,7 +2419,7 @@ bool CGameHandler::buildStructure( si32 tid, si32 bid, bool force /*=false*/ )
|
|||||||
complain("Cannot build that building!");
|
complain("Cannot build that building!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !force && bid == 26) //grail
|
if( !force && bid == 26) //grail
|
||||||
{
|
{
|
||||||
if(!t->visitingHero || !t->visitingHero->hasArt(2))
|
if(!t->visitingHero || !t->visitingHero->hasArt(2))
|
||||||
@ -2490,7 +2490,7 @@ bool CGameHandler::buildStructure( si32 tid, si32 bid, bool force /*=false*/ )
|
|||||||
ns.bid.insert(bid);
|
ns.bid.insert(bid);
|
||||||
ns.builded = force?t->builded:(t->builded+1);
|
ns.builded = force?t->builded:(t->builded+1);
|
||||||
sendAndApply(&ns);
|
sendAndApply(&ns);
|
||||||
|
|
||||||
//reveal ground for lookout tower
|
//reveal ground for lookout tower
|
||||||
FoWChange fw;
|
FoWChange fw;
|
||||||
fw.player = t->tempOwner;
|
fw.player = t->tempOwner;
|
||||||
@ -2591,7 +2591,7 @@ bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram, si32 from
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int slot = dst->getSlotFor(crid);
|
int slot = dst->getSlotFor(crid);
|
||||||
|
|
||||||
if( (!found && complain("Cannot recruit: no such creatures!"))
|
if( (!found && complain("Cannot recruit: no such creatures!"))
|
||||||
|| (cram > VLC->creh->creatures[crid]->maxAmount(gs->getPlayer(dst->tempOwner)->resources) && complain("Cannot recruit: lack of resources!"))
|
|| (cram > VLC->creh->creatures[crid]->maxAmount(gs->getPlayer(dst->tempOwner)->resources) && complain("Cannot recruit: lack of resources!"))
|
||||||
@ -2613,7 +2613,7 @@ bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram, si32 from
|
|||||||
|
|
||||||
sendAndApply(&sr);
|
sendAndApply(&sr);
|
||||||
sendAndApply(&sac);
|
sendAndApply(&sac);
|
||||||
|
|
||||||
if(warMachine)
|
if(warMachine)
|
||||||
{
|
{
|
||||||
const CGHeroInstance *h = dynamic_cast<const CGHeroInstance*>(dst);
|
const CGHeroInstance *h = dynamic_cast<const CGHeroInstance*>(dst);
|
||||||
@ -2655,22 +2655,22 @@ bool CGameHandler::upgradeCreature( ui32 objid, ui8 pos, ui32 upgID )
|
|||||||
TResources totalCost = ui.cost[newIDpos] * crQuantity;
|
TResources totalCost = ui.cost[newIDpos] * crQuantity;
|
||||||
|
|
||||||
//check if upgrade is possible
|
//check if upgrade is possible
|
||||||
if( (ui.oldID<0 || newIDpos == -1 ) && complain("That upgrade is not possible!"))
|
if( (ui.oldID<0 || newIDpos == -1 ) && complain("That upgrade is not possible!"))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//check if player has enough resources
|
//check if player has enough resources
|
||||||
if(!p->resources.canAfford(totalCost))
|
if(!p->resources.canAfford(totalCost))
|
||||||
COMPLAIN_RET("Cannot upgrade, not enough resources!");
|
COMPLAIN_RET("Cannot upgrade, not enough resources!");
|
||||||
|
|
||||||
//take resources
|
//take resources
|
||||||
SetResources sr;
|
SetResources sr;
|
||||||
sr.player = player;
|
sr.player = player;
|
||||||
sr.res = p->resources - totalCost;
|
sr.res = p->resources - totalCost;
|
||||||
sendAndApply(&sr);
|
sendAndApply(&sr);
|
||||||
|
|
||||||
//upgrade creature
|
//upgrade creature
|
||||||
changeStackType(StackLocation(obj, pos), VLC->creh->creatures[upgID]);
|
changeStackType(StackLocation(obj, pos), VLC->creh->creatures[upgID]);
|
||||||
return true;
|
return true;
|
||||||
@ -2684,11 +2684,11 @@ bool CGameHandler::changeStackType(const StackLocation &sl, CCreature *c)
|
|||||||
SetStackType sst;
|
SetStackType sst;
|
||||||
sst.sl = sl;
|
sst.sl = sl;
|
||||||
sst.type = c;
|
sst.type = c;
|
||||||
sendAndApply(&sst);
|
sendAndApply(&sst);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameHandler::moveArmy(const CArmedInstance *src, const CArmedInstance *dst, bool allowMerging)
|
void CGameHandler::moveArmy(const CArmedInstance *src, const CArmedInstance *dst, bool allowMerging)
|
||||||
{
|
{
|
||||||
assert(src->canBeMergedWith(*dst, allowMerging));
|
assert(src->canBeMergedWith(*dst, allowMerging));
|
||||||
while(src->stacksCount())//while there are unmoved creatures
|
while(src->stacksCount())//while there are unmoved creatures
|
||||||
@ -2731,16 +2731,16 @@ bool CGameHandler::garrisonSwap( si32 tid )
|
|||||||
complain("Cannot make garrison swap, not enough free slots!");
|
complain("Cannot make garrison swap, not enough free slots!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
moveArmy(town, town->visitingHero, true);
|
moveArmy(town, town->visitingHero, true);
|
||||||
|
|
||||||
SetHeroesInTown intown;
|
SetHeroesInTown intown;
|
||||||
intown.tid = tid;
|
intown.tid = tid;
|
||||||
intown.visiting = -1;
|
intown.visiting = -1;
|
||||||
intown.garrison = town->visitingHero->id;
|
intown.garrison = town->visitingHero->id;
|
||||||
sendAndApply(&intown);
|
sendAndApply(&intown);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (town->garrisonHero && !town->visitingHero) //move hero out of the garrison
|
else if (town->garrisonHero && !town->visitingHero) //move hero out of the garrison
|
||||||
{
|
{
|
||||||
//check if moving hero out of town will break 8 wandering heroes limit
|
//check if moving hero out of town will break 8 wandering heroes limit
|
||||||
@ -2780,7 +2780,7 @@ bool CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocat
|
|||||||
ArtifactLocation src = al1, dst = al2;
|
ArtifactLocation src = al1, dst = al2;
|
||||||
const int srcPlayer = src.owningPlayer(), dstPlayer = dst.owningPlayer();
|
const int srcPlayer = src.owningPlayer(), dstPlayer = dst.owningPlayer();
|
||||||
const CArmedInstance *srcObj = src.relatedObj(), *dstObj = dst.relatedObj();
|
const CArmedInstance *srcObj = src.relatedObj(), *dstObj = dst.relatedObj();
|
||||||
|
|
||||||
// Make sure exchange is even possible between the two heroes.
|
// Make sure exchange is even possible between the two heroes.
|
||||||
if(!isAllowedExchange(srcObj->id, dstObj->id))
|
if(!isAllowedExchange(srcObj->id, dstObj->id))
|
||||||
COMPLAIN_RET("That heroes cannot make any exchange!");
|
COMPLAIN_RET("That heroes cannot make any exchange!");
|
||||||
@ -2799,12 +2799,12 @@ bool CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocat
|
|||||||
&& srcArtifact && !srcArtifact->canBePutAt(dst, true))
|
&& srcArtifact && !srcArtifact->canBePutAt(dst, true))
|
||||||
COMPLAIN_RET("Cannot move artifact!");
|
COMPLAIN_RET("Cannot move artifact!");
|
||||||
|
|
||||||
if ((srcArtifact && srcArtifact->artType->id == GameConstants::ID_LOCK) || (destArtifact && destArtifact->artType->id == GameConstants::ID_LOCK))
|
if ((srcArtifact && srcArtifact->artType->id == GameConstants::ID_LOCK) || (destArtifact && destArtifact->artType->id == GameConstants::ID_LOCK))
|
||||||
COMPLAIN_RET("Cannot move artifact locks.");
|
COMPLAIN_RET("Cannot move artifact locks.");
|
||||||
|
|
||||||
if (dst.slot >= GameConstants::BACKPACK_START && srcArtifact->artType->isBig())
|
if (dst.slot >= GameConstants::BACKPACK_START && srcArtifact->artType->isBig())
|
||||||
COMPLAIN_RET("Cannot put big artifacts in backpack!");
|
COMPLAIN_RET("Cannot put big artifacts in backpack!");
|
||||||
if (src.slot == ArtifactPosition::MACH4 || dst.slot == ArtifactPosition::MACH4)
|
if (src.slot == ArtifactPosition::MACH4 || dst.slot == ArtifactPosition::MACH4)
|
||||||
COMPLAIN_RET("Cannot move catapult!");
|
COMPLAIN_RET("Cannot move catapult!");
|
||||||
|
|
||||||
if(dst.slot >= GameConstants::BACKPACK_START)
|
if(dst.slot >= GameConstants::BACKPACK_START)
|
||||||
@ -2894,7 +2894,7 @@ bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
|
|||||||
|| (!vstd::contains(town->builtBuildings,si32(EBuilding::BLACKSMITH)) && complain("No blackismith!"))
|
|| (!vstd::contains(town->builtBuildings,si32(EBuilding::BLACKSMITH)) && complain("No blackismith!"))
|
||||||
|| (gs->getPlayer(hero->getOwner())->resources[Res::GOLD] < price && complain("Not enough gold!")) //no gold
|
|| (gs->getPlayer(hero->getOwner())->resources[Res::GOLD] < price && complain("Not enough gold!")) //no gold
|
||||||
|| ((!(town->subID == 6 && vstd::contains(town->builtBuildings,si32(EBuilding::SPECIAL_3) ) )
|
|| ((!(town->subID == 6 && vstd::contains(town->builtBuildings,si32(EBuilding::SPECIAL_3) ) )
|
||||||
&& town->town->warMachine!= aid ) && complain("This machine is unavailable here!")))
|
&& town->town->warMachine!= aid ) && complain("This machine is unavailable here!")))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2913,7 +2913,7 @@ bool CGameHandler::buyArtifact(const IMarket *m, const CGHeroInstance *h, int ri
|
|||||||
|
|
||||||
int b1, b2;
|
int b1, b2;
|
||||||
m->getOffer(rid, aid, b1, b2, EMarketMode::RESOURCE_ARTIFACT);
|
m->getOffer(rid, aid, b1, b2, EMarketMode::RESOURCE_ARTIFACT);
|
||||||
|
|
||||||
if(getResource(h->tempOwner, rid) < b1)
|
if(getResource(h->tempOwner, rid) < b1)
|
||||||
COMPLAIN_RET("You can't afford to buy this artifact!");
|
COMPLAIN_RET("You can't afford to buy this artifact!");
|
||||||
|
|
||||||
@ -2986,13 +2986,13 @@ bool CGameHandler::buySecSkill( const IMarket *m, const CGHeroInstance *h, int s
|
|||||||
{
|
{
|
||||||
if (!h)
|
if (!h)
|
||||||
COMPLAIN_RET("You need hero to buy a skill!");
|
COMPLAIN_RET("You need hero to buy a skill!");
|
||||||
|
|
||||||
if (h->getSecSkillLevel(static_cast<CGHeroInstance::SecondarySkill>(skill)))
|
if (h->getSecSkillLevel(static_cast<CGHeroInstance::SecondarySkill>(skill)))
|
||||||
COMPLAIN_RET("Hero already know this skill");
|
COMPLAIN_RET("Hero already know this skill");
|
||||||
|
|
||||||
if (h->secSkills.size() >= GameConstants::SKILL_PER_HERO)//can't learn more skills
|
if (h->secSkills.size() >= GameConstants::SKILL_PER_HERO)//can't learn more skills
|
||||||
COMPLAIN_RET("Hero can't learn any more skills");
|
COMPLAIN_RET("Hero can't learn any more skills");
|
||||||
|
|
||||||
if (h->type->heroClass->proSec[skill]==0)//can't learn this skill (like necromancy for most of non-necros)
|
if (h->type->heroClass->proSec[skill]==0)//can't learn this skill (like necromancy for most of non-necros)
|
||||||
COMPLAIN_RET("The hero can't learn this skill!");
|
COMPLAIN_RET("The hero can't learn this skill!");
|
||||||
|
|
||||||
@ -3014,7 +3014,7 @@ bool CGameHandler::buySecSkill( const IMarket *m, const CGHeroInstance *h, int s
|
|||||||
|
|
||||||
bool CGameHandler::tradeResources(const IMarket *market, ui32 val, ui8 player, ui32 id1, ui32 id2)
|
bool CGameHandler::tradeResources(const IMarket *market, ui32 val, ui8 player, ui32 id1, ui32 id2)
|
||||||
{
|
{
|
||||||
int r1 = gs->getPlayer(player)->resources[id1],
|
int r1 = gs->getPlayer(player)->resources[id1],
|
||||||
r2 = gs->getPlayer(player)->resources[id2];
|
r2 = gs->getPlayer(player)->resources[id2];
|
||||||
|
|
||||||
vstd::amin(val, r1); //can't trade more resources than have
|
vstd::amin(val, r1); //can't trade more resources than have
|
||||||
@ -3058,13 +3058,13 @@ bool CGameHandler::sellCreatures(ui32 count, const IMarket *market, const CGHero
|
|||||||
int b1, b2; //base quantities for trade
|
int b1, b2; //base quantities for trade
|
||||||
market->getOffer(s.type->idNumber, resourceID, b1, b2, EMarketMode::CREATURE_RESOURCE);
|
market->getOffer(s.type->idNumber, resourceID, b1, b2, EMarketMode::CREATURE_RESOURCE);
|
||||||
int units = count / b1; //how many base quantities we trade
|
int units = count / b1; //how many base quantities we trade
|
||||||
|
|
||||||
if(count%b1) //all offered units of resource should be used, if not -> somewhere in calculations must be an error
|
if(count%b1) //all offered units of resource should be used, if not -> somewhere in calculations must be an error
|
||||||
{
|
{
|
||||||
//TODO: complain?
|
//TODO: complain?
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
changeStackCount(StackLocation(hero, slot), -count);
|
changeStackCount(StackLocation(hero, slot), -count);
|
||||||
|
|
||||||
SetResource sr;
|
SetResource sr;
|
||||||
@ -3092,7 +3092,7 @@ bool CGameHandler::transformInUndead(const IMarket *market, const CGHeroInstance
|
|||||||
|
|
||||||
const CStackInstance &s = army->getStack(slot);
|
const CStackInstance &s = army->getStack(slot);
|
||||||
int resCreature;//resulting creature - bone dragons or skeletons
|
int resCreature;//resulting creature - bone dragons or skeletons
|
||||||
|
|
||||||
if (s.hasBonusOfType(Bonus::DRAGON_NATURE))
|
if (s.hasBonusOfType(Bonus::DRAGON_NATURE))
|
||||||
resCreature = 68;
|
resCreature = 68;
|
||||||
else
|
else
|
||||||
@ -3249,7 +3249,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
//defensive stance //TODO: remove this bonus when stack becomes active
|
//defensive stance //TODO: remove this bonus when stack becomes active
|
||||||
SetStackEffect sse;
|
SetStackEffect sse;
|
||||||
sse.effect.push_back( Bonus(Bonus::STACK_GETS_TURN, Bonus::PRIMARY_SKILL, Bonus::OTHER, 20, -1, PrimarySkill::DEFENSE, Bonus::PERCENT_TO_ALL) );
|
sse.effect.push_back( Bonus(Bonus::STACK_GETS_TURN, Bonus::PRIMARY_SKILL, Bonus::OTHER, 20, -1, PrimarySkill::DEFENSE, Bonus::PERCENT_TO_ALL) );
|
||||||
sse.effect.push_back( Bonus(Bonus::STACK_GETS_TURN, Bonus::PRIMARY_SKILL, Bonus::OTHER, gs->curB->stacks[ba.stackNumber]->valOfBonuses(Bonus::DEFENSIVE_STANCE),
|
sse.effect.push_back( Bonus(Bonus::STACK_GETS_TURN, Bonus::PRIMARY_SKILL, Bonus::OTHER, gs->curB->stacks[ba.stackNumber]->valOfBonuses(Bonus::DEFENSIVE_STANCE),
|
||||||
-1, PrimarySkill::DEFENSE, Bonus::ADDITIVE_VALUE));
|
-1, PrimarySkill::DEFENSE, Bonus::ADDITIVE_VALUE));
|
||||||
sse.stacks.push_back(ba.stackNumber);
|
sse.stacks.push_back(ba.stackNumber);
|
||||||
sendAndApply(&sse);
|
sendAndApply(&sse);
|
||||||
@ -3306,7 +3306,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
&& !(curStack->doubleWide()
|
&& !(curStack->doubleWide()
|
||||||
&& ( curStack->position == ba.destinationTile + (curStack->attackerOwned ? +1 : -1 ) )
|
&& ( curStack->position == ba.destinationTile + (curStack->attackerOwned ? +1 : -1 ) )
|
||||||
) //nor occupy specified hex
|
) //nor occupy specified hex
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
std::string problem = "We cannot move this stack to its destination " + curStack->getCreature()->namePl;
|
std::string problem = "We cannot move this stack to its destination " + curStack->getCreature()->namePl;
|
||||||
tlog3 << problem << std::endl;
|
tlog3 << problem << std::endl;
|
||||||
@ -3429,7 +3429,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
sendAndApply(&start_action);
|
sendAndApply(&start_action);
|
||||||
const CGHeroInstance * attackingHero = gs->curB->heroes[ba.side];
|
const CGHeroInstance * attackingHero = gs->curB->heroes[ba.side];
|
||||||
CHeroHandler::SBallisticsLevelInfo sbi = VLC->heroh->ballistics[attackingHero->getSecSkillLevel(CGHeroInstance::BALLISTICS)];
|
CHeroHandler::SBallisticsLevelInfo sbi = VLC->heroh->ballistics[attackingHero->getSecSkillLevel(CGHeroInstance::BALLISTICS)];
|
||||||
|
|
||||||
int attackedPart = gs->curB->hexToWallPart(ba.destinationTile);
|
int attackedPart = gs->curB->hexToWallPart(ba.destinationTile);
|
||||||
if(attackedPart < 0)
|
if(attackedPart < 0)
|
||||||
{
|
{
|
||||||
@ -3442,7 +3442,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
{
|
{
|
||||||
if(wallInitHP + dmgAlreadyDealt == 3) //it's not destroyed
|
if(wallInitHP + dmgAlreadyDealt == 3) //it's not destroyed
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CatapultAttack ca; //package for clients
|
CatapultAttack ca; //package for clients
|
||||||
std::pair< std::pair< ui8, si16 >, ui8> attack; //<< attackedPart , destination tile >, damageDealt >
|
std::pair< std::pair< ui8, si16 >, ui8> attack; //<< attackedPart , destination tile >, damageDealt >
|
||||||
attack.first.first = attackedPart;
|
attack.first.first = attackedPart;
|
||||||
@ -3802,8 +3802,8 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
|
|||||||
//It creates, sends and applies needed package.
|
//It creates, sends and applies needed package.
|
||||||
auto placeObstacle = [&](BattleHex pos)
|
auto placeObstacle = [&](BattleHex pos)
|
||||||
{
|
{
|
||||||
static int obstacleIdToGive = gs->curB->obstacles.size()
|
static int obstacleIdToGive = gs->curB->obstacles.size()
|
||||||
? (gs->curB->obstacles.back()->uniqueID+1)
|
? (gs->curB->obstacles.back()->uniqueID+1)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
auto obstacle = make_shared<SpellCreatedObstacle>();
|
auto obstacle = make_shared<SpellCreatedObstacle>();
|
||||||
@ -3921,7 +3921,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
|
|||||||
|
|
||||||
//applying effects
|
//applying effects
|
||||||
switch (spellID)
|
switch (spellID)
|
||||||
{
|
{
|
||||||
case Spells::QUICKSAND:
|
case Spells::QUICKSAND:
|
||||||
case Spells::LAND_MINE:
|
case Spells::LAND_MINE:
|
||||||
{
|
{
|
||||||
@ -4016,7 +4016,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// permanent effects
|
// permanent effects
|
||||||
case Spells::SHIELD:
|
case Spells::SHIELD:
|
||||||
case Spells::AIR_SHIELD:
|
case Spells::AIR_SHIELD:
|
||||||
case Spells::FIRE_SHIELD:
|
case Spells::FIRE_SHIELD:
|
||||||
case Spells::PROTECTION_FROM_AIR:
|
case Spells::PROTECTION_FROM_AIR:
|
||||||
@ -4079,7 +4079,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
|
|||||||
if(vstd::contains(sc.resisted, (*it)->ID)) //this creature resisted the spell
|
if(vstd::contains(sc.resisted, (*it)->ID)) //this creature resisted the spell
|
||||||
continue;
|
continue;
|
||||||
sse.stacks.push_back((*it)->ID);
|
sse.stacks.push_back((*it)->ID);
|
||||||
|
|
||||||
//Apply hero specials - peculiar enchants
|
//Apply hero specials - peculiar enchants
|
||||||
if ((*it)->base) // no war machines - TODO: make it work
|
if ((*it)->base) // no war machines - TODO: make it work
|
||||||
{
|
{
|
||||||
@ -4093,7 +4093,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
|
|||||||
switch(tier)
|
switch(tier)
|
||||||
{
|
{
|
||||||
case 1: case 2:
|
case 1: case 2:
|
||||||
power = 3;
|
power = 3;
|
||||||
break;
|
break;
|
||||||
case 3: case 4:
|
case 3: case 4:
|
||||||
power = 2;
|
power = 2;
|
||||||
@ -4165,7 +4165,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
|
|||||||
{
|
{
|
||||||
if(vstd::contains(sc.resisted, (*it)->ID) //this creature resisted the spell
|
if(vstd::contains(sc.resisted, (*it)->ID) //this creature resisted the spell
|
||||||
|| (spellID == Spells::ANIMATE_DEAD && !(*it)->hasBonusOfType(Bonus::UNDEAD)) //we try to cast animate dead on living stack
|
|| (spellID == Spells::ANIMATE_DEAD && !(*it)->hasBonusOfType(Bonus::UNDEAD)) //we try to cast animate dead on living stack
|
||||||
)
|
)
|
||||||
continue;
|
continue;
|
||||||
StacksHealedOrResurrected::HealInfo hi;
|
StacksHealedOrResurrected::HealInfo hi;
|
||||||
hi.stackID = (*it)->ID;
|
hi.stackID = (*it)->ID;
|
||||||
@ -4302,7 +4302,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
|
|||||||
{
|
{
|
||||||
BattleStackAttacked bsa;
|
BattleStackAttacked bsa;
|
||||||
bsa.flags |= BattleStackAttacked::EFFECT;
|
bsa.flags |= BattleStackAttacked::EFFECT;
|
||||||
bsa.effect = VLC->spellh->spells[80]->mainEffectAnim; //use acid breath
|
bsa.effect = VLC->spellh->spells[80]->mainEffectAnim; //use acid breath
|
||||||
bsa.damageAmount = usedSpellPower; //damage times the number of attackers
|
bsa.damageAmount = usedSpellPower; //damage times the number of attackers
|
||||||
bsa.stackAttacked = (*it)->ID;
|
bsa.stackAttacked = (*it)->ID;
|
||||||
bsa.attackerID = -1;
|
bsa.attackerID = -1;
|
||||||
@ -4563,15 +4563,15 @@ void CGameHandler::handleDamageFromObstacle(const CObstacleInstance &obstacle, C
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
oneTimeObstacle = true;
|
oneTimeObstacle = true;
|
||||||
effect = 82; //makes
|
effect = 82; //makes
|
||||||
damage = gs->curB->calculateSpellDmg(VLC->spellh->spells[Spells::LAND_MINE], hero, curStack,
|
damage = gs->curB->calculateSpellDmg(VLC->spellh->spells[Spells::LAND_MINE], hero, curStack,
|
||||||
spellObstacle->spellLevel, spellObstacle->casterSpellPower);
|
spellObstacle->spellLevel, spellObstacle->casterSpellPower);
|
||||||
//TODO even if obstacle wasn't created by hero (Tower "moat") it should deal dmg as if casted by hero,
|
//TODO even if obstacle wasn't created by hero (Tower "moat") it should deal dmg as if casted by hero,
|
||||||
//if it is bigger than default dmg. Or is it just irrelevant H3 implementation quirk
|
//if it is bigger than default dmg. Or is it just irrelevant H3 implementation quirk
|
||||||
}
|
}
|
||||||
else if(obstacle.obstacleType == CObstacleInstance::FIRE_WALL)
|
else if(obstacle.obstacleType == CObstacleInstance::FIRE_WALL)
|
||||||
{
|
{
|
||||||
damage = gs->curB->calculateSpellDmg(VLC->spellh->spells[Spells::FIRE_WALL], hero, curStack,
|
damage = gs->curB->calculateSpellDmg(VLC->spellh->spells[Spells::FIRE_WALL], hero, curStack,
|
||||||
spellObstacle->spellLevel, spellObstacle->casterSpellPower);
|
spellObstacle->spellLevel, spellObstacle->casterSpellPower);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -4611,7 +4611,7 @@ void CGameHandler::handleTimeEvents()
|
|||||||
|
|
||||||
if( pinfo //player exists
|
if( pinfo //player exists
|
||||||
&& (ev->players & 1<<player) //event is enabled to this player
|
&& (ev->players & 1<<player) //event is enabled to this player
|
||||||
&& ((ev->computerAffected && !pinfo->human)
|
&& ((ev->computerAffected && !pinfo->human)
|
||||||
|| (ev->humanAffected && pinfo->human)
|
|| (ev->humanAffected && pinfo->human)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -4672,7 +4672,7 @@ void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n, std::map<
|
|||||||
|
|
||||||
if( pinfo //player exists
|
if( pinfo //player exists
|
||||||
&& (ev->players & 1<<player) //event is enabled to this player
|
&& (ev->players & 1<<player) //event is enabled to this player
|
||||||
&& ((ev->computerAffected && !pinfo->human)
|
&& ((ev->computerAffected && !pinfo->human)
|
||||||
|| (ev->humanAffected && pinfo->human) ) )
|
|| (ev->humanAffected && pinfo->human) ) )
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -4706,7 +4706,7 @@ void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n, std::map<
|
|||||||
if(town->creatureDwelling(i) && ev->creatures[i])//there is dwelling
|
if(town->creatureDwelling(i) && ev->creatures[i])//there is dwelling
|
||||||
{
|
{
|
||||||
newCreas[town->id][i] += ev->creatures[i];
|
newCreas[town->id][i] += ev->creatures[i];
|
||||||
iw.components.push_back(Component(Component::CREATURE,
|
iw.components.push_back(Component(Component::CREATURE,
|
||||||
town->creatures[i].second.back(), ev->creatures[i], 0));
|
town->creatures[i].second.back(), ev->creatures[i], 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4758,7 +4758,7 @@ void CGameHandler::showGarrisonDialog( int upobj, int hid, bool removableUnits,
|
|||||||
|
|
||||||
//register callback manually since we need to use query ID that's given in result of prepareNewQuery call
|
//register callback manually since we need to use query ID that's given in result of prepareNewQuery call
|
||||||
callbacks[gd.queryID] = [=](ui32 answer)
|
callbacks[gd.queryID] = [=](ui32 answer)
|
||||||
{
|
{
|
||||||
// Garrison callback calls the "original callback" and closes the exchange between objs.
|
// Garrison callback calls the "original callback" and closes the exchange between objs.
|
||||||
if (cb)
|
if (cb)
|
||||||
cb();
|
cb();
|
||||||
@ -4828,7 +4828,7 @@ bool CGameHandler::isAllowedExchange( int id1, int id2 )
|
|||||||
}
|
}
|
||||||
else //not exchanging between heroes, TODO: more sophisticated logic
|
else //not exchanging between heroes, TODO: more sophisticated logic
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -5126,7 +5126,7 @@ bool CGameHandler::dig( const CGHeroInstance *h )
|
|||||||
no.pos = h->getPosition();
|
no.pos = h->getPosition();
|
||||||
no.subID = getTile(no.pos)->tertype;
|
no.subID = getTile(no.pos)->tertype;
|
||||||
sendAndApply(&no);
|
sendAndApply(&no);
|
||||||
|
|
||||||
//take MPs
|
//take MPs
|
||||||
SetMovePoints smp;
|
SetMovePoints smp;
|
||||||
smp.hid = h->id;
|
smp.hid = h->id;
|
||||||
@ -5243,7 +5243,7 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat )
|
|||||||
}
|
}
|
||||||
if (((int)(mean * 100)) < rand() % 100) //fractional chance for one last kill
|
if (((int)(mean * 100)) < rand() % 100) //fractional chance for one last kill
|
||||||
++staredCreatures;
|
++staredCreatures;
|
||||||
|
|
||||||
staredCreatures += attacker->type->level * attacker->valOfBonuses(Bonus::DEATH_STARE, 1);
|
staredCreatures += attacker->type->level * attacker->valOfBonuses(Bonus::DEATH_STARE, 1);
|
||||||
if (staredCreatures)
|
if (staredCreatures)
|
||||||
{
|
{
|
||||||
@ -5276,7 +5276,7 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &p
|
|||||||
|
|
||||||
if(!h->canCastThisSpell(s))
|
if(!h->canCastThisSpell(s))
|
||||||
COMPLAIN_RET("Hero cannot cast this spell!");
|
COMPLAIN_RET("Hero cannot cast this spell!");
|
||||||
if(h->mana < cost)
|
if(h->mana < cost)
|
||||||
COMPLAIN_RET("Hero doesn't have enough spell points to cast this spell!");
|
COMPLAIN_RET("Hero doesn't have enough spell points to cast this spell!");
|
||||||
if(s->combatSpell)
|
if(s->combatSpell)
|
||||||
COMPLAIN_RET("This function can be used only for adventure map spells!");
|
COMPLAIN_RET("This function can be used only for adventure map spells!");
|
||||||
@ -5289,7 +5289,7 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &p
|
|||||||
using namespace Spells;
|
using namespace Spells;
|
||||||
switch(spellID)
|
switch(spellID)
|
||||||
{
|
{
|
||||||
case SUMMON_BOAT: //Summon Boat
|
case SUMMON_BOAT: //Summon Boat
|
||||||
{
|
{
|
||||||
//check if spell works at all
|
//check if spell works at all
|
||||||
if(rand() % 100 >= s->powers[schoolLevel]) //power is % chance of success
|
if(rand() % 100 >= s->powers[schoolLevel]) //power is % chance of success
|
||||||
@ -5351,7 +5351,7 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &p
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SCUTTLE_BOAT: //Scuttle Boat
|
case SCUTTLE_BOAT: //Scuttle Boat
|
||||||
{
|
{
|
||||||
//check if spell works at all
|
//check if spell works at all
|
||||||
if(rand() % 100 >= s->powers[schoolLevel]) //power is % chance of success
|
if(rand() % 100 >= s->powers[schoolLevel]) //power is % chance of success
|
||||||
@ -5399,7 +5399,7 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &p
|
|||||||
gb.id = h->id;
|
gb.id = h->id;
|
||||||
gb.bonus = Bonus(Bonus::ONE_DAY, Bonus::NONE, Bonus::SPELL_EFFECT, 0, Spells::DIMENSION_DOOR);
|
gb.bonus = Bonus(Bonus::ONE_DAY, Bonus::NONE, Bonus::SPELL_EFFECT, 0, Spells::DIMENSION_DOOR);
|
||||||
sendAndApply(&gb);
|
sendAndApply(&gb);
|
||||||
|
|
||||||
if(!dest->isClear(curr)) //wrong dest tile
|
if(!dest->isClear(curr)) //wrong dest tile
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
@ -5424,7 +5424,7 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &p
|
|||||||
tryAttackingGuard(guardPos, h);
|
tryAttackingGuard(guardPos, h);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FLY: //Fly
|
case FLY: //Fly
|
||||||
{
|
{
|
||||||
int subtype = schoolLevel >= 2 ? 1 : 2; //adv or expert
|
int subtype = schoolLevel >= 2 ? 1 : 2; //adv or expert
|
||||||
|
|
||||||
@ -5434,7 +5434,7 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &p
|
|||||||
sendAndApply(&gb);
|
sendAndApply(&gb);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WATER_WALK: //Water Walk
|
case WATER_WALK: //Water Walk
|
||||||
{
|
{
|
||||||
int subtype = schoolLevel >= 2 ? 1 : 2; //adv or expert
|
int subtype = schoolLevel >= 2 ? 1 : 2; //adv or expert
|
||||||
|
|
||||||
@ -5444,21 +5444,21 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &p
|
|||||||
sendAndApply(&gb);
|
sendAndApply(&gb);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOWN_PORTAL: //Town Portal
|
case TOWN_PORTAL: //Town Portal
|
||||||
{
|
{
|
||||||
if (!gs->map->isInTheMap(pos))
|
if (!gs->map->isInTheMap(pos))
|
||||||
COMPLAIN_RET("Destination tile not present!")
|
COMPLAIN_RET("Destination tile not present!")
|
||||||
TerrainTile tile = gs->map->getTile(pos);
|
TerrainTile tile = gs->map->getTile(pos);
|
||||||
if (tile.visitableObjects.empty() || tile.visitableObjects.back()->ID != GameConstants::TOWNI_TYPE )
|
if (tile.visitableObjects.empty() || tile.visitableObjects.back()->ID != GameConstants::TOWNI_TYPE )
|
||||||
COMPLAIN_RET("Town not found for Town Portal!");
|
COMPLAIN_RET("Town not found for Town Portal!");
|
||||||
|
|
||||||
CGTownInstance * town = static_cast<CGTownInstance*>(tile.visitableObjects.back());
|
CGTownInstance * town = static_cast<CGTownInstance*>(tile.visitableObjects.back());
|
||||||
if (town->tempOwner != h->tempOwner)
|
if (town->tempOwner != h->tempOwner)
|
||||||
COMPLAIN_RET("Can't teleport to another player!");
|
COMPLAIN_RET("Can't teleport to another player!");
|
||||||
if (town->visitingHero)
|
if (town->visitingHero)
|
||||||
COMPLAIN_RET("Can't teleport to occupied town!");
|
COMPLAIN_RET("Can't teleport to occupied town!");
|
||||||
|
|
||||||
if (h->getSpellSchoolLevel(s) < 2)
|
if (h->getSpellSchoolLevel(s) < 2)
|
||||||
{
|
{
|
||||||
double dist = town->pos.dist2d(h->pos);
|
double dist = town->pos.dist2d(h->pos);
|
||||||
@ -5482,10 +5482,10 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &p
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VISIONS: //Visions
|
case VISIONS: //Visions
|
||||||
case VIEW_EARTH: //View Earth
|
case VIEW_EARTH: //View Earth
|
||||||
case DISGUISE: //Disguise
|
case DISGUISE: //Disguise
|
||||||
case VIEW_AIR: //View Air
|
case VIEW_AIR: //View Air
|
||||||
default:
|
default:
|
||||||
COMPLAIN_RET("This spell is not implemented yet!");
|
COMPLAIN_RET("This spell is not implemented yet!");
|
||||||
break;
|
break;
|
||||||
@ -5529,7 +5529,7 @@ bool CGameHandler::sacrificeCreatures(const IMarket *market, const CGHeroInstanc
|
|||||||
COMPLAIN_RET("Cannot sacrifice last creature!");
|
COMPLAIN_RET("Cannot sacrifice last creature!");
|
||||||
|
|
||||||
int crid = hero->getStack(slot).type->idNumber;
|
int crid = hero->getStack(slot).type->idNumber;
|
||||||
|
|
||||||
changeStackCount(StackLocation(hero, slot), -count);
|
changeStackCount(StackLocation(hero, slot), -count);
|
||||||
|
|
||||||
int dump, exp;
|
int dump, exp;
|
||||||
@ -5661,9 +5661,9 @@ void CGameHandler::tryJoiningArmy(const CArmedInstance *src, const CArmedInstanc
|
|||||||
cont = false;
|
cont = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boost::function<void()> removeOrNot = 0;
|
boost::function<void()> removeOrNot = 0;
|
||||||
if(removeObjWhenFinished)
|
if(removeObjWhenFinished)
|
||||||
removeOrNot = boost::bind(&IGameCallback::removeObject,this,src->id);
|
removeOrNot = boost::bind(&IGameCallback::removeObject,this,src->id);
|
||||||
showGarrisonDialog(src->id, dst->id, true, removeOrNot); //show garrison window and optionally remove ourselves from map when player ends
|
showGarrisonDialog(src->id, dst->id, true, removeOrNot); //show garrison window and optionally remove ourselves from map when player ends
|
||||||
}
|
}
|
||||||
@ -5755,7 +5755,7 @@ void CGameHandler::runBattle()
|
|||||||
if(const SpellCreatedObstacle *sco = dynamic_cast<const SpellCreatedObstacle *>(obstPtr.get()))
|
if(const SpellCreatedObstacle *sco = dynamic_cast<const SpellCreatedObstacle *>(obstPtr.get()))
|
||||||
if(sco->turnsRemaining == 0)
|
if(sco->turnsRemaining == 0)
|
||||||
removeObstacle(*obstPtr);
|
removeObstacle(*obstPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CStack*> & stacks = (gs->curB->stacks);
|
std::vector<CStack*> & stacks = (gs->curB->stacks);
|
||||||
const BattleInfo & curB = *gs->curB;
|
const BattleInfo & curB = *gs->curB;
|
||||||
@ -5887,7 +5887,7 @@ void CGameHandler::runBattle()
|
|||||||
|
|
||||||
int numberOfAsks = 1;
|
int numberOfAsks = 1;
|
||||||
bool breakOuter = false;
|
bool breakOuter = false;
|
||||||
do
|
do
|
||||||
{//ask interface and wait for answer
|
{//ask interface and wait for answer
|
||||||
if(!battleResult.get())
|
if(!battleResult.get())
|
||||||
{
|
{
|
||||||
@ -5981,7 +5981,7 @@ void CGameHandler::giveHeroArtifact(const CGHeroInstance *h, const CArtifactInst
|
|||||||
al.slot = slot;
|
al.slot = slot;
|
||||||
|
|
||||||
if(slot < 0 || !a->canBePutAt(al))
|
if(slot < 0 || !a->canBePutAt(al))
|
||||||
{
|
{
|
||||||
complain("Cannot put artifact in that slot!");
|
complain("Cannot put artifact in that slot!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -6008,7 +6008,7 @@ void CGameHandler::giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact
|
|||||||
a = new CCombinedArtifactInstance();
|
a = new CCombinedArtifactInstance();
|
||||||
}
|
}
|
||||||
a->artType = artType; //*NOT* via settype -> all bonus-related stuff must be done by NewArtifact apply
|
a->artType = artType; //*NOT* via settype -> all bonus-related stuff must be done by NewArtifact apply
|
||||||
|
|
||||||
NewArtifact na;
|
NewArtifact na;
|
||||||
na.art = a;
|
na.art = a;
|
||||||
sendAndApply(&na); // -> updates a!!!, will create a on other machines
|
sendAndApply(&na); // -> updates a!!!, will create a on other machines
|
||||||
@ -6101,7 +6101,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleI
|
|||||||
{
|
{
|
||||||
auto c = dynamic_cast <const CCommanderInstance *>(st->base);
|
auto c = dynamic_cast <const CCommanderInstance *>(st->base);
|
||||||
if (c) //switch commander status to dead
|
if (c) //switch commander status to dead
|
||||||
{
|
{
|
||||||
auto h = dynamic_cast <const CGHeroInstance *>(army);
|
auto h = dynamic_cast <const CGHeroInstance *>(army);
|
||||||
if (h && h->commander == c)
|
if (h && h->commander == c)
|
||||||
heroWithDeadCommander = army->id; //TODO: unify commander handling
|
heroWithDeadCommander = army->id; //TODO: unify commander handling
|
||||||
|
Loading…
x
Reference in New Issue
Block a user