mirror of
https://github.com/vcmi/vcmi.git
synced 2026-06-19 22:57:37 +02:00
ERM is now a separate project, linking to ./Scripting/ERM.dll and consisting all ERM* files from ./lib.
Little changes around handling ERM. New class in lib: CFileUtility, so the code for scanning files with given extension is not duplicated.
This commit is contained in:
+24
-10
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
template<typename rett>
|
||||
rett * createAnyAI(std::string dllname, std::string methodName)
|
||||
rett * createAny(std::string dllname, std::string methodName)
|
||||
{
|
||||
char temp[50];
|
||||
rett * ret=NULL;
|
||||
@@ -29,24 +29,25 @@ rett * createAnyAI(std::string dllname, std::string methodName)
|
||||
|
||||
std::string dllPath;
|
||||
|
||||
//TODO unify at least partially (code duplication)
|
||||
#ifdef _WIN32
|
||||
dllPath = LIB_DIR "/" +dllname+".dll";
|
||||
dllPath = dllname;
|
||||
HINSTANCE dll = LoadLibraryA(dllPath.c_str());
|
||||
if (!dll)
|
||||
{
|
||||
tlog1 << "Cannot open AI library ("<<dllPath<<"). Throwing..."<<std::endl;
|
||||
throw new std::string("Cannot open AI library");
|
||||
tlog1 << "Cannot open dynamic library ("<<dllPath<<"). Throwing..."<<std::endl;
|
||||
throw new std::string("Cannot open dynamic library");
|
||||
}
|
||||
//int len = dllname.size()+1;
|
||||
getName = (void(*)(char*))GetProcAddress(dll,"GetAiName");
|
||||
getAI = (rett*(*)())GetProcAddress(dll,methodName.c_str());
|
||||
#else
|
||||
dllPath = LIB_DIR "/" + dllname + ".so";
|
||||
dllPath = dllname;
|
||||
void *dll = dlopen(dllPath.c_str(), RTLD_LOCAL | RTLD_LAZY);
|
||||
if (!dll)
|
||||
{
|
||||
tlog1 << "Cannot open AI library ("<<dllPath<<"). Throwing..."<<std::endl;
|
||||
throw new std::string("Cannot open AI library");
|
||||
tlog1 << "Cannot open dynamic library ("<<dllPath<<"). Throwing..."<<std::endl;
|
||||
throw new std::string("Cannot open dynamic library");
|
||||
}
|
||||
getName = (void(*)(char*))dlsym(dll,"GetAiName");
|
||||
getAI = (rett*(*)())dlsym(dll,methodName.c_str());
|
||||
@@ -58,20 +59,33 @@ rett * createAnyAI(std::string dllname, std::string methodName)
|
||||
if(!ret)
|
||||
tlog1 << "Cannot get AI!\n";
|
||||
|
||||
ret->dllName = dllname;
|
||||
return ret;
|
||||
}
|
||||
|
||||
CGlobalAI * CAIHandler::getNewAI(std::string dllname)
|
||||
|
||||
template<typename rett>
|
||||
rett * createAnyAI(std::string dllname, std::string methodName)
|
||||
{
|
||||
rett* ret = createAny<rett>(LIB_DIR "/" + dllname + '.' + LIB_EXT, methodName);
|
||||
ret->dllName = dllname;
|
||||
return ret;
|
||||
}
|
||||
|
||||
CGlobalAI * CDynLibHandler::getNewAI(std::string dllname)
|
||||
{
|
||||
return createAnyAI<CGlobalAI>(dllname, "GetNewAI");
|
||||
}
|
||||
|
||||
CBattleGameInterface * CAIHandler::getNewBattleAI(std::string dllname )
|
||||
CBattleGameInterface * CDynLibHandler::getNewBattleAI(std::string dllname )
|
||||
{
|
||||
return createAnyAI<CBattleGameInterface>(dllname, "GetNewBattleAI");
|
||||
}
|
||||
|
||||
CScriptingModule * CDynLibHandler::getNewScriptingModule(std::string dllname)
|
||||
{
|
||||
return createAny<CScriptingModule>(dllname, "GetNewModule");
|
||||
}
|
||||
|
||||
BattleAction CGlobalAI::activeStack( const CStack * stack )
|
||||
{
|
||||
BattleAction ba; ba.actionType = BattleAction::DEFEND;
|
||||
|
||||
+4
-1
@@ -54,6 +54,7 @@ typedef si32 TQuantity;
|
||||
template <typename Serializer> class CISer;
|
||||
template <typename Serializer> class COSer;
|
||||
struct ArtifactLocation;
|
||||
class CScriptingModule;
|
||||
|
||||
class CBattleGameInterface : public IBattleEventsReceiver
|
||||
{
|
||||
@@ -82,12 +83,14 @@ public:
|
||||
virtual void serialize(CISer<CLoadFile> &h, const int version){}; //loading
|
||||
};
|
||||
|
||||
class CAIHandler
|
||||
class CDynLibHandler
|
||||
{
|
||||
public:
|
||||
static CGlobalAI * getNewAI(std::string dllname);
|
||||
static CBattleGameInterface * getNewBattleAI(std::string dllname);
|
||||
static CScriptingModule * getNewScriptingModule(std::string dllname);
|
||||
};
|
||||
|
||||
class CGlobalAI : public CGameInterface // AI class (to derivate)
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="RD|Win32">
|
||||
<Configuration>RD</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{8F202F43-106D-4F63-AD9D-B1D43E803E8C}</ProjectGuid>
|
||||
<RootNamespace>ERM</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'">
|
||||
<OutDir>$(SolutionDir)$(Configuration)\bin\Scripting\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)\Scripting\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>../../../include;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>../../../libs; ../../;</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>../../../include;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>../../../libs; ../../;</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>../../../include;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>../../../libs; ../../;</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ERMInterpreter.h" />
|
||||
<ClInclude Include="ERMParser.h" />
|
||||
<ClInclude Include="ERMScriptModule.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ERMInterpreter.cpp" />
|
||||
<ClCompile Include="ERMParser.cpp" />
|
||||
<ClCompile Include="ERMScriptModule.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,6 +1,5 @@
|
||||
#define VCMI_DLL
|
||||
#include "ERMInterpreter.h"
|
||||
|
||||
#include <cctype>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
@@ -9,9 +8,9 @@
|
||||
#include <boost/assign/std/vector.hpp>
|
||||
#include <boost/assign/list_of.hpp>
|
||||
|
||||
#include "CObjectHandler.h"
|
||||
#include "CHeroHandler.h"
|
||||
#include "CCreatureHandler.h"
|
||||
#include "../../lib/CObjectHandler.h"
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
|
||||
/*
|
||||
* ERMInterpreter.cpp, part of VCMI engine
|
||||
@@ -745,9 +744,14 @@ struct HEPerformer : StandardReceiverVisitor<const CGHeroInstance *>
|
||||
if(erm->getIexp(params[0]).getInt() == 0)
|
||||
{
|
||||
int slot = erm->getIexp(params[1]).getInt();
|
||||
const CStackInstance *stack = identifier->getStackPtr(slot);
|
||||
if(params[2].which() == 6) //varp
|
||||
{
|
||||
erm->getIexp(boost::get<ERM::TVarpExp>(params[2])).setTo(identifier->getCreature(slot)->idNumber);
|
||||
IexpValStr lhs = erm->getIexp(boost::get<ERM::TVarpExp>(params[2]));
|
||||
if(stack)
|
||||
lhs.setTo(stack->getCreatureID());
|
||||
else
|
||||
lhs.setTo(-1);
|
||||
}
|
||||
else
|
||||
throw EScriptExecError("Setting stack creature type is not implemented!");
|
||||
@@ -787,6 +791,102 @@ struct IF_MPerformer : StandardBodyOptionItemVisitor<IFPerformer>
|
||||
void operator()(TStringConstant const& cmp) const OVERRIDE;
|
||||
};
|
||||
|
||||
|
||||
//according to the ERM help:
|
||||
//"%%" -> "%"
|
||||
//"%V#" -> current value of # flag.
|
||||
//"%Vf"..."%Vt" -> current value of corresponding variable.
|
||||
//"%W1"..."%W100" -> current value of corresponding hero variable.
|
||||
//"%X1"..."%X16" -> current value of corresponding function parameter.
|
||||
//"%Y1"..."%Y100" -> current value of corresponding local variable.
|
||||
//"%Z1"..."%Z500" -> current value of corresponding string variable.
|
||||
//"%$macro$" -> macro name of corresponding variable
|
||||
//"%Dd" -> current day of week
|
||||
//"%Dw" -> current week
|
||||
//"%Dm" -> current month
|
||||
//"%Da" -> current day from beginning of the game
|
||||
//"%Gc" -> the color of current gamer in text
|
||||
struct StringFormatter
|
||||
{
|
||||
int pos;
|
||||
int tokenLength;
|
||||
int percentPos;
|
||||
int charsToReplace;
|
||||
std::string &msg;
|
||||
|
||||
StringFormatter(std::string &MSG) : msg(MSG), pos(0) {}
|
||||
|
||||
static void format(std::string &msg)
|
||||
{
|
||||
StringFormatter sf(msg);
|
||||
sf.format();
|
||||
}
|
||||
|
||||
// startpos is the first digit
|
||||
// digits will be converted to number and returned
|
||||
// ADDITIVE on digitsUsed
|
||||
int getNum()
|
||||
{
|
||||
int toAdd = 0;
|
||||
int numStart = percentPos + 2;
|
||||
int numEnd = msg.find_first_not_of("1234567890", numStart);
|
||||
|
||||
if(numEnd == std::string::npos)
|
||||
toAdd = msg.size() - numStart;
|
||||
else
|
||||
toAdd = numEnd - numStart;
|
||||
|
||||
charsToReplace += toAdd;
|
||||
return boost::lexical_cast<int>(msg.substr(numStart, toAdd));
|
||||
}
|
||||
|
||||
void format()
|
||||
{
|
||||
while(pos < msg.size())
|
||||
{
|
||||
percentPos = msg.find_first_of('%', pos);
|
||||
charsToReplace = 1; //at least the same '%' needs to be replaced
|
||||
|
||||
std::ostringstream replaceWithWhat;
|
||||
|
||||
if(percentPos == std::string::npos) //processing done?
|
||||
break;
|
||||
|
||||
if(percentPos + 1 >= msg.size()) //at least one character after % is required
|
||||
throw EScriptExecError("Formatting error: % at the end of string!");
|
||||
|
||||
charsToReplace++; //the sign after % is consumed
|
||||
switch(msg[percentPos+1])
|
||||
{
|
||||
case '%':
|
||||
replaceWithWhat << '%';
|
||||
break;
|
||||
case 'F':
|
||||
replaceWithWhat << erm->ermGlobalEnv->getFlag(getNum());
|
||||
break;
|
||||
case 'V':
|
||||
if(std::isdigit(msg[percentPos + 2]))
|
||||
replaceWithWhat << erm->ermGlobalEnv->getStandardVar(getNum());
|
||||
else
|
||||
{
|
||||
charsToReplace++;
|
||||
replaceWithWhat << erm->ermGlobalEnv->getQuickVar(msg[percentPos+2]);
|
||||
}
|
||||
case 'X':
|
||||
replaceWithWhat << erm->getVar("x", getNum()).getInt();
|
||||
break;
|
||||
case 'Z':
|
||||
replaceWithWhat << erm->ermGlobalEnv->getZVar(getNum());
|
||||
break;
|
||||
default:
|
||||
throw EScriptExecError("Formatting error: unrecognized token indicator after %!");
|
||||
}
|
||||
msg.replace(percentPos, charsToReplace, replaceWithWhat.str());
|
||||
pos = percentPos + 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct IFPerformer : StandardReceiverVisitor<TUnusedType>
|
||||
{
|
||||
IFPerformer(ERMInterpreter * _interpr) : StandardReceiverVisitor<TUnusedType>(_interpr, 0)
|
||||
@@ -807,69 +907,10 @@ struct IFPerformer : StandardReceiverVisitor<TUnusedType>
|
||||
}
|
||||
}
|
||||
|
||||
// startpos is the first digit
|
||||
// digits will be converted to number and returned
|
||||
static int getNum(std::string &msg, int numStart, int &digitsUsed)
|
||||
{
|
||||
int numEnd = msg.find_first_not_of("1234567890", numStart);
|
||||
|
||||
if(numEnd == std::string::npos)
|
||||
digitsUsed = msg.size() - numStart;
|
||||
else
|
||||
digitsUsed = numEnd - numStart;
|
||||
|
||||
return boost::lexical_cast<int>(msg.substr(numStart, digitsUsed));
|
||||
}
|
||||
|
||||
static void formatMessage(std::string &msg)
|
||||
{
|
||||
int pos = 0; //index of the first not yet processed character in string
|
||||
|
||||
//according to the ERM help:
|
||||
//"%%" -> "%"
|
||||
//"%V#" -> current value of # flag.
|
||||
//"%Vf"..."%Vt" -> current value of corresponding variable.
|
||||
//"%W1"..."%W100" -> current value of corresponding hero variable.
|
||||
//"%X1"..."%X16" -> current value of corresponding function parameter.
|
||||
//"%Y1"..."%Y100" -> current value of corresponding local variable.
|
||||
//"%Z1"..."%Z500" -> current value of corresponding string variable.
|
||||
//"%$macro$" -> macro name of corresponding variable
|
||||
//"%Dd" -> current day of week
|
||||
//"%Dw" -> current week
|
||||
//"%Dm" -> current month
|
||||
//"%Da" -> current day from beginning of the game
|
||||
//"%Gc" -> the color of current gamer in text
|
||||
|
||||
while(pos < msg.size())
|
||||
{
|
||||
int percentPos = msg.find_first_of('%', pos);
|
||||
if(percentPos == std::string::npos) //processing done?
|
||||
break;
|
||||
|
||||
if(percentPos + 1 >= msg.size()) //at least one character after % is required
|
||||
throw EScriptExecError("Formatting error: % at the end of string!");
|
||||
;
|
||||
switch(msg[percentPos+1])
|
||||
{
|
||||
case '%':
|
||||
msg.erase(percentPos+1, 1); //just delete superfluous %
|
||||
break;
|
||||
case 'X':
|
||||
{
|
||||
int digits;
|
||||
int varNum = getNum(msg, percentPos+2, digits);
|
||||
msg.replace(percentPos, digits+2, boost::lexical_cast<std::string>(erm->getVar("x", varNum).getInt()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
void showMessage(const std::string &msg)
|
||||
{
|
||||
std::string msgToFormat = msg;
|
||||
IFPerformer::formatMessage(msgToFormat);
|
||||
StringFormatter::format(msgToFormat);
|
||||
acb->showInfoDialog(msgToFormat, icb->getLocalPlayer());
|
||||
}
|
||||
};
|
||||
@@ -1937,54 +1978,6 @@ void ERMInterpreter::setCurrentlyVisitedObj( int3 pos )
|
||||
ermGlobalEnv->getStandardVar(1000) = pos.z;
|
||||
}
|
||||
|
||||
struct StringProcessHLP
|
||||
{
|
||||
int extractNumber(const std::string & token)
|
||||
{
|
||||
return atoi(token.substr(1).c_str());
|
||||
}
|
||||
template <typename T>
|
||||
void replaceToken(std::string ret, int tokenBegin, int tokenEnd, T val)
|
||||
{
|
||||
ret.replace(tokenBegin, tokenEnd, boost::lexical_cast<std::string>(val));
|
||||
}
|
||||
};
|
||||
|
||||
std::string ERMInterpreter::processERMString( std::string ermstring )
|
||||
{
|
||||
StringProcessHLP hlp;
|
||||
std::string ret = ermstring;
|
||||
int curPos = 0;
|
||||
while((curPos = ret.find('%', curPos)) != std::string::npos)
|
||||
{
|
||||
curPos++;
|
||||
int tokenEnd = ret.find(' ', curPos);
|
||||
std::string token = ret.substr(curPos, tokenEnd - curPos);
|
||||
if(token.size() == 0)
|
||||
{
|
||||
throw EScriptExecError("Empty token not allowed!");
|
||||
}
|
||||
|
||||
switch(token[0])
|
||||
{
|
||||
case '%':
|
||||
ret.erase(curPos);
|
||||
break;
|
||||
case 'F':
|
||||
hlp.replaceToken(ret, curPos, tokenEnd, ermGlobalEnv->getFlag(hlp.extractNumber(token)));
|
||||
break;
|
||||
case 'V':
|
||||
hlp.replaceToken(ret, curPos, tokenEnd, ermGlobalEnv->getStandardVar(hlp.extractNumber(token)));
|
||||
break;
|
||||
default:
|
||||
throw EScriptExecError("Unrecognized token in string");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const std::string ERMInterpreter::triggerSymbol = "trigger";
|
||||
const std::string ERMInterpreter::postTriggerSymbol = "postTrigger";
|
||||
const std::string ERMInterpreter::defunSymbol = "defun";
|
||||
@@ -2747,6 +2740,16 @@ void ERMInterpreter::executeUserCommand(const std::string &cmd)
|
||||
tlog0 << "ERM here: received command: " << cmd << std::endl;
|
||||
}
|
||||
|
||||
void ERMInterpreter::giveInfoCB(CPrivilagedInfoCallback *cb)
|
||||
{
|
||||
icb = cb;
|
||||
}
|
||||
|
||||
void ERMInterpreter::giveActionCB(IGameEventRealizer *cb)
|
||||
{
|
||||
acb = cb;
|
||||
}
|
||||
|
||||
namespace VERMInterpreter
|
||||
{
|
||||
VOption convertToVOption(const ERM::TVOption & tvo)
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
#include "../global.h"
|
||||
#include "../../global.h"
|
||||
#include "ERMParser.h"
|
||||
#include "IGameEventsReceiver.h"
|
||||
#include "ERMScriptModule.h"
|
||||
|
||||
/*
|
||||
@@ -841,6 +840,8 @@ public:
|
||||
virtual void heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visitedObj, bool start) OVERRIDE;
|
||||
virtual void init() OVERRIDE;//sets up environment etc.
|
||||
virtual void executeUserCommand(const std::string &cmd) OVERRIDE;
|
||||
virtual void giveInfoCB(CPrivilagedInfoCallback *cb) OVERRIDE;
|
||||
virtual void giveActionCB(IGameEventRealizer *cb) OVERRIDE;
|
||||
|
||||
virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) OVERRIDE;
|
||||
|
||||
@@ -854,4 +855,5 @@ public:
|
||||
else
|
||||
throw VERMInterpreter::EScriptExecError("Wrong cast attempted, object is not of a desired type!");
|
||||
}
|
||||
|
||||
};
|
||||
@@ -1,4 +1,3 @@
|
||||
#define VCMI_DLL
|
||||
#include "ERMParser.h"
|
||||
#include <boost/version.hpp>
|
||||
//To make compilation with older boost versions possible
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "../global.h"
|
||||
#include "../../global.h"
|
||||
#include <fstream>
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "ERMScriptModule.h"
|
||||
#include "ERMInterpreter.h"
|
||||
|
||||
IGameEventRealizer *acb;
|
||||
CPrivilagedInfoCallback *icb;
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define strcpy_s(a, b, c) strncpy(a, c, b)
|
||||
#endif
|
||||
|
||||
const char *g_cszAiName = "(V)ERM interpreter";
|
||||
|
||||
extern "C" DLL_F_EXPORT void GetAiName(char* name)
|
||||
{
|
||||
strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
|
||||
}
|
||||
|
||||
extern "C" DLL_F_EXPORT CScriptingModule* GetNewModule()
|
||||
{
|
||||
return new ERMInterpreter();
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/CScriptingModule.h"
|
||||
extern IGameEventRealizer *acb;
|
||||
extern CPrivilagedInfoCallback *icb;
|
||||
@@ -14,6 +14,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StupidAI", "AI\StupidAI\Stu
|
||||
{B952FFC5-3039-4DE1-9F08-90ACDA483D8F} = {B952FFC5-3039-4DE1-9F08-90ACDA483D8F}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ERM", "Scripting\ERM\ERM.vcxproj", "{8F202F43-106D-4F63-AD9D-B1D43E803E8C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
@@ -51,6 +53,12 @@ Global
|
||||
{15DABC90-234A-4B6B-9EEB-777C4768B82B}.RD|Win32.Build.0 = RD|Win32
|
||||
{15DABC90-234A-4B6B-9EEB-777C4768B82B}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{15DABC90-234A-4B6B-9EEB-777C4768B82B}.Release|Win32.Build.0 = Release|Win32
|
||||
{8F202F43-106D-4F63-AD9D-B1D43E803E8C}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{8F202F43-106D-4F63-AD9D-B1D43E803E8C}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{8F202F43-106D-4F63-AD9D-B1D43E803E8C}.RD|Win32.ActiveCfg = RD|Win32
|
||||
{8F202F43-106D-4F63-AD9D-B1D43E803E8C}.RD|Win32.Build.0 = RD|Win32
|
||||
{8F202F43-106D-4F63-AD9D-B1D43E803E8C}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{8F202F43-106D-4F63-AD9D-B1D43E803E8C}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@
|
||||
#include "../lib/CObjectHandler.h"
|
||||
#include <boost/program_options.hpp>
|
||||
#include "../lib/CArtHandler.h"
|
||||
#include "../lib/ERMScriptModule.h"
|
||||
#include "../lib/CScriptingModule.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "SDL_syswm.h"
|
||||
|
||||
+2
-28
@@ -48,6 +48,7 @@
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
#include "../CThreadHelper.h"
|
||||
#include "CConfigHandler.h"
|
||||
#include "../lib/CFileUtility.h"
|
||||
|
||||
/*
|
||||
* CPreGame.cpp, part of VCMI engine
|
||||
@@ -846,34 +847,7 @@ void SelectionTab::filter( int size, bool selectFirst )
|
||||
|
||||
void SelectionTab::getFiles(std::vector<FileInfo> &out, const std::string &dirname, const std::string &ext)
|
||||
{
|
||||
if(!boost::filesystem::exists(dirname))
|
||||
{
|
||||
tlog1 << "Cannot find " << dirname << " directory!\n";
|
||||
}
|
||||
fs::path tie(dirname);
|
||||
fs::directory_iterator end_iter;
|
||||
for ( fs::directory_iterator file (tie); file!=end_iter; ++file )
|
||||
{
|
||||
if(fs::is_regular_file(file->status())
|
||||
&& boost::ends_with(file->path().filename(), ext))
|
||||
{
|
||||
std::time_t date = 0;
|
||||
try
|
||||
{
|
||||
date = fs::last_write_time(file->path());
|
||||
|
||||
out.resize(out.size()+1);
|
||||
out.back().date = date;
|
||||
out.back().name = file->path().string();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
tlog2 << "\t\tWarning: very corrupted map file: " << file->path().string() << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
CFileUtility::getFilesWithExt(out, dirname, ext);
|
||||
allItems.resize(out.size());
|
||||
}
|
||||
|
||||
|
||||
+1
-7
@@ -30,6 +30,7 @@ class CCampaignState;
|
||||
class CConnection;
|
||||
struct CPackForSelectionScreen;
|
||||
struct PlayerInfo;
|
||||
struct FileInfo;
|
||||
|
||||
namespace boost{ class thread; class recursive_mutex;}
|
||||
|
||||
@@ -66,13 +67,6 @@ public:
|
||||
void moveTo(CMenuScreen *next);
|
||||
};
|
||||
|
||||
/// Struct which stores name, date and a value which says if the file is located in LOD
|
||||
struct FileInfo
|
||||
{
|
||||
std::string name; // file name with full path and extension
|
||||
std::time_t date;
|
||||
bool inLod; //tells if this file is located in Lod
|
||||
};
|
||||
|
||||
/// Implementation of the chat box
|
||||
class CChatBox : public CIntObject
|
||||
|
||||
+19
-12
@@ -33,7 +33,8 @@
|
||||
#include "CPreGame.h"
|
||||
#include "CBattleInterface.h"
|
||||
#include "../CThreadHelper.h"
|
||||
#include "../lib/ERMScriptModule.h"
|
||||
#include "../lib/CScriptingModule.h"
|
||||
#include "../lib/CFileUtility.h"
|
||||
|
||||
#define NOT_LIB
|
||||
#include "../lib/RegisterTypes.cpp"
|
||||
@@ -394,7 +395,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
CCallback *cb = new CCallback(gs,color,this);
|
||||
if(!it->second.human)
|
||||
{
|
||||
playerint[color] = static_cast<CGameInterface*>(CAIHandler::getNewAI(conf.cc.defaultPlayerAI));
|
||||
playerint[color] = static_cast<CGameInterface*>(CDynLibHandler::getNewAI(conf.cc.defaultPlayerAI));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -408,7 +409,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
else
|
||||
{
|
||||
CBattleCallback * cbc = new CBattleCallback(gs, color, this);
|
||||
battleints[color] = CAIHandler::getNewBattleAI("StupidAI");
|
||||
battleints[color] = CDynLibHandler::getNewBattleAI("StupidAI");
|
||||
battleints[color]->init(cbc);
|
||||
}
|
||||
}
|
||||
@@ -430,13 +431,19 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
serv->addStdVecItems(const_cast<CGameInfo*>(CGI)->state);
|
||||
hotSeat = (humanPlayers > 1);
|
||||
|
||||
std::vector<FileInfo> scriptModules;
|
||||
CFileUtility::getFilesWithExt(scriptModules, "./Scripting", ".dll");
|
||||
BOOST_FOREACH(FileInfo &m, scriptModules)
|
||||
{
|
||||
CScriptingModule * nm = CDynLibHandler::getNewScriptingModule(m.name);
|
||||
privilagedGameEventReceivers.push_back(nm);
|
||||
privilagedBattleEventReceivers.push_back(nm);
|
||||
nm->giveActionCB(this);
|
||||
nm->giveInfoCB(this);
|
||||
nm->init();
|
||||
|
||||
erm = getERMModule();
|
||||
privilagedGameEventReceivers.push_back(erm);
|
||||
privilagedBattleEventReceivers.push_back(erm);
|
||||
icb = this;
|
||||
acb = this;
|
||||
erm->init();
|
||||
erm = nm; //something tells me that there'll at most one module and it'll be ERM
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
@@ -472,14 +479,14 @@ void CClient::serialize( Handler &h, const int version )
|
||||
if(pid == 255)
|
||||
{
|
||||
CBattleCallback * cbc = new CBattleCallback(gs, pid, this);
|
||||
CBattleGameInterface *cbgi = CAIHandler::getNewBattleAI(dllname);
|
||||
CBattleGameInterface *cbgi = CDynLibHandler::getNewBattleAI(dllname);
|
||||
battleints[pid] = cbgi;
|
||||
cbgi->init(cb);
|
||||
//TODO? consider serialization
|
||||
continue;
|
||||
}
|
||||
else
|
||||
nInt = CAIHandler::getNewAI(dllname);
|
||||
nInt = CDynLibHandler::getNewAI(dllname);
|
||||
}
|
||||
else
|
||||
nInt = new CPlayerInterface(pid);
|
||||
@@ -591,7 +598,7 @@ void CClient::battleStarted(const BattleInfo * info)
|
||||
|
||||
void CClient::loadNeutralBattleAI()
|
||||
{
|
||||
battleints[255] = CAIHandler::getNewBattleAI(conf.cc.defaultBattleAI);
|
||||
battleints[255] = CDynLibHandler::getNewBattleAI(conf.cc.defaultBattleAI);
|
||||
battleints[255]->init(new CBattleCallback(gs, 255, this));
|
||||
}
|
||||
|
||||
|
||||
@@ -51,22 +51,24 @@ extern std::string NAME_AFFIX; //client / server
|
||||
* LIB_DIR is where the AI libraries reside (linux only)
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
#define DATA_DIR "."
|
||||
#define USER_DIR "."
|
||||
#define BIN_DIR "."
|
||||
#define LIB_DIR "AI"
|
||||
#define SERVER_NAME "VCMI_server.exe"
|
||||
#define DATA_DIR "."
|
||||
#define USER_DIR "."
|
||||
#define BIN_DIR "."
|
||||
#define LIB_DIR "AI"
|
||||
#define SERVER_NAME "VCMI_server.exe"
|
||||
#define LIB_EXT "dll"
|
||||
#else
|
||||
#ifndef DATA_DIR
|
||||
#error DATA_DIR undefined.
|
||||
#endif
|
||||
#ifndef BIN_DIR
|
||||
#error BIN_DIR undefined.
|
||||
#endif
|
||||
#ifndef LIB_DIR
|
||||
#error LIB_DIR undefined.
|
||||
#endif
|
||||
#define SERVER_NAME "vcmiserver"
|
||||
#ifndef DATA_DIR
|
||||
#error DATA_DIR undefined.
|
||||
#endif
|
||||
#ifndef BIN_DIR
|
||||
#error BIN_DIR undefined.
|
||||
#endif
|
||||
#ifndef LIB_DIR
|
||||
#error LIB_DIR undefined.
|
||||
#endif
|
||||
#define SERVER_NAME "vcmiserver"
|
||||
#define LIB_EXT "so"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
+16
-1
@@ -268,7 +268,14 @@ void CCreatureSet::clear()
|
||||
const CStackInstance& CCreatureSet::getStack(TSlot slot) const
|
||||
{
|
||||
assert(hasStackAtSlot(slot));
|
||||
return *stacks.find(slot)->second;
|
||||
return *getStackPtr(slot);
|
||||
}
|
||||
|
||||
const CStackInstance* CCreatureSet::getStackPtr(TSlot slot) const
|
||||
{
|
||||
if(hasStackAtSlot(slot))
|
||||
return stacks.find(slot)->second;
|
||||
else return NULL;
|
||||
}
|
||||
|
||||
void CCreatureSet::eraseStack(TSlot slot)
|
||||
@@ -914,6 +921,14 @@ void CStackInstance::deserializationFix()
|
||||
setArmyObj(armyBackup);
|
||||
}
|
||||
|
||||
int CStackInstance::getCreatureID() const
|
||||
{
|
||||
if(type)
|
||||
return type->idNumber;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
CStackBasicDescriptor::CStackBasicDescriptor()
|
||||
{
|
||||
type = NULL;
|
||||
|
||||
+3
-1
@@ -53,6 +53,7 @@ public:
|
||||
std::string getQuantityTXT(bool capitalized = true) const;
|
||||
int getExpRank() const;
|
||||
si32 magicResistance() const;
|
||||
int getCreatureID() const; //-1 if not available
|
||||
void init();
|
||||
CStackInstance();
|
||||
CStackInstance(TCreature id, TQuantity count);
|
||||
@@ -132,7 +133,8 @@ public:
|
||||
bool setCreature (TSlot slot, TCreature type, TQuantity quantity) OVERRIDE; //replaces creature in stack; slots 0 to 6, if quantity=0 erases stack
|
||||
void setToArmy(CSimpleArmy &src); //erases all our army and moves stacks from src to us; src MUST NOT be an armed object! WARNING: use it wisely. Or better do not use at all.
|
||||
|
||||
const CStackInstance& getStack(TSlot slot) const;
|
||||
const CStackInstance& getStack(TSlot slot) const; //stack must exist
|
||||
const CStackInstance* getStackPtr(TSlot slot) const; //if stack doesn't exist, returns NULL
|
||||
const CCreature* getCreature(TSlot slot) const; //workaround of map issue;
|
||||
int getStackCount (TSlot slot) const;
|
||||
expType getStackExperience(TSlot slot) const;
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#define VCMI_DLL
|
||||
#include "CFileUtility.h"
|
||||
#include <boost/filesystem.hpp> // includes all needed Boost.Filesystem declarations
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
CFileUtility::CFileUtility(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CFileUtility::~CFileUtility(void)
|
||||
{
|
||||
}
|
||||
|
||||
void CFileUtility::getFilesWithExt(std::vector<FileInfo> &out, const std::string &dirname, const std::string &ext)
|
||||
{
|
||||
if(!fs::exists(dirname))
|
||||
{
|
||||
tlog1 << "Cannot find " << dirname << " directory!\n";
|
||||
}
|
||||
fs::path tie(dirname);
|
||||
fs::directory_iterator end_iter;
|
||||
for ( fs::directory_iterator file (tie); file!=end_iter; ++file )
|
||||
{
|
||||
if(fs::is_regular_file(file->status())
|
||||
&& boost::ends_with(file->path().filename(), ext))
|
||||
{
|
||||
std::time_t date = 0;
|
||||
try
|
||||
{
|
||||
date = fs::last_write_time(file->path());
|
||||
|
||||
out.resize(out.size()+1);
|
||||
out.back().date = date;
|
||||
out.back().name = file->path().string();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
tlog2 << "\t\tWarning: very corrupted file: " << file->path().string() << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "../global.h"
|
||||
|
||||
/// Struct which stores name, date and a value which says if the file is located in LOD
|
||||
struct FileInfo
|
||||
{
|
||||
std::string name; // file name with full path and extension
|
||||
std::time_t date;
|
||||
bool inLod; //tells if this file is located in Lod
|
||||
};
|
||||
|
||||
class DLL_EXPORT CFileUtility
|
||||
{
|
||||
public:
|
||||
CFileUtility(void);
|
||||
~CFileUtility(void);
|
||||
|
||||
static void getFilesWithExt(std::vector<FileInfo> &out, const std::string &dirname, const std::string &ext);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include "../global.h"
|
||||
#include "IGameEventsReceiver.h"
|
||||
#include "IGameCallback.h"
|
||||
|
||||
class CScriptingModule : public IGameEventsReceiver, public IBattleEventsReceiver
|
||||
{
|
||||
public:
|
||||
virtual void executeUserCommand(const std::string &cmd){};
|
||||
virtual void init(){}; //called upon the start of game (after map randomization, before first turn)
|
||||
virtual void giveActionCB(IGameEventRealizer *cb){};
|
||||
virtual void giveInfoCB(CPrivilagedInfoCallback *cb){};
|
||||
|
||||
CScriptingModule(){}
|
||||
virtual ~CScriptingModule(){}
|
||||
};
|
||||
@@ -1,20 +0,0 @@
|
||||
#define VCMI_DLL
|
||||
|
||||
#include "ERMScriptModule.h"
|
||||
#include "ERMInterpreter.h"
|
||||
#include "CObjectHandler.h"
|
||||
|
||||
IGameEventRealizer *acb;
|
||||
CPrivilagedInfoCallback *icb;
|
||||
|
||||
|
||||
CScriptingModule * getERMModule()
|
||||
{
|
||||
CScriptingModule *ret = new ERMInterpreter();
|
||||
return ret;
|
||||
}
|
||||
|
||||
CScriptingModule::~CScriptingModule()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "../global.h"
|
||||
#include "IGameEventsReceiver.h"
|
||||
#include "IGameCallback.h"
|
||||
|
||||
class IGameEventRealizer;
|
||||
|
||||
class ERMInterpreter;
|
||||
|
||||
class DLL_EXPORT CScriptingModule : public IGameEventsReceiver, public IBattleEventsReceiver
|
||||
{
|
||||
public:
|
||||
virtual void executeUserCommand(const std::string &cmd){};
|
||||
virtual void init(){}; //called upon the start of game (after map randomization, before first turn)
|
||||
virtual ~CScriptingModule();
|
||||
};
|
||||
|
||||
extern DLL_EXPORT IGameEventRealizer *acb;
|
||||
extern DLL_EXPORT CPrivilagedInfoCallback *icb;
|
||||
|
||||
|
||||
DLL_EXPORT CScriptingModule *getERMModule();
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
#include "CBuildingHandler.h"
|
||||
#include "CSpellHandler.h"
|
||||
#include "CGeneralTextHandler.h"
|
||||
#include "ERMInterpreter.h"
|
||||
#include "IGameEventsReceiver.h"
|
||||
|
||||
/*
|
||||
* VCMI_Lib.cpp, part of VCMI engine
|
||||
|
||||
@@ -172,6 +172,7 @@
|
||||
<ClCompile Include="CCreatureHandler.cpp" />
|
||||
<ClCompile Include="CCreatureSet.cpp" />
|
||||
<ClCompile Include="CDefObjInfoHandler.cpp" />
|
||||
<ClCompile Include="CFileUtility.cpp" />
|
||||
<ClCompile Include="CGameState.cpp" />
|
||||
<ClCompile Include="CGeneralTextHandler.cpp" />
|
||||
<ClCompile Include="CHeroHandler.cpp" />
|
||||
@@ -181,9 +182,6 @@
|
||||
<ClCompile Include="Connection.cpp" />
|
||||
<ClCompile Include="CSpellHandler.cpp" />
|
||||
<ClCompile Include="CTownHandler.cpp" />
|
||||
<ClCompile Include="ERMInterpreter.cpp" />
|
||||
<ClCompile Include="ERMParser.cpp" />
|
||||
<ClCompile Include="ERMScriptModule.cpp" />
|
||||
<ClCompile Include="HeroBonus.cpp" />
|
||||
<ClCompile Include="IGameCallback.cpp" />
|
||||
<ClCompile Include="map.cpp" />
|
||||
@@ -204,6 +202,7 @@
|
||||
<ClInclude Include="CCreatureHandler.h" />
|
||||
<ClInclude Include="CCreatureSet.h" />
|
||||
<ClInclude Include="CDefObjInfoHandler.h" />
|
||||
<ClInclude Include="CFileUtility.h" />
|
||||
<ClInclude Include="CGameState.h" />
|
||||
<ClInclude Include="CGeneralTextHandler.h" />
|
||||
<ClInclude Include="CHeroHandler.h" />
|
||||
@@ -214,11 +213,9 @@
|
||||
<ClInclude Include="CondSh.h" />
|
||||
<ClInclude Include="Connection.h" />
|
||||
<ClInclude Include="ConstTransitivePtr.h" />
|
||||
<ClInclude Include="CScriptingModule.h" />
|
||||
<ClInclude Include="CSpellHandler.h" />
|
||||
<ClInclude Include="CTownHandler.h" />
|
||||
<ClInclude Include="ERMInterpreter.h" />
|
||||
<ClInclude Include="ERMParser.h" />
|
||||
<ClInclude Include="ERMScriptModule.h" />
|
||||
<ClInclude Include="HeroBonus.h" />
|
||||
<ClInclude Include="IGameCallback.h" />
|
||||
<ClInclude Include="IGameEventsReceiver.h" />
|
||||
|
||||
Reference in New Issue
Block a user