Browse Source

Merge branch 'master' of http://git.tfgamessite.com/KevinSmarts/girllife-ecv into release

KevinSmarts 6 years ago
parent
commit
be8c872fb5
100 changed files with 7489 additions and 365 deletions
  1. 1 1
      MakeQSP.bat
  2. 0 0
      QSP/Player-original/fmodexp.dll
  3. 0 0
      QSP/Player-original/langs/de/qspgui.mo
  4. 0 0
      QSP/Player-original/langs/en/qspgui.mo
  5. 0 0
      QSP/Player-original/langs/eo/qspgui.mo
  6. 0 0
      QSP/Player-original/langs/ru/qspgui.mo
  7. 0 0
      QSP/Player-original/langs/uk/qspgui.mo
  8. 0 0
      QSP/Player-original/qsp.dll
  9. 0 0
      QSP/Player-original/qspgui.exe
  10. BIN
      QSP/Player-video/fmodexp.dll
  11. BIN
      QSP/Player-video/langs/de/qspgui.mo
  12. BIN
      QSP/Player-video/langs/en/qspgui.mo
  13. BIN
      QSP/Player-video/langs/eo/qspgui.mo
  14. BIN
      QSP/Player-video/langs/ru/qspgui.mo
  15. BIN
      QSP/Player-video/langs/uk/qspgui.mo
  16. BIN
      QSP/Player-video/libvlc.dll
  17. BIN
      QSP/Player-video/libvlccore.dll
  18. BIN
      QSP/Player-video/plugins/access/libfilesystem_plugin.dll
  19. BIN
      QSP/Player-video/plugins/audio_output/libdirectsound_plugin.dll
  20. BIN
      QSP/Player-video/plugins/codec/libavcodec_plugin.dll
  21. BIN
      QSP/Player-video/plugins/codec/libdxva2_plugin.dll
  22. BIN
      QSP/Player-video/plugins/plugins.dat
  23. BIN
      QSP/Player-video/plugins/video_chroma/libchain_plugin.dll
  24. BIN
      QSP/Player-video/plugins/video_chroma/libgrey_yuv_plugin.dll
  25. BIN
      QSP/Player-video/plugins/video_chroma/libi420_rgb_mmx_plugin.dll
  26. BIN
      QSP/Player-video/plugins/video_chroma/libi420_rgb_plugin.dll
  27. BIN
      QSP/Player-video/plugins/video_chroma/libi420_rgb_sse2_plugin.dll
  28. BIN
      QSP/Player-video/plugins/video_chroma/libi420_yuy2_mmx_plugin.dll
  29. BIN
      QSP/Player-video/plugins/video_chroma/libi420_yuy2_plugin.dll
  30. BIN
      QSP/Player-video/plugins/video_chroma/libi420_yuy2_sse2_plugin.dll
  31. BIN
      QSP/Player-video/plugins/video_chroma/libi422_i420_plugin.dll
  32. BIN
      QSP/Player-video/plugins/video_chroma/libi422_yuy2_mmx_plugin.dll
  33. BIN
      QSP/Player-video/plugins/video_chroma/libi422_yuy2_plugin.dll
  34. BIN
      QSP/Player-video/plugins/video_chroma/libi422_yuy2_sse2_plugin.dll
  35. BIN
      QSP/Player-video/plugins/video_chroma/librv32_plugin.dll
  36. BIN
      QSP/Player-video/plugins/video_chroma/libswscale_plugin.dll
  37. BIN
      QSP/Player-video/plugins/video_chroma/libyuy2_i420_plugin.dll
  38. BIN
      QSP/Player-video/plugins/video_chroma/libyuy2_i422_plugin.dll
  39. BIN
      QSP/Player-video/plugins/video_filter/libscale_plugin.dll
  40. BIN
      QSP/Player-video/plugins/video_filter/libyuvp_plugin.dll
  41. BIN
      QSP/Player-video/plugins/video_output/libdirect2d_plugin.dll
  42. BIN
      QSP/Player-video/plugins/video_output/libdirect3d_plugin.dll
  43. BIN
      QSP/Player-video/plugins/video_output/libdirectdraw_plugin.dll
  44. BIN
      QSP/Player-video/plugins/video_output/libdrawable_plugin.dll
  45. BIN
      QSP/Player-video/plugins/video_output/libgl_plugin.dll
  46. BIN
      QSP/Player-video/plugins/video_output/libglwin32_plugin.dll
  47. BIN
      QSP/Player-video/plugins/video_output/libyuv_plugin.dll
  48. BIN
      QSP/Player-video/qsp.dll
  49. BIN
      QSP/Player-video/qspgui.exe
  50. BIN
      QSP/qsp-analyser/QSP_Analyser.exe
  51. 32 0
      QSP/qsp-analyser/QSP_Analyser.sln
  52. 1519 0
      QSP/qsp-analyser/QSP_Analyser/Common.cs
  53. 667 0
      QSP/qsp-analyser/QSP_Analyser/List.txt
  54. 631 0
      QSP/qsp-analyser/QSP_Analyser/MainForm.Designer.cs
  55. 591 0
      QSP/qsp-analyser/QSP_Analyser/MainForm.cs
  56. 123 0
      QSP/qsp-analyser/QSP_Analyser/MainForm.resx
  57. 20 0
      QSP/qsp-analyser/QSP_Analyser/Program.cs
  58. 36 0
      QSP/qsp-analyser/QSP_Analyser/Properties/AssemblyInfo.cs
  59. 63 0
      QSP/qsp-analyser/QSP_Analyser/Properties/Resources.Designer.cs
  60. 117 0
      QSP/qsp-analyser/QSP_Analyser/Properties/Resources.resx
  61. 281 0
      QSP/qsp-analyser/QSP_Analyser/Properties/Settings.Designer.cs
  62. 172 0
      QSP/qsp-analyser/QSP_Analyser/Properties/Settings.settings
  63. 26 0
      QSP/qsp-analyser/QSP_Analyser/Properties/app.manifest
  64. 2244 0
      QSP/qsp-analyser/QSP_Analyser/QSPGameCode.cs
  65. 141 0
      QSP/qsp-analyser/QSP_Analyser/QSP_Analyser.csproj
  66. 16 0
      QSP/qsp-analyser/QSP_Analyser/QSP_Analyser.csproj.user
  67. 28 0
      QSP/qsp-analyser/QSP_Analyser/Settings.cs
  68. 178 0
      QSP/qsp-analyser/QSP_Analyser/app.config
  69. BIN
      QSP/sound/codec_aiff.dll
  70. BIN
      QSP/sound/codec_asf.dll
  71. BIN
      QSP/sound/codec_dls.dll
  72. BIN
      QSP/sound/codec_flac.dll
  73. BIN
      QSP/sound/codec_fsb.dll
  74. BIN
      QSP/sound/codec_it.dll
  75. BIN
      QSP/sound/codec_midi.dll
  76. BIN
      QSP/sound/codec_mod.dll
  77. BIN
      QSP/sound/codec_mpeg.dll
  78. BIN
      QSP/sound/codec_oggvorbis.dll
  79. BIN
      QSP/sound/codec_playlist.dll
  80. BIN
      QSP/sound/codec_s3m.dll
  81. BIN
      QSP/sound/codec_tag.dll
  82. BIN
      QSP/sound/codec_vag.dll
  83. BIN
      QSP/sound/codec_wav.dll
  84. BIN
      QSP/sound/codec_xm.dll
  85. BIN
      QSP/sound/output_dsound.dll
  86. 3 0
      To_do_list
  87. 1 2
      glife-notepad++
  88. 75 44
      glife.qproj
  89. 2 6
      locations/BDSM_Club
  90. 16 16
      locations/BDman
  91. 3 46
      locations/BDsex
  92. 21 21
      locations/BelSex
  93. 458 212
      locations/Cheatmenu_din
  94. 1 1
      locations/Cum_Manage
  95. 9 2
      locations/DNA
  96. 6 6
      locations/DanceWhore3
  97. 5 5
      locations/DanceWhore4
  98. 1 1
      locations/DanceWhore6
  99. 1 1
      locations/DanceWhore7
  100. 1 1
      locations/DanceWhore8

+ 1 - 1
MakeQSP.bat

@@ -5,7 +5,7 @@
 :: set CP_TO=..\GL_ECV
 
 :: This is the program used to open the QSPFILE. If you comment this line windows will launch the default app for the ".qsp" extension.
-set QSPGUI=QSP\qspgui.exe
+set QSPGUI=QSP\Player-video\qspgui.exe
 set QGEN=QSP\QGen5\QGen.exe
 
 :: The file that will be generated or open

+ 0 - 0
QSP/fmodexp.dll → QSP/Player-original/fmodexp.dll


+ 0 - 0
QSP/langs/de/qspgui.mo → QSP/Player-original/langs/de/qspgui.mo


+ 0 - 0
QSP/langs/en/qspgui.mo → QSP/Player-original/langs/en/qspgui.mo


+ 0 - 0
QSP/langs/eo/qspgui.mo → QSP/Player-original/langs/eo/qspgui.mo


+ 0 - 0
QSP/langs/ru/qspgui.mo → QSP/Player-original/langs/ru/qspgui.mo


+ 0 - 0
QSP/langs/uk/qspgui.mo → QSP/Player-original/langs/uk/qspgui.mo


+ 0 - 0
QSP/qsp.dll → QSP/Player-original/qsp.dll


+ 0 - 0
QSP/qspgui.exe → QSP/Player-original/qspgui.exe


BIN
QSP/Player-video/fmodexp.dll


BIN
QSP/Player-video/langs/de/qspgui.mo


BIN
QSP/Player-video/langs/en/qspgui.mo


BIN
QSP/Player-video/langs/eo/qspgui.mo


BIN
QSP/Player-video/langs/ru/qspgui.mo


BIN
QSP/Player-video/langs/uk/qspgui.mo


BIN
QSP/Player-video/libvlc.dll


BIN
QSP/Player-video/libvlccore.dll


BIN
QSP/Player-video/plugins/access/libfilesystem_plugin.dll


BIN
QSP/Player-video/plugins/audio_output/libdirectsound_plugin.dll


BIN
QSP/Player-video/plugins/codec/libavcodec_plugin.dll


BIN
QSP/Player-video/plugins/codec/libdxva2_plugin.dll


BIN
QSP/Player-video/plugins/plugins.dat


BIN
QSP/Player-video/plugins/video_chroma/libchain_plugin.dll


BIN
QSP/Player-video/plugins/video_chroma/libgrey_yuv_plugin.dll


BIN
QSP/Player-video/plugins/video_chroma/libi420_rgb_mmx_plugin.dll


BIN
QSP/Player-video/plugins/video_chroma/libi420_rgb_plugin.dll


BIN
QSP/Player-video/plugins/video_chroma/libi420_rgb_sse2_plugin.dll


BIN
QSP/Player-video/plugins/video_chroma/libi420_yuy2_mmx_plugin.dll


BIN
QSP/Player-video/plugins/video_chroma/libi420_yuy2_plugin.dll


BIN
QSP/Player-video/plugins/video_chroma/libi420_yuy2_sse2_plugin.dll


BIN
QSP/Player-video/plugins/video_chroma/libi422_i420_plugin.dll


BIN
QSP/Player-video/plugins/video_chroma/libi422_yuy2_mmx_plugin.dll


BIN
QSP/Player-video/plugins/video_chroma/libi422_yuy2_plugin.dll


BIN
QSP/Player-video/plugins/video_chroma/libi422_yuy2_sse2_plugin.dll


BIN
QSP/Player-video/plugins/video_chroma/librv32_plugin.dll


BIN
QSP/Player-video/plugins/video_chroma/libswscale_plugin.dll


BIN
QSP/Player-video/plugins/video_chroma/libyuy2_i420_plugin.dll


BIN
QSP/Player-video/plugins/video_chroma/libyuy2_i422_plugin.dll


BIN
QSP/Player-video/plugins/video_filter/libscale_plugin.dll


BIN
QSP/Player-video/plugins/video_filter/libyuvp_plugin.dll


BIN
QSP/Player-video/plugins/video_output/libdirect2d_plugin.dll


BIN
QSP/Player-video/plugins/video_output/libdirect3d_plugin.dll


BIN
QSP/Player-video/plugins/video_output/libdirectdraw_plugin.dll


BIN
QSP/Player-video/plugins/video_output/libdrawable_plugin.dll


BIN
QSP/Player-video/plugins/video_output/libgl_plugin.dll


BIN
QSP/Player-video/plugins/video_output/libglwin32_plugin.dll


BIN
QSP/Player-video/plugins/video_output/libyuv_plugin.dll


BIN
QSP/Player-video/qsp.dll


BIN
QSP/Player-video/qspgui.exe


BIN
QSP/qsp-analyser/QSP_Analyser.exe


+ 32 - 0
QSP/qsp-analyser/QSP_Analyser.sln

@@ -0,0 +1,32 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26430.16
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QSP_Analyser", "QSP_Analyser\QSP_Analyser.csproj", "{0EB1C8F9-E5A2-4C13-8ED2-C1897332F197}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Debug|Mixed Platforms = Debug|Mixed Platforms
+		Debug|Win32 = Debug|Win32
+		Release|Any CPU = Release|Any CPU
+		Release|Mixed Platforms = Release|Mixed Platforms
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{0EB1C8F9-E5A2-4C13-8ED2-C1897332F197}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0EB1C8F9-E5A2-4C13-8ED2-C1897332F197}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0EB1C8F9-E5A2-4C13-8ED2-C1897332F197}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{0EB1C8F9-E5A2-4C13-8ED2-C1897332F197}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{0EB1C8F9-E5A2-4C13-8ED2-C1897332F197}.Debug|Win32.ActiveCfg = Debug|Any CPU
+		{0EB1C8F9-E5A2-4C13-8ED2-C1897332F197}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{0EB1C8F9-E5A2-4C13-8ED2-C1897332F197}.Release|Any CPU.Build.0 = Release|Any CPU
+		{0EB1C8F9-E5A2-4C13-8ED2-C1897332F197}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{0EB1C8F9-E5A2-4C13-8ED2-C1897332F197}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{0EB1C8F9-E5A2-4C13-8ED2-C1897332F197}.Release|Win32.ActiveCfg = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 1519 - 0
QSP/qsp-analyser/QSP_Analyser/Common.cs

@@ -0,0 +1,1519 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace Analyser
+{
+    public class Common
+    {
+        const int QSP_MAXSTATSNAMES = 100;
+        const int QSP_STATSLEVELS = 3;
+        const int QSP_STATMAXARGS = 10;
+	    const int QSP_OPSLEVELS = 2;
+	    const int QSP_MAXOPSNAMES = 100;
+        const int QSP_OPMAXARGS = 10;
+	    public const int QSP_STACKSIZE = 30;
+        public const int QSP_MAXITEMS = 100;
+
+        public const int INVALID_INDEX = -1;
+        static public char[] WhiteSpace = {' ', '\t', '\r', '\n'};
+        //Разделители - " \t&'\"()[]=!<>+-/*:,{}"
+        static public char[] Delimiters = " \t&'\"()[]=!<>+-/*:,{}".ToCharArray();
+        static public char[] Digits = "0123456789".ToCharArray();
+        static public char[] LatinLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqsrtuvwxyz".ToCharArray();
+        static public char[] RussianLetters = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъьэюя".ToCharArray();
+        public struct QspStatement
+        {
+            public int ExtArg;
+            public int MinArgsCount;
+            public int MaxArgsCount;
+            public int[] ArgsTypes;
+        }
+        public struct QspStatementName
+        {
+            public string Name;
+            public int NameLen;
+            public int Code;
+        }
+        public enum QspStatementType
+        {
+            Unknown,
+            Label,
+            Comment,
+            Act,
+            For,
+            Local,
+            If,
+            ElseIf,
+            Else,
+            End,
+            AddObj,
+            ClA,
+            Clear,
+            CloseAll,
+            Close,
+            ClS,
+            CmdClear,
+            CopyArr,
+            DelAct,
+            DelObj,
+            Dynamic,
+            Exec,
+            Exit,
+            FreeLib,
+            GoSub,
+            GoTo,
+            IncLib,
+            Jump,
+            KillAll,
+            KillObj,
+            KillVar,
+            MClear,
+            Menu,
+            MNL,
+            MPL,
+            MP,
+            Msg,
+            NL,
+            OpenGame,
+            OpenQst,
+            Play,
+            PL,
+            P,
+            RefInt,
+            SaveGame,
+            SetTimer,
+            Set,
+            ShowActs,
+            ShowInput,
+            ShowObjs,
+            ShowVars,
+            UnSelect,
+            View,
+            Wait,
+            XGoTo,
+
+            Last_Statement
+        };
+
+        public struct QspFunction
+        {
+		    public int Priority;
+		    public int ResType;
+		    public int MinArgsCount;
+		    public int MaxArgsCount;
+		    public int[] ArgsTypes;
+        }
+        public struct QspFunctionName
+        {
+            public string Name;
+            public int NameLen;
+            public int Code;
+        }
+        public enum QspFunctionType
+        {
+            Unknown,
+            Start,
+            End,
+            Value,
+            OpenBracket,
+            Minus,
+            Comma,
+            CloseBracket,
+            Mul,
+            Div,
+            Add,
+            Sub,
+            Mod,
+            Ne,
+            Leq,
+            Geq,
+            Eq,
+            Lt,
+            Gt,
+            And,
+            Or,
+            Append,
+
+            First_Function,
+            Not = First_Function,
+            Loc,
+            Obj,
+            Min,
+            Max,
+            Rand,
+            IIf,
+            RGB,
+            Len,
+            IsNum,
+            LCase,
+            UCase,
+            Input,
+            Str,
+            Val,
+            ArrSize,
+            IsPlay,
+            Desc,
+            Trim,
+            GetObj,
+            StrComp,
+            StrFind,
+            StrPos,
+            Mid,
+            ArrPos,
+            ArrComp,
+            Instr,
+            Replace,
+            Func,
+            DynEval,
+            Rnd,
+            CountObj,
+            MsecsCount,
+            QSPVer,
+            UserText,
+            CurLoc,
+            SelObj,
+            SelAct,
+            MainText,
+            StatText,
+            CurActs,
+
+            Last_Operation
+        };
+
+        static public QspStatement[] qspStats;
+        static QspStatementName[,] qspStatsNames;
+        static int[] qspStatsNamesCounts;
+        static int qspStatMaxLen;
+        static public QspFunction[] qspOps;
+        static QspFunctionName[,] qspOpsNames;
+        static int[] qspOpsNamesCounts;
+        static int qspOpMaxLen;
+        static bool inited = false;
+
+        public class QspVariable
+        {
+            public bool IsString;
+            public string Name;
+            public bool Assigned;
+            public bool Used;
+            public QspVariable(string name, bool assigned, bool used)
+            {
+                IsString = name.IndexOf('$') == 0;
+                Name = name;
+                Assigned = assigned;
+                Used = used;
+            }
+        }
+        public class QspLocationLink
+        {
+            public string LocationName;
+            public bool LocationExists;
+            public bool LocationCalled;
+            public QspLocationLink(string name, bool exists, bool called)
+            {
+                LocationName = name;
+                LocationExists = exists;
+                LocationCalled = called;
+            }
+        }
+        public class QspObj
+        {
+            public string Name;
+            public bool Added;
+            public bool Removed;
+            public QspObj(string name, bool added, bool removed)
+            {
+                Name = name;
+                Added = added;
+                Removed = removed;
+            }
+        }
+        public class QspAct
+        {
+            public string Name;
+            public bool Added;
+            public bool Removed;
+            public QspAct(string name, bool added, bool removed)
+            {
+                Name = name;
+                Added = added;
+                Removed = removed;
+            }
+        }
+        static public List<QspVariable> vars;
+        static public List<QspLocationLink> locationLinks;
+        static public List<QspObj> objects;
+        static public List<QspAct> acts;
+
+        static public List<string> callerVariables;
+        static public List<string> systemVariables;
+        static public bool curlyParsing;
+
+        static public string currentLocation;
+
+        public enum QuoteType
+        {
+            None,
+            Single,
+            Double
+        }
+
+        public struct QspError
+        {
+            public string locationName; //Локация, на которой встретилась ошибка
+            public string text;         //Текст сообщения об ошибке
+            public int line;            //Номер строки в локации
+            public bool isError;        //Тип ошибки, если "true" - ошибка синтаксиса, если "false" - предупреждение
+        }
+        static List<QspError> m_errors;
+        static int m_errorCounter;
+        public static int GetErrorsCount()
+        {
+            return m_errorCounter;
+        }
+        static int m_warningCounter;
+        public static int GetWarningsCount()
+        {
+            return m_warningCounter;
+        }
+
+        public Common()
+        {
+            if (!inited)
+            {
+                inited = true;
+                qspStats = new QspStatement[(int)QspStatementType.Last_Statement];
+                qspStatsNames = new QspStatementName[QSP_STATSLEVELS, QSP_MAXSTATSNAMES];
+                qspStatsNamesCounts = new int[QSP_STATSLEVELS];
+                qspOps = new QspFunction[(int)QspFunctionType.Last_Operation];
+                qspOpsNames = new QspFunctionName[QSP_OPSLEVELS, QSP_MAXOPSNAMES];
+                qspOpsNamesCounts = new int[QSP_OPSLEVELS];
+
+                m_errors = new List<QspError>();
+                InitQsp();
+                ClearErrors();
+            }
+        }
+
+        static public void ClearErrors()
+        {
+            m_errors.Clear();
+            m_errorCounter = 0;
+            m_warningCounter = 0;
+        }
+
+        static public void ClearNonGameErrors()
+        {
+            for (int index = 0; index < m_errors.Count; ++index)
+            {
+                if (m_errors[index].isError && (m_errors[index].line == INVALID_INDEX))
+                {
+
+                    m_errors.RemoveAt(index);
+                    --index;
+                    m_errorCounter--;
+                }
+            }
+        }
+
+        static public void SubmitError(string text, int line)
+        {
+            QspError e;
+            e.locationName = currentLocation;
+            e.text = text;
+            e.line = line;
+            e.isError = true;
+            m_errors.Add(e);
+            m_errorCounter++;
+        }
+
+        static public void SubmitWarning(string text, int line)
+        {
+            QspError w;
+            w.locationName = currentLocation;
+            w.text = text;
+            w.line = line;
+            w.isError = false;
+            m_errors.Add(w);
+            m_warningCounter++;
+        }
+
+        static public List<QspError> GetErrors()
+        {
+            return m_errors;
+        }
+
+        static public bool StartOfMultiWordOperator(string op)
+        {
+            return op.ToUpper().Equals("ADD") || op.ToUpper().Equals("DEL");
+        }
+
+        static public void qspAddStatement(int statCode, int extArg, /*QSP_STATEMENT func,*/ int minArgs, int maxArgs, params int[] marker)
+        {
+            int i;
+            qspStats[statCode].ExtArg = extArg;
+            //qspStats[statCode].Func = func;
+            qspStats[statCode].MinArgsCount = minArgs;
+            qspStats[statCode].MaxArgsCount = maxArgs;
+            qspStats[statCode].ArgsTypes = new int[QSP_STATMAXARGS];
+            if (maxArgs > 0)
+            {
+                for (i = 0; i < maxArgs; ++i)
+                    qspStats[statCode].ArgsTypes[i] = marker[i];
+            }
+        }
+
+        static public void qspAddStatName(int statCode, string statName, int level)
+        {
+            int len = statName.Length;
+            int count = qspStatsNamesCounts[level];
+            qspStatsNames[level, count].Name = statName;
+            qspStatsNames[level, count].NameLen = len;
+            qspStatsNames[level, count].Code = statCode;
+            qspStatsNamesCounts[level] = count + 1;
+            /* Max length */
+            if (len > qspStatMaxLen) qspStatMaxLen = len;
+        }
+
+        static public void qspAddOperation(int opCode, int priority, /*QSP_FUNCTION func,*/ int resType, int minArgs, int maxArgs, params int[] marker)
+        {
+	        int i;
+	        qspOps[opCode].Priority = priority;
+	        //qspOps[opCode].Func = func;
+	        qspOps[opCode].ResType = resType;
+	        qspOps[opCode].MinArgsCount = minArgs;
+	        qspOps[opCode].MaxArgsCount = maxArgs;
+            qspOps[opCode].ArgsTypes = new int[QSP_OPMAXARGS];
+            if (maxArgs > 0)
+	        {
+		        for (i = 0; i < maxArgs; ++i)
+			        qspOps[opCode].ArgsTypes[i] = marker[i];
+	        }
+        }
+
+        static public void qspAddOpName(int opCode, string opName, int level)
+        {
+            int len = opName.Length;
+	        int count = qspOpsNamesCounts[level];
+	        qspOpsNames[level, count].Name = opName;
+	        qspOpsNames[level, count].NameLen = len;
+	        qspOpsNames[level, count].Code = opCode;
+	        qspOpsNamesCounts[level] = count + 1;
+	        /* Max length */
+	        if (len > qspOpMaxLen) qspOpMaxLen = len;
+        }
+
+
+        static public void InitQsp()
+        {
+            qspStatMaxLen = 0;
+            // код оператора, ExtArg, минимальное кол-во аргументов, максимальное кол-во аргументов, типы аргументов
+            //                                                                                       0 - авто
+            //                                                                                       1 - строка
+            //                                                                                       2 - числовой
+            qspAddStatement((int)QspStatementType.Else, 0, 0, 0);
+            qspAddStatement((int)QspStatementType.ElseIf, 0, 1, 1, 2);
+            qspAddStatement((int)QspStatementType.End, 0, 0, 0);
+            qspAddStatement((int)QspStatementType.Local, 0, 0, 0);
+            qspAddStatement((int)QspStatementType.Set, 0, 0, 0);
+            qspAddStatement((int)QspStatementType.If, 0, 1, 1, 2);
+            qspAddStatement((int)QspStatementType.Act, 0, 1, 2, 1, 1);
+            qspAddStatement((int)QspStatementType.For, 0, 0, 0);
+            qspAddStatement((int)QspStatementType.AddObj, 0, 1, 3, 1, 1, 2);
+            qspAddStatement((int)QspStatementType.ClA, 3, 0, 0);
+            qspAddStatement((int)QspStatementType.CloseAll, 1, 0, 0);
+            qspAddStatement((int)QspStatementType.Close, 0, 0, 1, 1);
+            qspAddStatement((int)QspStatementType.ClS, 4, 0, 0);
+            qspAddStatement((int)QspStatementType.CmdClear, 2, 0, 0);
+            qspAddStatement((int)QspStatementType.CopyArr, 0, 2, 4, 1, 1, 2, 2);
+            qspAddStatement((int)QspStatementType.DelAct, 0, 1, 1, 1);
+            qspAddStatement((int)QspStatementType.DelObj, 0, 1, 1, 1);
+            qspAddStatement((int)QspStatementType.Dynamic, 0, 1, 10, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+            qspAddStatement((int)QspStatementType.Exec, 0, 1, 1, 1);
+            qspAddStatement((int)QspStatementType.Exit, 0, 0, 0);
+            qspAddStatement((int)QspStatementType.FreeLib, 6, 0, 0);
+            qspAddStatement((int)QspStatementType.GoSub, 0, 1, 10, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+            qspAddStatement((int)QspStatementType.GoTo, 1, 1, 10, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+            qspAddStatement((int)QspStatementType.IncLib, 1, 1, 1, 1);
+            qspAddStatement((int)QspStatementType.Jump, 0, 1, 1, 1);
+            qspAddStatement((int)QspStatementType.KillAll, 5, 0, 0);
+            qspAddStatement((int)QspStatementType.KillObj, 1, 0, 1, 2);
+            qspAddStatement((int)QspStatementType.KillVar, 0, 0, 2, 1, 2);
+            qspAddStatement((int)QspStatementType.Menu, 0, 1, 3, 1, 2, 2);
+            qspAddStatement((int)QspStatementType.MClear, 1, 0, 0);
+            qspAddStatement((int)QspStatementType.MNL, 5, 0, 1, 1);
+            qspAddStatement((int)QspStatementType.MPL, 3, 0, 1, 1);
+            qspAddStatement((int)QspStatementType.MP, 1, 1, 1, 1);
+            qspAddStatement((int)QspStatementType.Clear, 0, 0, 0);
+            qspAddStatement((int)QspStatementType.NL, 4, 0, 1, 1);
+            qspAddStatement((int)QspStatementType.PL, 2, 0, 1, 1);
+            qspAddStatement((int)QspStatementType.P, 0, 1, 1, 1);
+            qspAddStatement((int)QspStatementType.Msg, 0, 1, 1, 1);
+            qspAddStatement((int)QspStatementType.OpenGame, 0, 0, 1, 1);
+            qspAddStatement((int)QspStatementType.OpenQst, 0, 1, 1, 1);
+            qspAddStatement((int)QspStatementType.Play, 0, 1, 2, 1, 2);
+            qspAddStatement((int)QspStatementType.RefInt, 0, 0, 0);
+            qspAddStatement((int)QspStatementType.SaveGame, 0, 0, 1, 1);
+            qspAddStatement((int)QspStatementType.SetTimer, 0, 1, 1, 2);
+            qspAddStatement((int)QspStatementType.ShowActs, 0, 1, 1, 2);
+            qspAddStatement((int)QspStatementType.ShowInput, 3, 1, 1, 2);
+            qspAddStatement((int)QspStatementType.ShowObjs, 1, 1, 1, 2);
+            qspAddStatement((int)QspStatementType.ShowVars, 2, 1, 1, 2);
+            qspAddStatement((int)QspStatementType.UnSelect, 0, 0, 0);
+            qspAddStatement((int)QspStatementType.View, 0, 0, 1, 1);
+            qspAddStatement((int)QspStatementType.Wait, 0, 1, 1, 2);
+            qspAddStatement((int)QspStatementType.XGoTo, 0, 1, 10, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+            /* Names */
+            qspAddStatName((int)QspStatementType.Else, "ELSE", 2);
+            qspAddStatName((int)QspStatementType.ElseIf, "ELSEIF", 1);
+            qspAddStatName((int)QspStatementType.End, "END", 2);
+            qspAddStatName((int)QspStatementType.Local, "LOCAL", 2);
+            qspAddStatName((int)QspStatementType.Set, "SET", 2);
+            qspAddStatName((int)QspStatementType.Set, "LET", 2);
+            qspAddStatName((int)QspStatementType.If, "IF", 2);
+            qspAddStatName((int)QspStatementType.Act, "ACT", 2);
+            qspAddStatName((int)QspStatementType.For, "FOR", 2);
+            qspAddStatName((int)QspStatementType.AddObj, "ADDOBJ", 2);
+            qspAddStatName((int)QspStatementType.AddObj, "ADD OBJ", 2);
+            qspAddStatName((int)QspStatementType.ClA, "CLA", 2);
+            qspAddStatName((int)QspStatementType.CloseAll, "CLOSE ALL", 1);
+            qspAddStatName((int)QspStatementType.Close, "CLOSE", 2);
+            qspAddStatName((int)QspStatementType.ClS, "CLS", 2);
+            qspAddStatName((int)QspStatementType.CmdClear, "CMDCLEAR", 2);
+            qspAddStatName((int)QspStatementType.CmdClear, "CMDCLR", 2);
+            qspAddStatName((int)QspStatementType.CopyArr, "COPYARR", 2);
+            qspAddStatName((int)QspStatementType.DelAct, "DELACT", 2);
+            qspAddStatName((int)QspStatementType.DelAct, "DEL ACT", 2);
+            qspAddStatName((int)QspStatementType.DelObj, "DELOBJ", 2);
+            qspAddStatName((int)QspStatementType.DelObj, "DEL OBJ", 2);
+            qspAddStatName((int)QspStatementType.Dynamic, "DYNAMIC", 2);
+            qspAddStatName((int)QspStatementType.Exec, "EXEC", 2);
+            qspAddStatName((int)QspStatementType.Exit, "EXIT", 2);
+            qspAddStatName((int)QspStatementType.FreeLib, "FREELIB", 2);
+            qspAddStatName((int)QspStatementType.GoSub, "GOSUB", 2);
+            qspAddStatName((int)QspStatementType.GoSub, "GS", 2);
+            qspAddStatName((int)QspStatementType.GoTo, "GOTO", 2);
+            qspAddStatName((int)QspStatementType.GoTo, "GT", 2);
+            qspAddStatName((int)QspStatementType.IncLib, "INCLIB", 2);
+            qspAddStatName((int)QspStatementType.Jump, "JUMP", 2);
+            qspAddStatName((int)QspStatementType.KillAll, "KILLALL", 2);
+            qspAddStatName((int)QspStatementType.KillObj, "KILLOBJ", 2);
+            qspAddStatName((int)QspStatementType.KillVar, "KILLVAR", 2);
+            qspAddStatName((int)QspStatementType.Menu, "MENU", 2);
+            qspAddStatName((int)QspStatementType.MClear, "*CLEAR", 2);
+            qspAddStatName((int)QspStatementType.MClear, "*CLR", 2);
+            qspAddStatName((int)QspStatementType.MNL, "*NL", 2);
+            qspAddStatName((int)QspStatementType.MPL, "*PL", 1);
+            qspAddStatName((int)QspStatementType.MP, "*P", 2);
+            qspAddStatName((int)QspStatementType.Clear, "CLEAR", 2);
+            qspAddStatName((int)QspStatementType.Clear, "CLR", 2);
+            qspAddStatName((int)QspStatementType.NL, "NL", 2);
+            qspAddStatName((int)QspStatementType.PL, "PL", 1);
+            qspAddStatName((int)QspStatementType.P, "P", 2);
+            qspAddStatName((int)QspStatementType.Msg, "MSG", 2);
+            qspAddStatName((int)QspStatementType.OpenGame, "OPENGAME", 2);
+            qspAddStatName((int)QspStatementType.OpenQst, "OPENQST", 2);
+            qspAddStatName((int)QspStatementType.Play, "PLAY", 0);
+            qspAddStatName((int)QspStatementType.RefInt, "REFINT", 2);
+            qspAddStatName((int)QspStatementType.SaveGame, "SAVEGAME", 2);
+            qspAddStatName((int)QspStatementType.SetTimer, "SETTIMER", 1);
+            qspAddStatName((int)QspStatementType.ShowActs, "SHOWACTS", 2);
+            qspAddStatName((int)QspStatementType.ShowInput, "SHOWINPUT", 2);
+            qspAddStatName((int)QspStatementType.ShowObjs, "SHOWOBJS", 2);
+            qspAddStatName((int)QspStatementType.ShowVars, "SHOWSTAT", 2);
+            qspAddStatName((int)QspStatementType.UnSelect, "UNSELECT", 1);
+            qspAddStatName((int)QspStatementType.UnSelect, "UNSEL", 2);
+            qspAddStatName((int)QspStatementType.View, "VIEW", 2);
+            qspAddStatName((int)QspStatementType.Wait, "WAIT", 2);
+            qspAddStatName((int)QspStatementType.XGoTo, "XGOTO", 2);
+            qspAddStatName((int)QspStatementType.XGoTo, "XGT", 2);
+
+            //Математические операторы и функции
+	        int i;
+	        for (i = 0; i < QSP_OPSLEVELS; ++i) qspOpsNamesCounts[i] = 0;
+	        qspOpMaxLen = 0;
+            // код оператора, приоритет, тип результата, минимальное кол-во аргументов, максимальное кол-во аргументов, типы аргументов
+            //                                                                                       0 - авто
+            //                                                                                       1 - строка
+            //                                                                                       2 - числовой
+	        qspAddOperation((int)QspFunctionType.Value, 0, 0, 0, 0);
+	        qspAddOperation((int)QspFunctionType.Start, 127, 0, 0, 0);
+	        qspAddOperation((int)QspFunctionType.End, 0, 0, 0, 0);
+	        qspAddOperation((int)QspFunctionType.OpenBracket, 127, 0, 0, 0);
+	        qspAddOperation((int)QspFunctionType.CloseBracket, 0, 0, 0, 0);
+	        qspAddOperation((int)QspFunctionType.Minus, 18, 2, 1, 1, 2);
+	        qspAddOperation((int)QspFunctionType.Add, 14, 0, 2, 2, 0, 0);
+	        qspAddOperation((int)QspFunctionType.Sub, 14, 2, 2, 2, 2, 2);
+	        qspAddOperation((int)QspFunctionType.Mul, 17, 2, 2, 2, 2, 2);
+	        qspAddOperation((int)QspFunctionType.Div, 17, 2, 2, 2, 2, 2);
+	        qspAddOperation((int)QspFunctionType.Mod, 16, 2, 2, 2, 2, 2);
+	        qspAddOperation((int)QspFunctionType.Ne, 10, 2, 2, 2, 0, 0);
+	        qspAddOperation((int)QspFunctionType.Leq, 10, 2, 2, 2, 0, 0);
+	        qspAddOperation((int)QspFunctionType.Geq, 10, 2, 2, 2, 0, 0);
+	        qspAddOperation((int)QspFunctionType.Eq, 10, 2, 2, 2, 0, 0);
+	        qspAddOperation((int)QspFunctionType.Lt, 10, 2, 2, 2, 0, 0);
+	        qspAddOperation((int)QspFunctionType.Gt, 10, 2, 2, 2, 0, 0);
+	        qspAddOperation((int)QspFunctionType.Append, 12, 1, 2, 2, 1, 1);
+	        qspAddOperation((int)QspFunctionType.Comma, 0, 1, 2, 2, 1, 1);
+	        qspAddOperation((int)QspFunctionType.And, 7, 2, 2, 2, 2, 2);
+	        qspAddOperation((int)QspFunctionType.Or, 6, 2, 2, 2, 2, 2);
+	        qspAddOperation((int)QspFunctionType.Loc, 8, 2, 1, 1, 1);
+	        qspAddOperation((int)QspFunctionType.Obj, 8, 2, 1, 1, 1);
+	        qspAddOperation((int)QspFunctionType.Not, 8, 2, 1, 1, 2);
+	        qspAddOperation((int)QspFunctionType.Min, 30, 0, 1, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	        qspAddOperation((int)QspFunctionType.Max, 30, 0, 1, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	        qspAddOperation((int)QspFunctionType.Rand, 30, 2, 1, 2, 2, 2);
+	        qspAddOperation((int)QspFunctionType.IIf, 30, 0, 3, 3, 2, 0, 0);
+	        qspAddOperation((int)QspFunctionType.RGB, 30, 2, 3, 4, 2, 2, 2, 2);
+	        qspAddOperation((int)QspFunctionType.Len, 30, 2, 1, 1, 1);
+	        qspAddOperation((int)QspFunctionType.IsNum, 30, 2, 1, 1, 0);
+	        qspAddOperation((int)QspFunctionType.LCase, 30, 1, 1, 1, 1);
+	        qspAddOperation((int)QspFunctionType.UCase, 30, 1, 1, 1, 1);
+	        qspAddOperation((int)QspFunctionType.Input, 30, 1, 1, 1, 1);
+	        qspAddOperation((int)QspFunctionType.Str, 30, 1, 1, 1, 1);
+	        qspAddOperation((int)QspFunctionType.Val, 30, 2, 1, 1, 0);
+	        qspAddOperation((int)QspFunctionType.ArrSize, 30, 2, 1, 1, 1);
+	        qspAddOperation((int)QspFunctionType.IsPlay, 30, 2, 1, 1, 1);
+	        qspAddOperation((int)QspFunctionType.Desc, 30, 1, 1, 1, 1);
+	        qspAddOperation((int)QspFunctionType.Trim, 30, 1, 1, 1, 1);
+	        qspAddOperation((int)QspFunctionType.GetObj, 30, 1, 1, 1, 2);
+	        qspAddOperation((int)QspFunctionType.StrComp, 30, 2, 2, 2, 1, 1);
+	        qspAddOperation((int)QspFunctionType.StrFind, 30, 1, 2, 3, 1, 1, 2);
+	        qspAddOperation((int)QspFunctionType.StrPos, 30, 2, 2, 3, 1, 1, 2);
+	        qspAddOperation((int)QspFunctionType.Mid, 30, 1, 2, 3, 1, 2, 2);
+	        qspAddOperation((int)QspFunctionType.ArrPos, 30, 2, 2, 3, 1, 0, 2);
+	        qspAddOperation((int)QspFunctionType.ArrComp, 30, 2, 2, 3, 1, 0, 2);
+	        qspAddOperation((int)QspFunctionType.Instr, 30, 2, 2, 3, 1, 1, 2);
+	        qspAddOperation((int)QspFunctionType.Replace, 30, 1, 2, 3, 1, 1, 1);
+	        qspAddOperation((int)QspFunctionType.Func, 30, 0, 1, 10, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	        qspAddOperation((int)QspFunctionType.DynEval, 30, 0, 1, 10, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	        qspAddOperation((int)QspFunctionType.Rnd, 30, 2, 0, 0);
+	        qspAddOperation((int)QspFunctionType.CountObj, 30, 2, 0, 0);
+	        qspAddOperation((int)QspFunctionType.MsecsCount, 30, 2, 0, 0);
+	        qspAddOperation((int)QspFunctionType.QSPVer, 30, 1, 0, 0);
+	        qspAddOperation((int)QspFunctionType.UserText, 30, 1, 0, 0);
+	        qspAddOperation((int)QspFunctionType.CurLoc, 30, 1, 0, 0);
+	        qspAddOperation((int)QspFunctionType.SelObj, 30, 1, 0, 0);
+	        qspAddOperation((int)QspFunctionType.SelAct, 30, 1, 0, 0);
+	        qspAddOperation((int)QspFunctionType.MainText, 30, 1, 0, 0);
+	        qspAddOperation((int)QspFunctionType.StatText, 30, 1, 0, 0);
+	        qspAddOperation((int)QspFunctionType.CurActs, 30, 1, 0, 0);
+	        /* Names */
+	        qspAddOpName((int)QspFunctionType.CloseBracket, ")", 1);
+	        qspAddOpName((int)QspFunctionType.Add, "+", 1);
+	        qspAddOpName((int)QspFunctionType.Sub, "-", 1);
+	        qspAddOpName((int)QspFunctionType.Mul, "*", 1);
+	        qspAddOpName((int)QspFunctionType.Div, "/", 1);
+	        qspAddOpName((int)QspFunctionType.Mod, "MOD", 1);
+	        qspAddOpName((int)QspFunctionType.Ne, "!", 1);
+	        qspAddOpName((int)QspFunctionType.Ne, "<>", 0);
+	        qspAddOpName((int)QspFunctionType.Leq, "<=", 0);
+	        qspAddOpName((int)QspFunctionType.Leq, "=<", 0);
+	        qspAddOpName((int)QspFunctionType.Geq, ">=", 0);
+	        qspAddOpName((int)QspFunctionType.Geq, "=>", 0);
+	        qspAddOpName((int)QspFunctionType.Eq, "=", 1);
+	        qspAddOpName((int)QspFunctionType.Lt, "<", 1);
+	        qspAddOpName((int)QspFunctionType.Gt, ">", 1);
+	        qspAddOpName((int)QspFunctionType.Append, "&", 1);
+	        qspAddOpName((int)QspFunctionType.Comma, ",", 1);
+	        qspAddOpName((int)QspFunctionType.And, "AND", 1);
+	        qspAddOpName((int)QspFunctionType.Or, "OR", 1);
+	        qspAddOpName((int)QspFunctionType.Loc, "LOC", 1);
+	        qspAddOpName((int)QspFunctionType.Obj, "OBJ", 1);
+	        qspAddOpName((int)QspFunctionType.Not, "NO", 1);
+	        qspAddOpName((int)QspFunctionType.Min, "MIN", 1);
+	        qspAddOpName((int)QspFunctionType.Min, "$MIN", 1);
+	        qspAddOpName((int)QspFunctionType.Max, "MAX", 1);
+	        qspAddOpName((int)QspFunctionType.Max, "$MAX", 1);
+	        qspAddOpName((int)QspFunctionType.Rand, "RAND", 1);
+	        qspAddOpName((int)QspFunctionType.IIf, "IIF", 1);
+	        qspAddOpName((int)QspFunctionType.IIf, "$IIF", 1);
+	        qspAddOpName((int)QspFunctionType.RGB, "RGB", 1);
+	        qspAddOpName((int)QspFunctionType.Len, "LEN", 1);
+	        qspAddOpName((int)QspFunctionType.IsNum, "ISNUM", 1);
+	        qspAddOpName((int)QspFunctionType.LCase, "LCASE", 1);
+	        qspAddOpName((int)QspFunctionType.LCase, "$LCASE", 1);
+	        qspAddOpName((int)QspFunctionType.UCase, "UCASE", 1);
+	        qspAddOpName((int)QspFunctionType.UCase, "$UCASE", 1);
+	        qspAddOpName((int)QspFunctionType.Input, "INPUT", 1);
+	        qspAddOpName((int)QspFunctionType.Input, "$INPUT", 1);
+	        qspAddOpName((int)QspFunctionType.Str, "STR", 1);
+	        qspAddOpName((int)QspFunctionType.Str, "$STR", 1);
+	        qspAddOpName((int)QspFunctionType.Val, "VAL", 1);
+	        qspAddOpName((int)QspFunctionType.ArrSize, "ARRSIZE", 1);
+	        qspAddOpName((int)QspFunctionType.IsPlay, "ISPLAY", 1);
+	        qspAddOpName((int)QspFunctionType.Desc, "DESC", 1);
+	        qspAddOpName((int)QspFunctionType.Desc, "$DESC", 1);
+	        qspAddOpName((int)QspFunctionType.Trim, "TRIM", 1);
+	        qspAddOpName((int)QspFunctionType.Trim, "$TRIM", 1);
+	        qspAddOpName((int)QspFunctionType.GetObj, "GETOBJ", 1);
+	        qspAddOpName((int)QspFunctionType.GetObj, "$GETOBJ", 1);
+	        qspAddOpName((int)QspFunctionType.StrComp, "STRCOMP", 1);
+	        qspAddOpName((int)QspFunctionType.StrFind, "STRFIND", 1);
+	        qspAddOpName((int)QspFunctionType.StrFind, "$STRFIND", 1);
+	        qspAddOpName((int)QspFunctionType.StrPos, "STRPOS", 1);
+	        qspAddOpName((int)QspFunctionType.Mid, "MID", 1);
+	        qspAddOpName((int)QspFunctionType.Mid, "$MID", 1);
+	        qspAddOpName((int)QspFunctionType.ArrPos, "ARRPOS", 1);
+	        qspAddOpName((int)QspFunctionType.ArrComp, "ARRCOMP", 1);
+	        qspAddOpName((int)QspFunctionType.Instr, "INSTR", 1);
+	        qspAddOpName((int)QspFunctionType.Replace, "REPLACE", 1);
+	        qspAddOpName((int)QspFunctionType.Replace, "$REPLACE", 1);
+	        qspAddOpName((int)QspFunctionType.Func, "FUNC", 1);
+	        qspAddOpName((int)QspFunctionType.Func, "$FUNC", 1);
+	        qspAddOpName((int)QspFunctionType.DynEval, "DYNEVAL", 1);
+	        qspAddOpName((int)QspFunctionType.DynEval, "$DYNEVAL", 1);
+	        qspAddOpName((int)QspFunctionType.Rnd, "RND", 1);
+	        qspAddOpName((int)QspFunctionType.CountObj, "COUNTOBJ", 1);
+	        qspAddOpName((int)QspFunctionType.MsecsCount, "MSECSCOUNT", 1);
+	        qspAddOpName((int)QspFunctionType.QSPVer, "QSPVER", 1);
+	        qspAddOpName((int)QspFunctionType.QSPVer, "$QSPVER", 1);
+	        qspAddOpName((int)QspFunctionType.UserText, "USER_TEXT", 1);
+	        qspAddOpName((int)QspFunctionType.UserText, "$USER_TEXT", 1);
+	        qspAddOpName((int)QspFunctionType.UserText, "USRTXT", 1);
+	        qspAddOpName((int)QspFunctionType.UserText, "$USRTXT", 1);
+	        qspAddOpName((int)QspFunctionType.CurLoc, "CURLOC", 1);
+	        qspAddOpName((int)QspFunctionType.CurLoc, "$CURLOC", 1);
+	        qspAddOpName((int)QspFunctionType.SelObj, "SELOBJ", 1);
+	        qspAddOpName((int)QspFunctionType.SelObj, "$SELOBJ", 1);
+	        qspAddOpName((int)QspFunctionType.SelAct, "SELACT", 1);
+	        qspAddOpName((int)QspFunctionType.SelAct, "$SELACT", 1);
+	        qspAddOpName((int)QspFunctionType.MainText, "MAINTXT", 1);
+	        qspAddOpName((int)QspFunctionType.MainText, "$MAINTXT", 1);
+	        qspAddOpName((int)QspFunctionType.StatText, "STATTXT", 1);
+	        qspAddOpName((int)QspFunctionType.StatText, "$STATTXT", 1);
+	        qspAddOpName((int)QspFunctionType.CurActs, "CURACTS", 1);
+	        qspAddOpName((int)QspFunctionType.CurActs, "$CURACTS", 1);
+        }
+
+        static public int qspGetStatCode(string s)
+        {
+            if (s.Length == 0)
+                return (int)QspStatementType.Unknown;
+            if (s[0] == ':')
+                return (int)QspStatementType.Label;
+            if (s[0] == '!')
+                return (int)QspStatementType.Comment;
+            int len;
+            if (s.Length < qspStatMaxLen)
+                len = s.Length;
+            else
+                len = qspStatMaxLen;
+            string name = s.Substring(0, len).ToUpper().Trim(WhiteSpace);
+	        for (int i = 0; i < QSP_STATSLEVELS; ++i)
+	        {
+                for (int j = 0; j < qspStatsNamesCounts[i]; j++)
+                {
+                    if (name.Equals(qspStatsNames[i,j].Name))
+                        return qspStatsNames[i,j].Code;
+                }
+	        }
+            return (int)QspStatementType.Unknown;
+        }
+
+        static public int qspGetFunctionCode(string s, bool functionsOnly)
+        {
+            if (s.Length == 0)
+                return (int)QspFunctionType.End;
+            int len;
+            if (s.Length < qspOpMaxLen)
+                len = s.Length;
+            else
+                len = qspOpMaxLen;
+            string name = s.Substring(0, len).ToUpper().Trim(WhiteSpace);
+            for (int i = 0; i < QSP_OPSLEVELS; ++i)
+            {
+                for (int j = 0; j < qspOpsNamesCounts[i]; j++)
+                {
+                    if ((name.Equals(qspOpsNames[i, j].Name)) && 
+                        (!functionsOnly || (qspOpsNames[i, j].Code >= (int)QspFunctionType.First_Function)))
+                        return qspOpsNames[i, j].Code;
+                }
+            }
+            return (int)QspFunctionType.Unknown;
+        }
+        
+        static public QspVariable GetVar(string name)
+        {
+            foreach (QspVariable var in vars)
+            {
+                if (var.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
+                    return var;
+            }
+            return null;
+        }
+
+        static public void AddVar(string name, bool assigned, bool used)
+        {
+            QspVariable var = GetVar(name);
+            if (var == null)
+            {
+                var = new QspVariable(name, assigned, used);
+                vars.Add(var);
+            }
+            else
+            {
+                if (assigned)
+                    var.Assigned = assigned;
+                if (used)
+                    var.Used = used;
+            }
+        }
+
+        static public QspLocationLink GetLocationLink(string name)
+        {
+            foreach (QspLocationLink loc in locationLinks)
+            {
+                if (loc.LocationName.Equals(name, StringComparison.OrdinalIgnoreCase))
+                    return loc;
+            }
+            return null;
+        }
+
+        static public void AddLocationLink(string name, bool exists, bool called)
+        {
+            QspLocationLink loc = GetLocationLink(name);
+            if (loc == null)
+            {
+                loc = new QspLocationLink(name, exists, called);
+                locationLinks.Add(loc);
+            }
+            else
+            {
+                if (exists)
+                    loc.LocationExists = exists;
+                if (called)
+                    loc.LocationCalled = called;
+            }
+        }
+
+        static public QspObj GetObj(string name)
+        {
+            foreach (QspObj obj in objects)
+            {
+                if (obj.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
+                    return obj;
+            }
+            return null;
+        }
+
+        static public void AddObj(string name, bool added, bool removed)
+        {
+            QspObj obj = GetObj(name);
+            if (obj == null)
+            {
+                obj = new QspObj(name, added, removed);
+                objects.Add(obj);
+            }
+            else
+            {
+                if (added)
+                    obj.Added = added;
+                if (removed)
+                    obj.Removed = removed;
+            }
+        }
+
+        static public QspAct GetAct(string name)
+        {
+            foreach (QspAct act in acts)
+            {
+                if (act.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
+                    return act;
+            }
+            return null;
+        }
+
+        static public void AddAct(string name, bool added, bool removed)
+        {
+            QspAct act = GetAct(name);
+            if (act == null)
+            {
+                act = new QspAct(name, added, removed);
+                acts.Add(act);
+            }
+            else
+            {
+                if (added)
+                    act.Added = added;
+                if (removed)
+                    act.Removed = removed;
+            }
+        }
+
+        static public void SetConfig(List<string> callerVars, List<string> systemVars, bool EnableCurlyParsing)
+        {
+            callerVariables = callerVars;
+            systemVariables = systemVars;
+            curlyParsing = EnableCurlyParsing;
+        }
+
+        static public bool IsNumber(String s)
+        {
+            foreach (char c in s.ToCharArray())
+            {
+                if (Array.IndexOf(Digits, c) == INVALID_INDEX)
+                    return false;
+            }
+            return true;
+        }
+
+        static public bool ListContainsIgnoreCase(List<string> stringList, string value)
+        {
+            bool contains = null != stringList.Find(delegate(string str)
+            {
+                return str.Equals(value, StringComparison.OrdinalIgnoreCase);
+            });
+            return contains;
+        }
+
+        static public string GenerateCsvName(string FileName)
+        {
+            string result = FileName;
+            if (result.EndsWith(".txt"))
+                result = result.Substring(0, result.Length - 4);
+            result = result + ".csv";
+            return result;
+        }
+
+        static public bool ExportToCsv(string srcFile, string delimiter)
+        {
+            //Выгружаем исходный код в CSV
+            //4 колонки: номер+локация, оригинал, место для перевода, место для комментария
+
+            string dstFile = GenerateCsvName(srcFile);
+
+            StreamReader fi = null;
+            if (!OpenStreamForReading(ref fi, srcFile))
+            {
+                return false;
+            }
+            StreamWriter fo = null;
+            if (!OpenStreamForWriting(ref fo, dstFile))
+            {
+                fi.Close();
+                return false;
+            }
+            string line;
+            int line_counter = 0;
+            int quoted_line_counter = 0;
+            bool inside = false;
+            string locName = null;
+
+            int quote = (int)QuoteType.None;
+            string quotedText = "";
+            bool quotedTextCompleted = false;
+
+            while ((line = fi.ReadLine()) != null)
+            {
+                line_counter++;
+                line = line.Trim(WhiteSpace);
+                if ((line.Length > 0) && (line[0] == '#'))
+                {
+                    //имя локации
+                    locName = line.Substring(1).Trim(WhiteSpace);
+                    inside = true;
+                }
+                else if ((line.Length > 38) && line.StartsWith("--- ") && line.EndsWith(" ---------------------------------"))
+                {
+                    inside = false;
+                    locName = null;
+                }
+                else if (inside)
+                {
+                    //Разбираем только строки внутри локаций
+                    int pos = 0;
+
+                    //Разбор строки
+                    while (pos < line.Length)
+                    {
+                        char c = line[pos];
+                        if (c == '\'')
+                        {
+                            //Апостроф
+                            if (quote == (int)QuoteType.None)
+                            {
+                                quote = (int)QuoteType.Single;
+                                quotedText = "";
+                            }
+                            else if (quote == (int)QuoteType.Single)
+                            {
+                                if ((pos + 1 < line.Length) && (line[pos + 1] == '\''))
+                                {
+                                    //Экранированный апостроф
+                                    pos++;
+                                    quotedText += c;
+                                }
+                                else
+                                {
+                                    quote = (int)QuoteType.None;
+                                    quotedTextCompleted = true;
+                                }
+                            }
+                            else
+                            {
+                                quotedText += c;
+                            }
+                        }
+                        else if (c == '"')
+                        {
+                            //Кавычка
+                            if (quote == (int)QuoteType.None)
+                            {
+                                quote = (int)QuoteType.Double;
+                                quotedText = "";
+                            }
+                            else if (quote == (int)QuoteType.Double)
+                            {
+                                if ((pos + 1 < line.Length) && (line[pos + 1] == '"'))
+                                {
+                                    //Экранированная кавычка
+                                    pos++;
+                                    quotedText += c;
+                                }
+                                else
+                                {
+                                    quote = (int)QuoteType.None;
+                                    quotedTextCompleted = true;
+                                }
+                            }
+                            else
+                            {
+                                quotedText += c;
+                            }
+                        }
+                        else if (quote != (int)QuoteType.None)
+                        {
+                            //Строка текста внутри кавычек или апострофов
+                            quotedText += c;
+                        }
+                        else if (c == '{')
+                        {
+                            //Пропускаем содержимое фигурных скобок
+                            int curlyLevel = 1;
+                            pos++;
+                            int curlyQuote = (int)QuoteType.None;
+                            while (pos < line.Length)
+                            {
+                                char c2 = line[pos];
+
+                                if (c2 == '\'')
+                                {
+                                    //Апостроф
+                                    if (curlyQuote == (int)QuoteType.None)
+                                    {
+                                        curlyQuote = (int)QuoteType.Single;
+                                    }
+                                    else if (curlyQuote == (int)QuoteType.Single)
+                                    {
+                                        if ((pos + 1 < line.Length) && (line[pos + 1] == '\''))
+                                        {
+                                            //Экранированный апостроф
+                                            pos++;
+                                        }
+                                        else
+                                        {
+                                            curlyQuote = (int)QuoteType.None;
+                                        }
+                                    }
+                                }
+                                else if (c2 == '"')
+                                {
+                                    //Кавычка
+                                    if (curlyQuote == (int)QuoteType.None)
+                                    {
+                                        curlyQuote = (int)QuoteType.Double;
+                                    }
+                                    else if (curlyQuote == (int)QuoteType.Double)
+                                    {
+                                        if ((pos + 1 < line.Length) && (line[pos + 1] == '"'))
+                                        {
+                                            //Экранированная кавычка
+                                            pos++;
+                                        }
+                                        else
+                                        {
+                                            curlyQuote = (int)QuoteType.None;
+                                        }
+                                    }
+                                }
+                                else if (curlyQuote == (int)QuoteType.None)
+                                {
+                                    if (c2 == '{')
+                                    {
+                                        curlyLevel++;
+                                    }
+                                    else if (c2 == '}')
+                                    {
+                                        curlyLevel--;
+                                        if (curlyLevel == 0)
+                                            break;
+                                    }
+                                }
+                                pos++;
+                            }
+                        }
+
+                        if (quotedTextCompleted)
+                        {
+                            //Формируем строку для csv-файла
+                            //4 колонки: номер+локация, оригинал, место для перевода, место для комментария
+                            if (quotedText.Trim(WhiteSpace).Length > 0)
+                            {
+                                quoted_line_counter++;
+
+                                string csv_line = "";
+                                csv_line += CsvEscape(quoted_line_counter.ToString() + ":" + locName) + delimiter;
+                                csv_line += CsvEscape(quotedText) + delimiter;
+                                csv_line += CsvEscape("") + delimiter;
+                                csv_line += CsvEscape("");
+
+                                //Записываем строку в csv-файл
+                                fo.WriteLine(csv_line);
+                            }
+                            quotedTextCompleted = false;
+                        }
+                        pos++;
+                    }
+                }
+            }
+            fi.Close();
+            fo.Close();
+            return true;
+        }
+
+        static public string CsvEscape(string src)
+        {
+            //Форматируем строку для записи в csv-файл
+            string result = "\"" + src.Replace("\"", "\"\"") + "\"";
+            return result;
+        }
+
+        static public string CsvUnEscape(string src)
+        {
+            //Преобразовываем строку из csv-формата в обычный текст
+            string result = src;
+            if (src.StartsWith("\""))
+            {
+                result = result.Substring(1, result.Length - 2);
+                result = result.Replace("\"\"", "\"");
+            }
+            return result;
+        }
+
+        static public bool TranslateFromCsv(string srcFile, string suffix, bool IgnoreEmptyTranslations, string delimiter)
+        {
+            //Создаем перевод на основе загруженного файла и CSV
+            //Проверяем соответствие номера, локации, оригинального текста, в случае несовпадения выдаем ошибку и не сохраняем файл
+            //Для пустых строк заполняем текстом оригинала, либо выдаем ошибку - в зависимости от настроек.
+
+            string dstFile = srcFile;
+            if (dstFile.EndsWith(".txt"))
+                dstFile = dstFile.Substring(0, dstFile.Length - 4);
+            dstFile = dstFile + suffix + ".txt";
+
+            string csvFile = GenerateCsvName(srcFile);
+
+            StreamReader fi_src = null;
+            if (!OpenStreamForReading(ref fi_src, srcFile))
+            {
+                return false;
+            }
+            StreamReader fi_csv = null;
+            if (!OpenStreamForReading(ref fi_csv, csvFile))
+            {
+                fi_src.Close();
+                return false;
+            }
+            StreamWriter fo = null;
+            if (!OpenStreamForWriting(ref fo, dstFile))
+            {
+                fi_src.Close();
+                fi_csv.Close();
+                return false;
+            }
+            string line;
+            string line_cut;
+            int line_counter = 0;
+            int quoted_line_counter = 0;
+            bool inside = false;
+            string locName = null;
+
+            int quote = (int)QuoteType.None;
+            string quotedText = "";
+            bool quotedTextCompleted = false;
+
+            string rawText = "";
+
+            bool aborted = false;
+
+            while ((line = fi_src.ReadLine()) != null)
+            {
+                line_counter++;
+                line_cut = line.Trim(WhiteSpace);
+                if ((line_cut.Length > 0) && (line_cut[0] == '#'))
+                {
+                    //имя локации
+                    locName = line_cut.Substring(1).Trim(WhiteSpace);
+                    inside = true;
+                    fo.WriteLine(line);
+                }
+                else if ((line_cut.Length > 38) && line_cut.StartsWith("--- ") && line_cut.EndsWith(" ---------------------------------"))
+                {
+                    inside = false;
+                    locName = null;
+                    fo.WriteLine(line);
+                }
+                else if (inside)
+                {
+                    //Разбираем только строки внутри локаций
+                    int pos = 0;
+
+                    //Разбор строки
+                    while (pos < line.Length)
+                    {
+                        char c = line[pos];
+                        if (c == '\'')
+                        {
+                            //Апостроф
+                            if (quote == (int)QuoteType.None)
+                            {
+                                quote = (int)QuoteType.Single;
+                                quotedText = "";
+                                rawText += c;
+                            }
+                            else if (quote == (int)QuoteType.Single)
+                            {
+                                if ((pos + 1 < line.Length) && (line[pos + 1] == '\''))
+                                {
+                                    //Экранированный апостроф
+                                    pos++;
+                                    quotedText += c;
+                                }
+                                else
+                                {
+                                    quote = (int)QuoteType.None;
+                                    quotedTextCompleted = true;
+                                }
+                            }
+                            else
+                            {
+                                quotedText += c;
+                            }
+                        }
+                        else if (c == '"')
+                        {
+                            //Кавычка
+                            if (quote == (int)QuoteType.None)
+                            {
+                                quote = (int)QuoteType.Double;
+                                quotedText = "";
+                                rawText += c;
+                            }
+                            else if (quote == (int)QuoteType.Double)
+                            {
+                                if ((pos + 1 < line.Length) && (line[pos + 1] == '"'))
+                                {
+                                    //Экранированная кавычка
+                                    pos++;
+                                    quotedText += c;
+                                }
+                                else
+                                {
+                                    quote = (int)QuoteType.None;
+                                    quotedTextCompleted = true;
+                                }
+                            }
+                            else
+                            {
+                                quotedText += c;
+                            }
+                        }
+                        else if (quote != (int)QuoteType.None)
+                        {
+                            //Строка текста внутри кавычек или апострофов
+                            quotedText += c;
+                        }
+                        else if (c == '{')
+                        {
+                            //Пропускаем содержимое фигурных скобок
+                            int curlyLevel = 1;
+                            rawText += c;
+                            pos++;
+                            int curlyQuote = (int)QuoteType.None;
+                            while (pos < line.Length)
+                            {
+                                char c2 = line[pos];
+                                rawText += c2;
+
+                                if (c2 == '\'')
+                                {
+                                    //Апостроф
+                                    if (curlyQuote == (int)QuoteType.None)
+                                    {
+                                        curlyQuote = (int)QuoteType.Single;
+                                    }
+                                    else if (curlyQuote == (int)QuoteType.Single)
+                                    {
+                                        if ((pos + 1 < line.Length) && (line[pos + 1] == '\''))
+                                        {
+                                            //Экранированный апостроф
+                                            rawText += line[pos + 1];
+                                            pos++;
+                                        }
+                                        else
+                                        {
+                                            curlyQuote = (int)QuoteType.None;
+                                        }
+                                    }
+                                }
+                                else if (c2 == '"')
+                                {
+                                    //Кавычка
+                                    if (curlyQuote == (int)QuoteType.None)
+                                    {
+                                        curlyQuote = (int)QuoteType.Double;
+                                    }
+                                    else if (curlyQuote == (int)QuoteType.Double)
+                                    {
+                                        if ((pos + 1 < line.Length) && (line[pos + 1] == '"'))
+                                        {
+                                            //Экранированная кавычка
+                                            rawText += line[pos + 1];
+                                            pos++;
+                                        }
+                                        else
+                                        {
+                                            curlyQuote = (int)QuoteType.None;
+                                        }
+                                    }
+                                }
+                                else if (curlyQuote == (int)QuoteType.None)
+                                {
+                                    if (c2 == '{')
+                                    {
+                                        curlyLevel++;
+                                    }
+                                    else if (c2 == '}')
+                                    {
+                                        curlyLevel--;
+                                        if (curlyLevel == 0)
+                                            break;
+                                    }
+                                }
+                                pos++;
+                            }
+                        }
+                        else
+                        {
+                            rawText += c;
+                        }
+
+                        if (quotedTextCompleted)
+                        {
+                            //Читаем строку из файла перевода
+                            string translation = quotedText;
+
+                            if (quotedText.Trim(WhiteSpace).Length > 0)
+                            {
+                                translation = "";
+                                quoted_line_counter++;
+
+                                bool csvLineCompleted = false;
+                                string csv_line = null;
+                                int valuesCount = 0;
+                                string thirdValue = "";
+                                int csvQuote = (int)QuoteType.None;
+                                string csvText = "";
+                                bool csvValueCompleted = false;
+
+                                int csvLineIndex = INVALID_INDEX;
+                                string csvLocName = "";
+                                string csvOriginalLine = "";
+
+                                while (!csvLineCompleted && ((csv_line = fi_csv.ReadLine()) != null))
+                                {
+                                    int csvPos = 0;
+
+                                    //Разбор строки
+                                    while (csvPos < csv_line.Length)
+                                    {
+                                        int newValuesCount = valuesCount;
+                                        char c3 = csv_line[csvPos];
+                                        if (c3 == '"')
+                                        {
+                                            csvText += c3;
+                                            //Кавычка
+                                            if (csvQuote == (int)QuoteType.None)
+                                            {
+                                                csvQuote = (int)QuoteType.Double;
+                                            }
+                                            else if (csvQuote == (int)QuoteType.Double)
+                                            {
+                                                if ((csvPos + 1 < csv_line.Length) && (csv_line[csvPos + 1] == '"'))
+                                                {
+                                                    //Экранированная кавычка
+                                                    csvText += csv_line[csvPos + 1];
+                                                    csvPos++;
+                                                }
+                                                else
+                                                {
+                                                    csvQuote = (int)QuoteType.None;
+                                                }
+                                            }
+                                        }
+                                        else if (csvQuote != (int)QuoteType.None)
+                                        {
+                                            //Строка текста внутри кавычек
+                                            csvText += c3;
+                                        }
+                                        else if (c3.ToString() == delimiter)
+                                        {
+                                            newValuesCount++;
+                                            csvValueCompleted = true;
+                                        }
+                                        else
+                                        {
+                                            csvText += c3;
+                                        }
+
+                                        if ((csvQuote == (int)QuoteType.None) && (csvPos == csv_line.Length - 1))
+                                        {
+                                            newValuesCount++;
+                                            csvValueCompleted = true;
+                                        }
+
+                                        if (csvValueCompleted)
+                                        {
+                                            for (int iter = valuesCount + 1; iter <= newValuesCount; iter++)
+                                            {
+                                                csvText = CsvUnEscape(csvText.Trim(WhiteSpace));
+                                                if (iter == 1)   //Первая колонка - имя локации и номер строки
+                                                {
+                                                    string[] csvFirst = csvText.Split(":".ToCharArray());
+                                                    if (csvFirst.Length == 2)
+                                                    {
+                                                        csvLineIndex = Convert.ToInt32(csvFirst[0]);
+                                                        csvLocName = csvFirst[1];
+                                                    }
+                                                }
+                                                else if (iter == 2)   //Вторая колонка - оригинал
+                                                {
+                                                    csvOriginalLine = csvText;
+                                                }
+                                                else if (iter == 3)   //Третья колонка - перевод
+                                                {
+                                                    thirdValue = csvText;
+                                                }
+                                                csvText = "";
+                                            }
+                                            csvValueCompleted = false;
+                                            valuesCount = newValuesCount;
+                                        }
+                                        csvPos++;
+                                    }
+                                    if (csvQuote == (int)QuoteType.None)
+                                    {
+                                        csvLineCompleted = true;
+                                    }
+                                    else
+                                    {
+                                        csvText += Environment.NewLine;
+                                    }
+                                }
+
+                                if ((csv_line == null) || (csvLineCompleted && 
+                                    ((csvLocName != locName) || (quoted_line_counter != csvLineIndex) || (csvOriginalLine != quotedText))))
+                                {
+                                    SubmitError("CSV-file does not match the original! Generate it again.", INVALID_INDEX);
+                                    aborted = true;
+                                    break;
+                                }
+                                if (!csvLineCompleted)
+                                {
+                                    SubmitError("CSV-file damaged! Line number: " + quoted_line_counter.ToString(), INVALID_INDEX);
+                                    aborted = true;
+                                    break;
+                                }
+                                translation = thirdValue;
+
+                                if (translation.Length == 0)
+                                {
+                                    if (IgnoreEmptyTranslations)
+                                    {
+                                        translation = quotedText;
+                                    }
+                                    else
+                                    {
+                                        SubmitError("Line number " + quoted_line_counter + " is not converted!", INVALID_INDEX);
+                                        aborted = true;
+                                        break;
+                                    }
+                                }
+                            }
+                            rawText += translation;
+                            rawText += c;
+                            quotedTextCompleted = false;
+                        }
+                        pos++;
+                    }
+                    if (aborted)
+                        break;
+                    if (quote == (int)QuoteType.None)
+                    {
+                        //Записываем строку в файл перевода
+                        fo.WriteLine(rawText);
+                        rawText = "";
+                    }
+                }
+                else
+                {
+                    fo.WriteLine(line);
+                }
+            }
+            fi_src.Close();
+            fi_csv.Close();
+            fo.Close();
+            if (aborted)
+            {
+                //Убить корявый перевод
+                File.Delete(dstFile);
+            }
+            return !aborted;
+        }
+
+        static public bool OpenStreamForReading(ref StreamReader fi, string file)
+        {
+            bool result = false;
+            try
+            {
+                fi = new StreamReader(file, Encoding.Default);
+                result = true;
+            }
+            catch (Exception e)
+            {
+                SubmitError("File \"" + file + "\" cannot be opened for reading (it can be opened by another program).", INVALID_INDEX);
+                result = false;
+            }
+            return result;
+        }
+
+        static public bool OpenStreamForWriting(ref StreamWriter fo, string file)
+        {
+            bool result = false;
+            try
+            {
+                fo = new StreamWriter(file, false, Encoding.Default);
+                result = true;
+            }
+            catch (Exception e)
+            {
+                SubmitError("File \"" + file + "\" cannot be opened for writing (it can be opened by another program).", INVALID_INDEX);
+                result = false;
+            }
+            return result;
+        }
+    }
+}

+ 667 - 0
QSP/qsp-analyser/QSP_Analyser/List.txt

@@ -0,0 +1,667 @@
+Common.cs
+Line 1430:	SubmitError("CSV-файл не соответствует исходному! Сгенерируйте его заново.", INVALID_INDEX);
+			SubmitError("CSV-file does not match the original! Generate it again.", INVALID_INDEX);
+
+			
+Line 1436:	SubmitError("CSV-файл поврежден! Номер строки: " + quoted_line_counter.ToString(), INVALID_INDEX);
+			SubmitError("CSV-file damaged! Line number: " + quoted_line_counter.ToString(), INVALID_INDEX);
+
+			
+Line 1450:	SubmitError("Не переведена строка номер " + quoted_line_counter + "!", INVALID_INDEX);
+			SubmitError("Line number " + quoted_line_counter + " is not converted!", INVALID_INDEX);
+			
+
+Line 1497:	SubmitError("Файл \"" + file + "\" недоступен для чтения (возможно, он открыт другой программой).", INVALID_INDEX);
+			SubmitError("File \"" + file + "\" cannot be opened for reading (it can be opened by another program).", INVALID_INDEX);
+			
+
+Line 1513:	SubmitError("Файл \"" + file + "\" недоступен для записи (возможно, он открыт другой программой).", INVALID_INDEX);
+			SubmitError("File \"" + file + "\" cannot be opened for writing (it can be opened by another program).", INVALID_INDEX);
+			
+
+MainForm.Designer.cs
+Line 86:             this.label1.Text = "Эта утилита анализирует код игры на языке QSP в формате TXT2GAM.";
+Line 86:             this.label1.Text = "This utility analyzes the QSP game code in form TXT2GAM.";
+
+
+Line 137:             this.btnTry1.Text = "Локации";
+Line 137:             this.btnTry1.Text = "Locations";
+
+
+Line 147:             this.btnTry2.Text = "Переменные";
+Line 147:             this.btnTry2.Text = "Variables";
+
+
+Line 157:             this.btnTry3.Text = "Предметы";
+Line 157:             this.btnTry3.Text = "Items";
+
+
+Line 199:             this.tabCheck.Text = "Анализ"
+Line 199:             this.tabCheck.Text = "Analysis";
+
+
+Line 208:             this.btnTry4.Text = "Действия";
+Line 208:             this.btnTry4.Text = "Events";
+
+
+Line 218:             this.btnReload.Text = "Перечитать";
+Line 218:             this.btnReload.Text = "Reload";
+
+
+Line 242:             this.tabOptions.Text = "Настройки";
+Line 242:             this.tabOptions.Text = "Settings";
+
+
+Line 255:             this.chkCurlyParse.Text = "Интерпретировать содержимое фигурных скобок как код";
+Line 255:             this.chkCurlyParse.Text = "Content between curly brackets take as a code";
+
+
+Line 268:             this.chkActions.Text = "Действия";
+Line 268:             this.chkActions.Text = "Actions";
+
+
+Line 305:             this.lblSystemVariables.Text = "Системные переменные(исключения из списка неиспользуемых переменных)";
+Line 305:             this.lblSystemVariables.Text = "System variables (exception from the list of unused variables)";
+
+
+Line 314:             this.lblSortHeader.Text = "Сортировать при выводе:";
+Line 314:             this.lblSortHeader.Text = "Sort by output:";
+
+
+Line 322:             this.btnReset.Text = "Сбросить настройки";
+Line 322:             this.btnReset.Text = "Reset settings";
+
+
+Line 347:             this.chkSortObjects.Text = "Предметы";
+Line 347:             this.chkSortObjects.Text = "Items";
+
+
+Line 360:             this.chkSortVariables.Text = "Переменные";
+Line 360:             this.chkSortVariables.Text = "Variables";
+
+
+Line 373:             this.chkSortLocations.Text = "Локации";
+Line 373:             this.chkSortLocations.Text = "Locations";
+
+
+Line 399:             this.chkVariableCalls.Text = "Считать присваивание переменных \r\nссылкой на локацию:";
+Line 399:             this.chkVariableCalls.Text = "Consider variable assignment \r\nby link to location:";
+
+
+Line 410:             this.tabTranslate.Text = "Конвертация";
+Line 410:             this.tabTranslate.Text = "Conversion";
+
+
+Line 423:             this.chkIgnoreEmptyTranslationsCsv.Text = "Игнорировать непереведенные строки\r\n(для \"пустых\" значений перевода будет оставлен текст оригинала)";
+Line 423:             this.chkIgnoreEmptyTranslationsCsv.Text = "Ignore unconverted strings\r\n(for \"empty\" value of conversion will be used original text)";
+
+
+Line 434:             this.lblSuffixCsv.Text = "Суффикс для файла перевода:";
+Line 433:             this.lblSuffixCsv.Text = "Extension for conversion file:";
+
+
+Line 451:             this.btnTranslateFromCsv.Text = "Сделать перевод, используя CSV";
+Line 451:             this.btnTranslateFromCsv.Text = "Make conversion, use CSV";
+
+
+Line 464:             this.grpCsvDelimiter.Text = "Разделитель CSV";
+Line 464:             this.grpCsvDelimiter.Text = "Split CSV";
+
+
+Line 475:             this.radComma.Text = "Запятая - ,";
+Line 475:             this.radComma.Text = "Comma - ,";
+
+
+Line 485:             this.radSemicolon.Text = "Точка с запятой - ;";
+Line 485:             this.radSemicolon.Text = "Semicolon - ;";
+
+
+Line 494:             this.btnExportCsv.Text = "Экспорт в CSV";
+Line 494:             this.btnExportCsv.Text = "Export to CSV";
+
+
+Line 520:             this.grpTranslateCsv.Text = "Перевод";
+Line 520:             this.grpTranslateCsv.Text = "Conversion";
+
+
+Line 528:             this.btnBeautify.Text = "Отформатировать код";
+Line 528:             this.btnBeautify.Text = "Format the code";
+
+
+Line 546:             this.Text = "Анализатор кода QSP";
+Line 546:             this.Text = "QSP Code Analyzer";
+
+MainForm.cs
+
+Line 72:             Log("Ошибок: " + Common.GetErrorsCount() + ", предупреждений: " + Common.GetWarningsCount());
+Line 72:             Log("No of errors: " + Common.GetErrorsCount() + ", warnings: " + Common.GetWarningsCount());
+
+
+Line 77:                 string errorMessage = "локация \"" + error.locationName + "\", строка #" + Convert.ToString(err_line) + " : " + error.text;
+Line 77:                 string errorMessage = "Location \"" + error.locationName + "\", Line #" + Convert.ToString(err_line) + " : " + error.text;
+
+
+Line 80:                     Log("Ошибка, " + errorMessage);
+Line 80:                     Log("Error, " + errorMessage);
+
+
+Line 84:                     Log("Предупреждение, " + errorMessage);
+Line 84:                     Log("Warning, " + errorMessage);
+
+
+Line 100:                 Log("Пытаемся прочесть файл...");
+Line 100:                 Log("Trying to read the file ...");
+
+
+Line 103:                     Log("Файл успешно прочитался.");
+Line 103:                     Log("The file was read successfully");
+
+
+Line 110:                 Log("Файл не загружен.");
+Line 110:                 Log("File was not read.");
+
+
+Line 182:                         MessageBox.Show("Исходный файл не найден!");
+Line 182:                         MessageBox.Show("Input file was not found!");
+
+
+Line 188:                     MessageBox.Show("Выберите исходный файл!");
+Line 188:                     MessageBox.Show("Select input file!");
+
+
+Line 235:             Log("Обрабатываем имена локаций...");
+Line 235:             Log("We process the names of locations ...");
+
+
+Line 236:             PrintArray(txtList1, LocationsDefined, "Существующие локации");
+Line 236:             PrintArray(txtList1, LocationsDefined, "Existing locations");
+
+
+Line 237:             Log("Добавлено локаций: " + LocationsDefined.Count.ToString());
+Line 237:             Log("Added locations: " + LocationsDefined.Count.ToString());
+
+
+Line 239:             Log("Обрабатываем ссылки на локации...");
+Line 239:             Log("We process the reference to locations...");
+
+
+Line 240:             PrintArray(txtList2, LocationsReferenced, "Ссылки на локации");
+Line 240:             PrintArray(txtList2, LocationsReferenced, "References to locations");
+
+
+Line 241:             Log("Добавлено ссылок на локации: " + LocationsReferenced.Count.ToString());
+Line 241:             Log("Added reference to location: " + LocationsReferenced.Count.ToString());
+
+
+Line 243:             Log("Начинаем поиск неправильных ссылок...");
+Line 243:             Log("We begin to search for incorrect links ...");
+
+
+Line 244:             PrintArray(txtList3, LocationsUnDefined, "Неверные ссылки");
+Line 244:             PrintArray(txtList3, LocationsUnDefined, "incorrect links");
+
+
+Line 245:             Log("Найдено неправильных ссылок: " + LocationsUnDefined.Count.ToString());
+Line 245:             Log("Found incorrect links: " + LocationsUnDefined.Count.ToString());
+
+
+Line 247:             Log("Начинаем поиск потерянных локаций - тех, на которые нет ссылок...");
+Line 247:             Log("We begin to search for lost locations - those for which there are no references ...");
+
+
+Line 248:             PrintArray(txtList3, LocationsUnReferenced, "Потерянные локации");
+Line 248:             PrintArray(txtList3, LocationsUnReferenced, "Lost locations");
+
+
+Line 249:             Log("Найдено потерянных локаций: " + LocationsUnReferenced.Count.ToString());
+Line 249:             Log("Found lost locations: " + LocationsUnReferenced.Count.ToString());
+
+
+Line 266:             Log("Выполняем поиск переменных...");
+Line 266:             Log("Search for variables ...");
+
+
+Line 293:             PrintArray(txtList1, TextVars, "Текстовые переменные");
+Line 293:             PrintArray(txtList1, TextVars, "String variables");
+
+
+Line 294:             PrintArray(txtList2, NumericVars, "Числовые переменные");
+Line 294:             PrintArray(txtList2, NumericVars, "Numeric variables");
+
+
+Line 296:             Log("Добавлено переменных: " + Common.vars.Count.ToString());
+Line 296:             Log("Added variables: " + Common.vars.Count.ToString());
+
+
+Line 300:             PrintArray(txtList3, TextVars_unassigned, "Не иниц. переменные:");
+Line 300:             PrintArray(txtList3, TextVars_unassigned, "no init variables:");
+
+
+Line 301:             Log("Найдено обращений к неинициализированным текстовым переменным: " + TextVars_unassigned.Count.ToString());
+Line 301:             Log("Found using of uninitialized text variables: " + TextVars_unassigned.Count.ToString());
+
+
+Line 305:             Log("Найдено обращений к неинициализированным числовым переменным: " + NumericVars_unassigned.Count.ToString());
+Line 305:             Log("Found using of uninitialized numeric variables: " + NumericVars_unassigned.Count.ToString());
+
+
+Line 309:             PrintArray(txtList3, TextVars_unused, "Не исп. переменные:");
+Line 309:             PrintArray(txtList3, TextVars_unused, "Unused variables:");
+
+
+Line 310:             Log("Найдено неиспользуемых текстовых переменных: " + TextVars_unused.Count.ToString());
+Line 310:             Log("Found unused string variables: " + TextVars_unused.Count.ToString());
+
+
+Line 314:             Log("Найдено неиспользуемых числовых переменных: " + NumericVars_unused.Count.ToString());
+Line 314:             Log("Found unused numeric variables: " + NumericVars_unused.Count.ToString());
+
+
+Line 349:             Log("Выполняем поиск предметов...");
+Line 349:             Log("Search of items...");
+
+
+Line 350:             PrintArray(txtList1, ObjectsAdded, "Добавление предмета");
+Line 350:             PrintArray(txtList1, ObjectsAdded, "Added items");
+
+
+Line 351:             PrintArray(txtList2, ObjectsDeleted, "Удаление предмета");
+Line 351:             PrintArray(txtList2, ObjectsDeleted, "Remove item");
+
+
+Line 352:             Log("Добавлений предметов: " + ObjectsAdded.Count.ToString());
+Line 352:             Log("Items adding: " + ObjectsAdded.Count.ToString());
+
+
+Line 353:             Log("Удалений предметов: " + ObjectsDeleted.Count.ToString());
+Line 353:             Log("Items removing: " + ObjectsDeleted.Count.ToString());
+
+
+Line 355:             Log("Начинаем поиск удаления несуществующих предметов...");
+Line 355:             Log("Search of nonexisting items...");
+
+
+Line 356:             PrintArray(txtList3, ObjectsUnDefined, "Неверное удаление");
+Line 356:             PrintArray(txtList3, ObjectsUnDefined, "Invalid deletion");
+
+
+Line 357:             Log("Найдено неправильных удалений: " + ObjectsUnDefined.Count.ToString());
+Line 357:             Log("Found invalid deletions: " + ObjectsUnDefined.Count.ToString());
+
+
+Line 359:             Log("Начинаем поиск потерянных предметов - те, которые не удаляются в процессе игры...");
+Line 359:             Log("Looking for lost items - those that are not deleted during the game ...");
+
+
+Line 360:             PrintArray(txtList3, ObjectsLost, "Потерянные предметы");
+Line 360:             PrintArray(txtList3, ObjectsLost, "Lost items");
+
+
+Line 361:             Log("Найдено потерянных предметов: " + ObjectsLost.Count.ToString());
+Line 361:             Log("Lost items found: " + ObjectsLost.Count.ToString());
+
+
+Line 392:             Log("Выполняем поиск действий...");
+Line 392:             Log("Search for actions...");
+
+
+Line 393:             PrintArray(txtList1, ActsAdded, "Добавление действия");
+Line 393:             PrintArray(txtList1, ActsAdded, "Add an action");
+
+
+Line 394:             PrintArray(txtList2, ActsDeleted, "Удаление действия");
+Line 394:             PrintArray(txtList2, ActsDeleted, "Remove an action");
+
+
+Line 395:             Log("Добавлений действий: " + ActsAdded.Count.ToString());
+Line 395:             Log("Added action: " + ActsAdded.Count.ToString());
+
+
+Line 396:             Log("Удалений действий: " + ActsDeleted.Count.ToString());
+Line 396:             Log("Removed action: " + ActsDeleted.Count.ToString());
+
+
+Line 398:             Log("Начинаем поиск удаления несуществующих действий...");
+Line 398:             Log("We begin to search for deletion of nonexistent actions...");
+
+
+Line 399:             PrintArray(txtList3, ActsUnDefined, "Неверное удаление");
+Line 399:             PrintArray(txtList3, ActsUnDefined, "Invalid deletion");
+
+
+Line 400:             Log("Найдено неправильных удалений: " + ActsUnDefined.Count.ToString());
+Line 400:             Log("Invalid deletions found: " + ActsUnDefined.Count.ToString());
+
+
+Line 450:                     MessageBox.Show("Ошибка: " + error.text);
+Line 450:                     MessageBox.Show("Error: " + error.text);
+
+
+Line 464:                     MessageBox.Show("В файле есть ошибки синтаксиса, экспорт невозможен!");
+Line 464:                     MessageBox.Show("There are syntax errors in the file, export is not possible!");
+
+
+Line 498:                     MessageBox.Show("В файле есть ошибки синтаксиса, экспорт невозможен!");
+Line 498:                     MessageBox.Show("There are syntax errors in the file, export is not possible!");
+
+
+Line 505:                     MessageBox.Show("Не обнаружен файл CSV!");
+Line 505:                     MessageBox.Show("CSV file was not found!");
+
+
+Line 510:                     MessageBox.Show("Введите суффикс для файла перевода.");
+Line 510:                     MessageBox.Show("Enter an extension of the conversion file.");
+
+
+QSPGameCode.cs
+
+Line 98:                 SubmitError("Слишком сложное выражение", currentLine);
+Line 98:                 SubmitError("Quite complicated expression", currentLine);
+
+
+Line 110:                 SubmitError("Слишком много аргументов в выражении", currentLine);
+Line 110:                 SubmitError("Quite many arguments in the expression", currentLine);
+
+
+Line 193:                                 SubmitError("Закрывающая фигурная скобка без открывающей", oldLine + 1);
+Line 193:                                 SubmitError("Closing curly brace without opening one", oldLine + 1);
+
+
+Line 229:                 SubmitError("Незакрытая строка", oldLine + 1);
+Line 229:                 SubmitError("Unclosed string", oldLine + 1);
+
+
+Line 235:                 SubmitError("Незакрытая фигурная скобка", oldLine + 1);
+Line 235:                 SubmitError("Unclosed curly bracket", oldLine + 1);
+
+
+Line 476:                             SubmitError("Внутренняя ошибка анализатора - незакрытая фигурная скобка \"{\"", currentLine);
+Line 476:                             SubmitError("Internal error of the analyzer - unclosed curly bracket \"{\"", currentLine);
+
+
+Line 505:                                     SubmitError("Пустая метка", lineNum);
+Line 505:                                     SubmitError("Empty label", lineNum);
+
+
+Line 510:                                     SubmitError("Незакрытая строка в названии метки", lineNum);
+Line 510:                                     SubmitError("Unclosed string in the label name", lineNum);
+
+
+Line 546:                                             SubmitError("ELSEIF без IF", lineNum);
+Line 546:                                             SubmitError("ELSEIF without IF", lineNum);
+
+
+Line 557:                                         SubmitError("Многострочный IF должен стоять в начале строки", lineNum);
+Line 557:                                         SubmitError("Multiline IF should be placed at the beginning of the line", lineNum);
+
+
+Line 559:                                         SubmitError("Многострочный ELSEIF должен стоять в начале строки", lineNum);
+Line 559:                                         SubmitError("Multiline ELSEIF should be placed at the beginning of the line", lineNum);
+
+
+Line 578:                                     SubmitError("ELSEIF в однострочном IF не поддерживается", lineNum);
+Line 578:                                     SubmitError("ELSEIF cannot be used in single line IF", lineNum);
+
+
+Line 584:                                 SubmitError("После знака \":\" в многострочном ELSEIF не должно быть операторов", lineNum);
+Line 584:                                 SubmitError("An operator cannot be placed after colon\":\" in multiline ELSEIF", lineNum);
+
+
+Line 609:                                     SubmitError("Многострочный ACT должен стоять в начале строки", lineNum);
+Line 609:                                     SubmitError("Multiline ACT should be placed at the beginning of the line", lineNum);
+
+
+Line 637:                                     SubmitError("Лишний \"&\": возможно, вы хотели написать \"AND\"", lineNum);
+Line 637:                                     SubmitError("Redundant \"&\": perhaps should be \"AND\"", lineNum);
+
+
+Line 643:                                     SubmitError("Лишний \"&\"", lineNum);
+Line 643:                                     SubmitError("Redundant \"&\"", lineNum);
+
+
+Line 678:                                 SubmitError("Квадратная скобка ставится только сразу за именем массива, без пробелов", lineNum);
+Line 678:                                 SubmitError("A square bracket has to be placed just behind the name of the array, with no spaces", lineNum);
+
+
+Line 692:                                         SubmitError("Лишняя скобка \")\"", lineNum);
+Line 692:                                         SubmitError("Redundant bracket \")\"", lineNum);
+
+
+Line 788:                             SubmitError("Внутренняя ошибка анализатора! Пустой блок!", lineNum);
+Line 788:                             SubmitError("Internal error of analyzer! Empty block!", lineNum);
+
+
+Line 817:                                 SubmitError("ELSEIF без IF", lineNum);
+Line 817:                                 SubmitError("ELSEIF без IF", lineNum);
+
+
+Line 839:                                         SubmitError("После многострочного ELSE не должно быть операторов", lineNum);
+Line 839:                                         SubmitError("An operator cannot be placed after multiline ELSE", lineNum);
+
+
+Line 864:                                             SubmitError("ELSE без IF", lineNum);
+Line 864:                                             SubmitError("ELSE without IF", lineNum);
+
+
+Line 870:                                         SubmitError("Неверная запись однострочного ACT", lineNum);
+Line 870:                                         SubmitError("Invalid notation of single line ACT", lineNum);
+
+
+Line 882:                                         SubmitError("Перед ELSE в однострочном IF должны быть операторы", lineNum);
+Line 882:                                         SubmitError("After single line IF has to be any operators before ELSE", lineNum);
+
+
+Line 888:                                     SubmitError("ELSE без IF", lineNum);
+Line 888:                                     SubmitError("ELSE without IF", lineNum);
+
+
+Line 923:                                 SubmitError("Лишний END", lineNum);
+Line 923:                                 SubmitError("Redundant END", lineNum);
+
+
+Line 982:                             SubmitError("Внутренняя ошибка анализатора! Пустой блок!", lineNum);
+Line 982:                             SubmitError("Internal error of the analyzer! Empty block!", lineNum);
+
+
+Line 1000:                     SubmitError("Лишняя скобка \"(\"", lineNum);
+Line 1000:                     SubmitError("Redundant bracket \"(\"", lineNum);
+
+
+Line 1005:                     SubmitError("IF без \":\"", lineNum);
+Line 1005:                     SubmitError("IF without \":\"", lineNum);
+
+
+Line 1010:                     SubmitError("ACT без \":\"", lineNum);
+Line 1010:                     SubmitError("ACT without \":\"", lineNum);
+
+
+Line 1031:                         SubmitError("Неверная запись однострочного ACT", lineNum);
+Line 1031:                         SubmitError("Invalid notation of single line ACT", lineNum);
+
+
+Line 1036:                         SubmitError("Неверная запись однострочного IF", lineNum);
+Line 1036:                         SubmitError("Invalid notation of single line IF", lineNum);
+
+
+Line 1041:                         SubmitError("После ELSE в однострочном IF должны быть операторы", lineNum);
+Line 1041:                         SubmitError("In single line IF has to be any operators after ELSE", lineNum);
+
+
+Line 1085:                     SubmitError("Многострочный IF без END", cline.line);
+Line 1085:                     SubmitError("Multi line IF without END", cline.line);
+
+
+Line 1090:                     SubmitError("Многострочный ACT без END", cline.line);
+Line 1090:                     SubmitError("Multi line ACT without END", cline.line);
+
+
+Line 1117:                     SubmitError("Не найден знак \"=\"", currentLine);
+Line 1117:                     SubmitError("Not found the char \"=\"", currentLine);
+
+
+Line 1125:                         SubmitError("Не указано имя переменной для присваивания, слева от знака \"=\"", currentLine);
+Line 1125:                         SubmitError("The name of a variable before the character \"=\" is not specified!", currentLine);
+
+
+Line 1131:                         SubmitError("После знака \"=\" должно быть значение для присваивания", currentLine);
+Line 1131:                         SubmitError("It should be a value after char \"=\"", currentLine);
+
+
+Line 1191:                         SubmitError("Оператор IF без условия", currentLine);
+Line 1191:                         SubmitError("Operator IF without condition", currentLine);
+
+
+Line 1195:                         SubmitError("Оператор ELSEIF без условия", currentLine);
+Line 1195:                         SubmitError("Operator ELSEIF without condition", currentLine);
+
+
+Line 1298:                         SubmitError("Слишком много аргументов для оператора", currentLine);
+Line 1298:                         SubmitError("Too many arguments for the operator", currentLine);
+
+
+Line 1312:                             SubmitError("Аргумент не может быть пустым", currentLine);
+Line 1312:                             SubmitError("Argument can not be empty", currentLine);
+
+
+Line 1327:                         SubmitError("Аргумент не может быть пустым", currentLine);
+Line 1327:                         SubmitError("Argument can not be empty", currentLine);
+
+
+Line 1334:                 SubmitError("Для оператора требуется больше аргументов", currentLine);
+Line 1334:                 SubmitError("The operator requires more arguments", currentLine);
+
+
+Line 1369:                         SubmitError("Неизвестное действие в выражении", currentLine);
+Line 1369:                         SubmitError("Unknown action in the expression", currentLine);
+
+
+Line 1376:                         SubmitError("Ошибка синтаксиса", currentLine);
+Line 1376:                         SubmitError("Syntax error", currentLine);
+
+
+Line 1390:                             SubmitError("Ошибка синтаксиса", currentLine);
+Line 1390:                             SubmitError("Syntax error", currentLine);
+
+
+Line 1402:                             SubmitError("Не найдена закрывающая скобка", currentLine);
+Line 1402:                             SubmitError("Closing bracket not found", currentLine);
+
+
+Line 1410:                             SubmitError("Не найдена открывающая скобка", currentLine);
+Line 1410:                             SubmitError("Opening bracket not found", currentLine);
+
+
+Line 1419:                                 SubmitError("Неверное число аргументов функции", currentLine);
+Line 1419:                                 SubmitError("Invalid number of arguments", currentLine);
+
+
+Line 1496:                                 SubmitError("Неверное число аргументов функции", currentLine);
+Line 1496:                                 SubmitError("Invalid number of arguments", currentLine);
+
+
+Line 1498:                                 SubmitError("Ошибка синтаксиса", currentLine);
+Line 1498:                                 SubmitError("Syntax error", currentLine);
+
+
+Line 1504:                             SubmitError("Ошибка синтаксиса", currentLine);
+Line 1504:                             SubmitError("Syntax error", currentLine);
+
+
+Line 1509:                             SubmitError("Неверное число аргументов функции", currentLine);
+Line 1509:                             SubmitError("Invalid number of arguments", currentLine);
+
+
+Line 1522:                             SubmitError("Внутренняя ошибка анализатора: недопустимые символы в имени переменной", currentLine);
+Line 1522:                             SubmitError("Internal error of the analyzer: Invalid characters in the variable name", currentLine);
+
+
+Line 1554:                                 SubmitError("Скобки не найдены", currentLine);
+Line 1554:                                 SubmitError("Brackets not found", currentLine);
+
+
+Line 1587:                                     SubmitError("Незакрытая скобка \"[\"", currentLine);
+Line 1587:                                     SubmitError("Unclosed parenthesis \"[\"", currentLine);
+
+
+Line 1609:                             SubmitError("Неверное число аргументов функции", currentLine);
+Line 1609:                             SubmitError("Invalid number of arguments", currentLine);
+
+
+Line 1611:                             SubmitError("Ошибка синтаксиса", currentLine);
+Line 1611:                             SubmitError("Syntax error", currentLine);
+
+
+Line 1625:                 SubmitError("Внутренняя ошибка анализатора: пустое имя переменной!", currentLine);
+Line 1625:                 SubmitError("Internal error of the analyzer: empty name of variable!", currentLine);
+
+
+Line 1634:                 SubmitError("Ключевое слово языка \"" + name + "\" не может быть использовано в качестве имени переменной", currentLine);
+Line 1634:                 SubmitError("QSP Keyword \"" + name + "\" cannot be used as a variable name", currentLine);
+
+
+Line 1647:                 SubmitError("Недопустимое имя переменной \"" + name + "\"", currentLine);
+Line 1647:                 SubmitError("Invalid variable name \"" + name + "\"", currentLine);
+
+
+Line 1653:                 SubmitError("Имя переменной \"" + name + "\" не может начинаться с цифры", currentLine);
+Line 1653:                 SubmitError("Variable name \"" + name + "\" cannot start with a digit", currentLine);
+
+
+Line 1659:                 SubmitError("Недопустимые символы в имени переменной \"" + name + "\"", currentLine);
+Line 1659:                 SubmitError("Invalid symbols in the name of the variable \"" + name + "\"", currentLine);
+
+
+Line 1666:                 SubmitWarning("В имени переменной \"" + name + "\" используются одновременно английские и русские символы, возможно опечатка", currentLine);
+Line 1666:                 SubmitWarning("English and Russian symbols are used simultaneously in the name of varible \"" + name + "\" , possibly a typo", currentLine);
+
+
+Line 1687:                     SubmitError("Недопустимое выражение", currentLine);
+Line 1687:                     SubmitError("Invalid expression", currentLine);
+
+
+Line 1708:                 SubmitError("Слева от знака \"=\" в операции присваивания должно стоять имя переменной", currentLine);
+Line 1708:                 SubmitError("Name of the variable should be before char \"=\" in the assignment operation", currentLine);
+
+
+Line 1908:                     SubmitWarning("Незакрытый апостроф внутри тега", currentLine);
+Line 1908:                     SubmitWarning("Unclosed apostrophe inside the tag", currentLine);
+
+
+Line 1913:                     SubmitWarning("Незакрытая кавычка внутри тега", currentLine);
+Line 1913:                     SubmitWarning("Unclosed quote inside the tag", currentLine);
+
+
+Line 1918:                     SubmitWarning("Незакрытый тег",currentLine);
+Line 1918:                     SubmitWarning("Unclosed tag",currentLine);
+
+
+Line 1923:                     SubmitWarning("Имя тега должно следовать сразу за открывающей угловой скобкой, без пробелов", currentLine);
+Line 1923:                     SubmitWarning("The name of the tag should follow immediately after the opening angle bracket, without spaces", currentLine);
+
+
+Line 2048:                         SubmitError("Незакрытый апостроф в подвыражении", currentLine);
+Line 2048:                         SubmitError("Unclosed apostrophe in a subexpression", currentLine);	
+	
+
+Line 2055:                         SubmitError("Незакрытая кавычка в подвыражении", currentLine);	
+Line 2055:                         SubmitError("Unclosed quote in a subexpression", currentLine);
+
+
+Line 2062:                         SubmitError("Незакрытая фигурная скобка в подвыражении", currentLine);
+Line 2062:                         SubmitError("Unclosed curly bracket in a subexpression", currentLine);
+
+
+Line 2069:                         SubmitError("Незакрытое подвыражение", currentLine);
+Line 2069:                         SubmitError("Unclosed subexpression", currentLine);
+
+
+Line 2076:                         SubmitError("Пустое подвыражение", currentLine);
+Line 2076:                         SubmitError("Empty subexpression", currentLine);
+
+
+Line 2173:                 SubmitError("Пустое имя локации", line);
+Line 2173:                 SubmitError("Empty name of location", line);
+
+
+Line 2178:                 SubmitError("Локация с именем " + name + " уже существует", line);
+Line 2178:                 SubmitError("Location named " + name + " exist already", line);

+ 631 - 0
QSP/qsp-analyser/QSP_Analyser/MainForm.Designer.cs

@@ -0,0 +1,631 @@
+namespace Analyser
+{
+    partial class MainForm
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.label1 = new System.Windows.Forms.Label();
+            this.dlgOpen = new System.Windows.Forms.OpenFileDialog();
+            this.btnBrowse = new System.Windows.Forms.Button();
+            this.txtList1 = new System.Windows.Forms.TextBox();
+            this.txtList2 = new System.Windows.Forms.TextBox();
+            this.txtList3 = new System.Windows.Forms.TextBox();
+            this.btnTry1 = new System.Windows.Forms.Button();
+            this.btnTry2 = new System.Windows.Forms.Button();
+            this.btnTry3 = new System.Windows.Forms.Button();
+            this.txtStatus = new System.Windows.Forms.TextBox();
+            this.tabControl = new System.Windows.Forms.TabControl();
+            this.tabCheck = new System.Windows.Forms.TabPage();
+            this.btnCancel = new System.Windows.Forms.Button();
+            this.btnTry4 = new System.Windows.Forms.Button();
+            this.btnReload = new System.Windows.Forms.Button();
+            this.tabOptions = new System.Windows.Forms.TabPage();
+            this.chkCurlyParse = new System.Windows.Forms.CheckBox();
+            this.chkActions = new System.Windows.Forms.CheckBox();
+            this.txtSystemAeroVars = new System.Windows.Forms.TextBox();
+            this.chkAero = new System.Windows.Forms.CheckBox();
+            this.lblSystemVariables = new System.Windows.Forms.Label();
+            this.lblSortHeader = new System.Windows.Forms.Label();
+            this.btnReset = new System.Windows.Forms.Button();
+            this.txtSystemVariables = new System.Windows.Forms.TextBox();
+            this.chkSortObjects = new System.Windows.Forms.CheckBox();
+            this.chkSortVariables = new System.Windows.Forms.CheckBox();
+            this.chkSortLocations = new System.Windows.Forms.CheckBox();
+            this.txtVariableNames = new System.Windows.Forms.TextBox();
+            this.chkVariableCalls = new System.Windows.Forms.CheckBox();
+            this.tabTranslate = new System.Windows.Forms.TabPage();
+            this.btnBeautify = new System.Windows.Forms.Button();
+            this.grpTranslateCsv = new System.Windows.Forms.GroupBox();
+            this.grpCsvDelimiter = new System.Windows.Forms.GroupBox();
+            this.radComma = new System.Windows.Forms.RadioButton();
+            this.radSemicolon = new System.Windows.Forms.RadioButton();
+            this.btnTranslateFromCsv = new System.Windows.Forms.Button();
+            this.chkIgnoreEmptyTranslationsCsv = new System.Windows.Forms.CheckBox();
+            this.lblSuffixCsv = new System.Windows.Forms.Label();
+            this.btnExportCsv = new System.Windows.Forms.Button();
+            this.edtSuffixCsv = new System.Windows.Forms.TextBox();
+            this.edtFile = new System.Windows.Forms.TextBox();
+            this.progressBar1 = new System.Windows.Forms.ProgressBar();
+            this.tabControl.SuspendLayout();
+            this.tabCheck.SuspendLayout();
+            this.tabOptions.SuspendLayout();
+            this.tabTranslate.SuspendLayout();
+            this.grpTranslateCsv.SuspendLayout();
+            this.grpCsvDelimiter.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(15, 13);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(287, 13);
+            this.label1.TabIndex = 0;
+            this.label1.Text = "This utility analyzes the QSP game code in form TXT2GAM.";
+            // 
+            // btnBrowse
+            // 
+            this.btnBrowse.Location = new System.Drawing.Point(591, 8);
+            this.btnBrowse.Name = "btnBrowse";
+            this.btnBrowse.Size = new System.Drawing.Size(29, 23);
+            this.btnBrowse.TabIndex = 2;
+            this.btnBrowse.Text = "...";
+            this.btnBrowse.UseVisualStyleBackColor = true;
+            this.btnBrowse.Click += new System.EventHandler(this.btnBrowse_Click);
+            // 
+            // txtList1
+            // 
+            this.txtList1.BackColor = System.Drawing.SystemColors.Window;
+            this.txtList1.Location = new System.Drawing.Point(3, 59);
+            this.txtList1.Multiline = true;
+            this.txtList1.Name = "txtList1";
+            this.txtList1.ReadOnly = true;
+            this.txtList1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.txtList1.Size = new System.Drawing.Size(205, 348);
+            this.txtList1.TabIndex = 3;
+            // 
+            // txtList2
+            // 
+            this.txtList2.BackColor = System.Drawing.SystemColors.Window;
+            this.txtList2.Location = new System.Drawing.Point(214, 59);
+            this.txtList2.Multiline = true;
+            this.txtList2.Name = "txtList2";
+            this.txtList2.ReadOnly = true;
+            this.txtList2.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.txtList2.Size = new System.Drawing.Size(210, 348);
+            this.txtList2.TabIndex = 4;
+            // 
+            // txtList3
+            // 
+            this.txtList3.BackColor = System.Drawing.SystemColors.Window;
+            this.txtList3.Location = new System.Drawing.Point(430, 59);
+            this.txtList3.Multiline = true;
+            this.txtList3.Name = "txtList3";
+            this.txtList3.ReadOnly = true;
+            this.txtList3.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.txtList3.Size = new System.Drawing.Size(229, 348);
+            this.txtList3.TabIndex = 5;
+            // 
+            // btnTry1
+            // 
+            this.btnTry1.Location = new System.Drawing.Point(12, 6);
+            this.btnTry1.Name = "btnTry1";
+            this.btnTry1.Size = new System.Drawing.Size(77, 28);
+            this.btnTry1.TabIndex = 6;
+            this.btnTry1.Text = "Locations";
+            this.btnTry1.UseVisualStyleBackColor = true;
+            this.btnTry1.Click += new System.EventHandler(this.btnTry1_Click);
+            // 
+            // btnTry2
+            // 
+            this.btnTry2.Location = new System.Drawing.Point(95, 6);
+            this.btnTry2.Name = "btnTry2";
+            this.btnTry2.Size = new System.Drawing.Size(91, 28);
+            this.btnTry2.TabIndex = 7;
+            this.btnTry2.Text = "Variables";
+            this.btnTry2.UseVisualStyleBackColor = true;
+            this.btnTry2.Click += new System.EventHandler(this.btnTry2_Click);
+            // 
+            // btnTry3
+            // 
+            this.btnTry3.Location = new System.Drawing.Point(192, 6);
+            this.btnTry3.Name = "btnTry3";
+            this.btnTry3.Size = new System.Drawing.Size(80, 28);
+            this.btnTry3.TabIndex = 8;
+            this.btnTry3.Text = "Items";
+            this.btnTry3.UseVisualStyleBackColor = true;
+            this.btnTry3.Click += new System.EventHandler(this.btnTry3_Click);
+            // 
+            // txtStatus
+            // 
+            this.txtStatus.BackColor = System.Drawing.SystemColors.Window;
+            this.txtStatus.Location = new System.Drawing.Point(3, 413);
+            this.txtStatus.Multiline = true;
+            this.txtStatus.Name = "txtStatus";
+            this.txtStatus.ReadOnly = true;
+            this.txtStatus.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.txtStatus.Size = new System.Drawing.Size(656, 148);
+            this.txtStatus.TabIndex = 9;
+            // 
+            // tabControl
+            // 
+            this.tabControl.Controls.Add(this.tabCheck);
+            this.tabControl.Controls.Add(this.tabOptions);
+            this.tabControl.Controls.Add(this.tabTranslate);
+            this.tabControl.Location = new System.Drawing.Point(1, 37);
+            this.tabControl.Name = "tabControl";
+            this.tabControl.SelectedIndex = 0;
+            this.tabControl.Size = new System.Drawing.Size(670, 590);
+            this.tabControl.TabIndex = 12;
+            // 
+            // tabCheck
+            // 
+            this.tabCheck.Controls.Add(this.btnCancel);
+            this.tabCheck.Controls.Add(this.btnTry4);
+            this.tabCheck.Controls.Add(this.btnReload);
+            this.tabCheck.Controls.Add(this.btnTry1);
+            this.tabCheck.Controls.Add(this.txtStatus);
+            this.tabCheck.Controls.Add(this.txtList3);
+            this.tabCheck.Controls.Add(this.btnTry2);
+            this.tabCheck.Controls.Add(this.txtList2);
+            this.tabCheck.Controls.Add(this.btnTry3);
+            this.tabCheck.Controls.Add(this.txtList1);
+            this.tabCheck.Location = new System.Drawing.Point(4, 22);
+            this.tabCheck.Name = "tabCheck";
+            this.tabCheck.Padding = new System.Windows.Forms.Padding(3);
+            this.tabCheck.Size = new System.Drawing.Size(662, 564);
+            this.tabCheck.TabIndex = 0;
+            this.tabCheck.Text = "Analysis";
+            this.tabCheck.UseVisualStyleBackColor = true;
+            // 
+            // btnCancel
+            // 
+            this.btnCancel.Location = new System.Drawing.Point(455, 6);
+            this.btnCancel.Name = "btnCancel";
+            this.btnCancel.Size = new System.Drawing.Size(77, 28);
+            this.btnCancel.TabIndex = 14;
+            this.btnCancel.Text = "Cancel";
+            this.btnCancel.UseVisualStyleBackColor = true;
+            this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
+            // 
+            // btnTry4
+            // 
+            this.btnTry4.Location = new System.Drawing.Point(278, 6);
+            this.btnTry4.Name = "btnTry4";
+            this.btnTry4.Size = new System.Drawing.Size(75, 28);
+            this.btnTry4.TabIndex = 13;
+            this.btnTry4.Text = "Events";
+            this.btnTry4.UseVisualStyleBackColor = true;
+            this.btnTry4.Click += new System.EventHandler(this.btnTry4_Click);
+            // 
+            // btnReload
+            // 
+            this.btnReload.Location = new System.Drawing.Point(538, 6);
+            this.btnReload.Name = "btnReload";
+            this.btnReload.Size = new System.Drawing.Size(77, 28);
+            this.btnReload.TabIndex = 12;
+            this.btnReload.Text = "Reload";
+            this.btnReload.UseVisualStyleBackColor = true;
+            this.btnReload.Click += new System.EventHandler(this.btnReload_Click);
+            // 
+            // tabOptions
+            // 
+            this.tabOptions.Controls.Add(this.chkCurlyParse);
+            this.tabOptions.Controls.Add(this.chkActions);
+            this.tabOptions.Controls.Add(this.txtSystemAeroVars);
+            this.tabOptions.Controls.Add(this.chkAero);
+            this.tabOptions.Controls.Add(this.lblSystemVariables);
+            this.tabOptions.Controls.Add(this.lblSortHeader);
+            this.tabOptions.Controls.Add(this.btnReset);
+            this.tabOptions.Controls.Add(this.txtSystemVariables);
+            this.tabOptions.Controls.Add(this.chkSortObjects);
+            this.tabOptions.Controls.Add(this.chkSortVariables);
+            this.tabOptions.Controls.Add(this.chkSortLocations);
+            this.tabOptions.Controls.Add(this.txtVariableNames);
+            this.tabOptions.Controls.Add(this.chkVariableCalls);
+            this.tabOptions.Location = new System.Drawing.Point(4, 22);
+            this.tabOptions.Name = "tabOptions";
+            this.tabOptions.Padding = new System.Windows.Forms.Padding(3);
+            this.tabOptions.Size = new System.Drawing.Size(662, 564);
+            this.tabOptions.TabIndex = 1;
+            this.tabOptions.Text = "Settings";
+            this.tabOptions.UseVisualStyleBackColor = true;
+            // 
+            // chkCurlyParse
+            // 
+            this.chkCurlyParse.AutoSize = true;
+            this.chkCurlyParse.Checked = global::Analyser.Properties.Settings.Default.EnableCurlyParsing;
+            this.chkCurlyParse.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.chkCurlyParse.DataBindings.Add(new System.Windows.Forms.Binding("Checked", global::Analyser.Properties.Settings.Default, "EnableCurlyParsing", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
+            this.chkCurlyParse.Location = new System.Drawing.Point(250, 290);
+            this.chkCurlyParse.Name = "chkCurlyParse";
+            this.chkCurlyParse.Size = new System.Drawing.Size(250, 17);
+            this.chkCurlyParse.TabIndex = 23;
+            this.chkCurlyParse.Text = "Content between curly brackets take as a code";
+            this.chkCurlyParse.UseVisualStyleBackColor = true;
+            // 
+            // chkActions
+            // 
+            this.chkActions.AutoSize = true;
+            this.chkActions.Checked = global::Analyser.Properties.Settings.Default.EnableSortingActions;
+            this.chkActions.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.chkActions.DataBindings.Add(new System.Windows.Forms.Binding("Checked", global::Analyser.Properties.Settings.Default, "EnableSortingActions", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
+            this.chkActions.Location = new System.Drawing.Point(260, 112);
+            this.chkActions.Name = "chkActions";
+            this.chkActions.Size = new System.Drawing.Size(61, 17);
+            this.chkActions.TabIndex = 22;
+            this.chkActions.Text = "Actions";
+            this.chkActions.UseVisualStyleBackColor = true;
+            // 
+            // txtSystemAeroVars
+            // 
+            this.txtSystemAeroVars.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", global::Analyser.Properties.Settings.Default, "EnableAero", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
+            this.txtSystemAeroVars.DataBindings.Add(new System.Windows.Forms.Binding("Text", global::Analyser.Properties.Settings.Default, "AeroSystemVars", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
+            this.txtSystemAeroVars.Enabled = global::Analyser.Properties.Settings.Default.EnableAero;
+            this.txtSystemAeroVars.Location = new System.Drawing.Point(423, 42);
+            this.txtSystemAeroVars.Multiline = true;
+            this.txtSystemAeroVars.Name = "txtSystemAeroVars";
+            this.txtSystemAeroVars.ReadOnly = true;
+            this.txtSystemAeroVars.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.txtSystemAeroVars.Size = new System.Drawing.Size(157, 190);
+            this.txtSystemAeroVars.TabIndex = 21;
+            this.txtSystemAeroVars.Text = global::Analyser.Properties.Settings.Default.AeroSystemVars;
+            // 
+            // chkAero
+            // 
+            this.chkAero.AutoSize = true;
+            this.chkAero.Checked = global::Analyser.Properties.Settings.Default.EnableAero;
+            this.chkAero.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.chkAero.DataBindings.Add(new System.Windows.Forms.Binding("Checked", global::Analyser.Properties.Settings.Default, "EnableAero", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
+            this.chkAero.Location = new System.Drawing.Point(423, 13);
+            this.chkAero.Name = "chkAero";
+            this.chkAero.Size = new System.Drawing.Size(70, 17);
+            this.chkAero.TabIndex = 20;
+            this.chkAero.Text = "AeroQSP";
+            this.chkAero.UseVisualStyleBackColor = true;
+            // 
+            // lblSystemVariables
+            // 
+            this.lblSystemVariables.AutoSize = true;
+            this.lblSystemVariables.Location = new System.Drawing.Point(0, 255);
+            this.lblSystemVariables.Name = "lblSystemVariables";
+            this.lblSystemVariables.Size = new System.Drawing.Size(292, 13);
+            this.lblSystemVariables.TabIndex = 19;
+            this.lblSystemVariables.Text = "System variables (exception from the list of unused variables)";
+            // 
+            // lblSortHeader
+            // 
+            this.lblSortHeader.AutoSize = true;
+            this.lblSortHeader.Location = new System.Drawing.Point(245, 14);
+            this.lblSortHeader.Name = "lblSortHeader";
+            this.lblSortHeader.Size = new System.Drawing.Size(76, 13);
+            this.lblSortHeader.TabIndex = 15;
+            this.lblSortHeader.Text = "Sort by output:";
+            // 
+            // btnReset
+            // 
+            this.btnReset.Location = new System.Drawing.Point(13, 519);
+            this.btnReset.Name = "btnReset";
+            this.btnReset.Size = new System.Drawing.Size(147, 23);
+            this.btnReset.TabIndex = 13;
+            this.btnReset.Text = "Reset settings";
+            this.btnReset.UseVisualStyleBackColor = true;
+            this.btnReset.Click += new System.EventHandler(this.btnReset_Click);
+            // 
+            // txtSystemVariables
+            // 
+            this.txtSystemVariables.DataBindings.Add(new System.Windows.Forms.Binding("Text", global::Analyser.Properties.Settings.Default, "SystemVariables", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
+            this.txtSystemVariables.Location = new System.Drawing.Point(0, 274);
+            this.txtSystemVariables.Multiline = true;
+            this.txtSystemVariables.Name = "txtSystemVariables";
+            this.txtSystemVariables.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.txtSystemVariables.Size = new System.Drawing.Size(213, 220);
+            this.txtSystemVariables.TabIndex = 18;
+            this.txtSystemVariables.Text = global::Analyser.Properties.Settings.Default.SystemVariables;
+            // 
+            // chkSortObjects
+            // 
+            this.chkSortObjects.AutoSize = true;
+            this.chkSortObjects.Checked = global::Analyser.Properties.Settings.Default.EnableSortingObjects;
+            this.chkSortObjects.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.chkSortObjects.DataBindings.Add(new System.Windows.Forms.Binding("Checked", global::Analyser.Properties.Settings.Default, "EnableSortingObjects", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
+            this.chkSortObjects.Location = new System.Drawing.Point(260, 88);
+            this.chkSortObjects.Name = "chkSortObjects";
+            this.chkSortObjects.Size = new System.Drawing.Size(51, 17);
+            this.chkSortObjects.TabIndex = 17;
+            this.chkSortObjects.Text = "Items";
+            this.chkSortObjects.UseVisualStyleBackColor = true;
+            // 
+            // chkSortVariables
+            // 
+            this.chkSortVariables.AutoSize = true;
+            this.chkSortVariables.Checked = global::Analyser.Properties.Settings.Default.EnableSortingVariables;
+            this.chkSortVariables.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.chkSortVariables.DataBindings.Add(new System.Windows.Forms.Binding("Checked", global::Analyser.Properties.Settings.Default, "EnableSortingVariables", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
+            this.chkSortVariables.Location = new System.Drawing.Point(260, 65);
+            this.chkSortVariables.Name = "chkSortVariables";
+            this.chkSortVariables.Size = new System.Drawing.Size(69, 17);
+            this.chkSortVariables.TabIndex = 16;
+            this.chkSortVariables.Text = "Variables";
+            this.chkSortVariables.UseVisualStyleBackColor = true;
+            // 
+            // chkSortLocations
+            // 
+            this.chkSortLocations.AutoSize = true;
+            this.chkSortLocations.Checked = global::Analyser.Properties.Settings.Default.EnableSortingLocations;
+            this.chkSortLocations.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.chkSortLocations.DataBindings.Add(new System.Windows.Forms.Binding("Checked", global::Analyser.Properties.Settings.Default, "EnableSortingLocations", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
+            this.chkSortLocations.Location = new System.Drawing.Point(260, 42);
+            this.chkSortLocations.Name = "chkSortLocations";
+            this.chkSortLocations.Size = new System.Drawing.Size(72, 17);
+            this.chkSortLocations.TabIndex = 14;
+            this.chkSortLocations.Text = "Locations";
+            this.chkSortLocations.UseVisualStyleBackColor = true;
+            // 
+            // txtVariableNames
+            // 
+            this.txtVariableNames.DataBindings.Add(new System.Windows.Forms.Binding("Text", global::Analyser.Properties.Settings.Default, "VariableNames", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
+            this.txtVariableNames.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", global::Analyser.Properties.Settings.Default, "EnableVariableCalls", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
+            this.txtVariableNames.Enabled = global::Analyser.Properties.Settings.Default.EnableVariableCalls;
+            this.txtVariableNames.Location = new System.Drawing.Point(0, 42);
+            this.txtVariableNames.Multiline = true;
+            this.txtVariableNames.Name = "txtVariableNames";
+            this.txtVariableNames.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.txtVariableNames.Size = new System.Drawing.Size(213, 190);
+            this.txtVariableNames.TabIndex = 12;
+            this.txtVariableNames.Text = global::Analyser.Properties.Settings.Default.VariableNames;
+            // 
+            // chkVariableCalls
+            // 
+            this.chkVariableCalls.AutoSize = true;
+            this.chkVariableCalls.Checked = global::Analyser.Properties.Settings.Default.EnableVariableCalls;
+            this.chkVariableCalls.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.chkVariableCalls.DataBindings.Add(new System.Windows.Forms.Binding("Checked", global::Analyser.Properties.Settings.Default, "EnableVariableCalls", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
+            this.chkVariableCalls.Location = new System.Drawing.Point(3, 6);
+            this.chkVariableCalls.Name = "chkVariableCalls";
+            this.chkVariableCalls.Size = new System.Drawing.Size(166, 30);
+            this.chkVariableCalls.TabIndex = 11;
+            this.chkVariableCalls.Text = "Consider variable assignment \r\nby link to location:";
+            this.chkVariableCalls.UseVisualStyleBackColor = true;
+            // 
+            // tabTranslate
+            // 
+            this.tabTranslate.Controls.Add(this.btnBeautify);
+            this.tabTranslate.Controls.Add(this.grpTranslateCsv);
+            this.tabTranslate.Location = new System.Drawing.Point(4, 22);
+            this.tabTranslate.Name = "tabTranslate";
+            this.tabTranslate.Size = new System.Drawing.Size(662, 564);
+            this.tabTranslate.TabIndex = 2;
+            this.tabTranslate.Text = "Conversion";
+            this.tabTranslate.UseVisualStyleBackColor = true;
+            // 
+            // btnBeautify
+            // 
+            this.btnBeautify.Location = new System.Drawing.Point(56, 279);
+            this.btnBeautify.Name = "btnBeautify";
+            this.btnBeautify.Size = new System.Drawing.Size(129, 23);
+            this.btnBeautify.TabIndex = 9;
+            this.btnBeautify.Text = "Format the code";
+            this.btnBeautify.UseVisualStyleBackColor = true;
+            this.btnBeautify.Click += new System.EventHandler(this.btnBeautify_Click);
+            // 
+            // grpTranslateCsv
+            // 
+            this.grpTranslateCsv.Controls.Add(this.grpCsvDelimiter);
+            this.grpTranslateCsv.Controls.Add(this.btnTranslateFromCsv);
+            this.grpTranslateCsv.Controls.Add(this.chkIgnoreEmptyTranslationsCsv);
+            this.grpTranslateCsv.Controls.Add(this.lblSuffixCsv);
+            this.grpTranslateCsv.Controls.Add(this.btnExportCsv);
+            this.grpTranslateCsv.Controls.Add(this.edtSuffixCsv);
+            this.grpTranslateCsv.Location = new System.Drawing.Point(7, 3);
+            this.grpTranslateCsv.Name = "grpTranslateCsv";
+            this.grpTranslateCsv.Size = new System.Drawing.Size(642, 168);
+            this.grpTranslateCsv.TabIndex = 8;
+            this.grpTranslateCsv.TabStop = false;
+            this.grpTranslateCsv.Text = "Conversion";
+            // 
+            // grpCsvDelimiter
+            // 
+            this.grpCsvDelimiter.Controls.Add(this.radComma);
+            this.grpCsvDelimiter.Controls.Add(this.radSemicolon);
+            this.grpCsvDelimiter.Location = new System.Drawing.Point(24, 29);
+            this.grpCsvDelimiter.Name = "grpCsvDelimiter";
+            this.grpCsvDelimiter.Size = new System.Drawing.Size(138, 72);
+            this.grpCsvDelimiter.TabIndex = 3;
+            this.grpCsvDelimiter.TabStop = false;
+            this.grpCsvDelimiter.Text = "Split CSV";
+            // 
+            // radComma
+            // 
+            this.radComma.AutoSize = true;
+            this.radComma.Checked = true;
+            this.radComma.Location = new System.Drawing.Point(6, 19);
+            this.radComma.Name = "radComma";
+            this.radComma.Size = new System.Drawing.Size(72, 17);
+            this.radComma.TabIndex = 1;
+            this.radComma.TabStop = true;
+            this.radComma.Text = "Comma - ,";
+            this.radComma.UseVisualStyleBackColor = true;
+            // 
+            // radSemicolon
+            // 
+            this.radSemicolon.AutoSize = true;
+            this.radSemicolon.Location = new System.Drawing.Point(6, 42);
+            this.radSemicolon.Name = "radSemicolon";
+            this.radSemicolon.Size = new System.Drawing.Size(86, 17);
+            this.radSemicolon.TabIndex = 2;
+            this.radSemicolon.Text = "Semicolon - ;";
+            this.radSemicolon.UseVisualStyleBackColor = true;
+            // 
+            // btnTranslateFromCsv
+            // 
+            this.btnTranslateFromCsv.Location = new System.Drawing.Point(303, 126);
+            this.btnTranslateFromCsv.Name = "btnTranslateFromCsv";
+            this.btnTranslateFromCsv.Size = new System.Drawing.Size(198, 23);
+            this.btnTranslateFromCsv.TabIndex = 4;
+            this.btnTranslateFromCsv.Text = "Make conversion, use CSV";
+            this.btnTranslateFromCsv.UseVisualStyleBackColor = true;
+            this.btnTranslateFromCsv.Click += new System.EventHandler(this.btnTranslateFromCsv_Click);
+            // 
+            // chkIgnoreEmptyTranslationsCsv
+            // 
+            this.chkIgnoreEmptyTranslationsCsv.AutoSize = true;
+            this.chkIgnoreEmptyTranslationsCsv.Checked = global::Analyser.Properties.Settings.Default.IgnoreEmptyTranslationsCsv;
+            this.chkIgnoreEmptyTranslationsCsv.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.chkIgnoreEmptyTranslationsCsv.DataBindings.Add(new System.Windows.Forms.Binding("Checked", global::Analyser.Properties.Settings.Default, "IgnoreEmptyTranslationsCsv", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
+            this.chkIgnoreEmptyTranslationsCsv.Location = new System.Drawing.Point(235, 55);
+            this.chkIgnoreEmptyTranslationsCsv.Name = "chkIgnoreEmptyTranslationsCsv";
+            this.chkIgnoreEmptyTranslationsCsv.Size = new System.Drawing.Size(295, 30);
+            this.chkIgnoreEmptyTranslationsCsv.TabIndex = 7;
+            this.chkIgnoreEmptyTranslationsCsv.Text = "Ignore unconverted strings\r\n(for \"empty\" value of conversion will be used origina" +
+    "l text)";
+            this.chkIgnoreEmptyTranslationsCsv.UseVisualStyleBackColor = true;
+            // 
+            // lblSuffixCsv
+            // 
+            this.lblSuffixCsv.AutoSize = true;
+            this.lblSuffixCsv.Location = new System.Drawing.Point(232, 32);
+            this.lblSuffixCsv.Name = "lblSuffixCsv";
+            this.lblSuffixCsv.Size = new System.Drawing.Size(142, 13);
+            this.lblSuffixCsv.TabIndex = 6;
+            this.lblSuffixCsv.Text = "Extension for conversion file:";
+            // 
+            // btnExportCsv
+            // 
+            this.btnExportCsv.Location = new System.Drawing.Point(41, 126);
+            this.btnExportCsv.Name = "btnExportCsv";
+            this.btnExportCsv.Size = new System.Drawing.Size(97, 23);
+            this.btnExportCsv.TabIndex = 0;
+            this.btnExportCsv.Text = "Export to CSV";
+            this.btnExportCsv.UseVisualStyleBackColor = true;
+            this.btnExportCsv.Click += new System.EventHandler(this.btnExportCsv_Click);
+            // 
+            // edtSuffixCsv
+            // 
+            this.edtSuffixCsv.DataBindings.Add(new System.Windows.Forms.Binding("Text", global::Analyser.Properties.Settings.Default, "CsvTranslationSuffix", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
+            this.edtSuffixCsv.Location = new System.Drawing.Point(401, 29);
+            this.edtSuffixCsv.Name = "edtSuffixCsv";
+            this.edtSuffixCsv.Size = new System.Drawing.Size(100, 20);
+            this.edtSuffixCsv.TabIndex = 5;
+            this.edtSuffixCsv.Text = global::Analyser.Properties.Settings.Default.CsvTranslationSuffix;
+            // 
+            // edtFile
+            // 
+            this.edtFile.DataBindings.Add(new System.Windows.Forms.Binding("Text", global::Analyser.Properties.Settings.Default, "filepath", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
+            this.edtFile.Location = new System.Drawing.Point(409, 10);
+            this.edtFile.Name = "edtFile";
+            this.edtFile.Size = new System.Drawing.Size(176, 20);
+            this.edtFile.TabIndex = 1;
+            this.edtFile.Text = global::Analyser.Properties.Settings.Default.filepath;
+            // 
+            // progressBar1
+            // 
+            this.progressBar1.Location = new System.Drawing.Point(5, 626);
+            this.progressBar1.Name = "progressBar1";
+            this.progressBar1.Size = new System.Drawing.Size(659, 23);
+            this.progressBar1.TabIndex = 13;
+            // 
+            // MainForm
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(668, 653);
+            this.Controls.Add(this.progressBar1);
+            this.Controls.Add(this.tabControl);
+            this.Controls.Add(this.btnBrowse);
+            this.Controls.Add(this.edtFile);
+            this.Controls.Add(this.label1);
+            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
+            this.MaximizeBox = false;
+            this.Name = "MainForm";
+            this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
+            this.Text = "QSP Code Analyzer";
+            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);
+            this.Load += new System.EventHandler(this.MainForm_Load);
+            this.Shown += new System.EventHandler(this.MainForm_Shown);
+            this.tabControl.ResumeLayout(false);
+            this.tabCheck.ResumeLayout(false);
+            this.tabCheck.PerformLayout();
+            this.tabOptions.ResumeLayout(false);
+            this.tabOptions.PerformLayout();
+            this.tabTranslate.ResumeLayout(false);
+            this.grpTranslateCsv.ResumeLayout(false);
+            this.grpTranslateCsv.PerformLayout();
+            this.grpCsvDelimiter.ResumeLayout(false);
+            this.grpCsvDelimiter.PerformLayout();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.TextBox edtFile;
+        private System.Windows.Forms.OpenFileDialog dlgOpen;
+        private System.Windows.Forms.Button btnBrowse;
+        private System.Windows.Forms.TextBox txtList1;
+        private System.Windows.Forms.TextBox txtList2;
+        private System.Windows.Forms.TextBox txtList3;
+        private System.Windows.Forms.Button btnTry1;
+        private System.Windows.Forms.Button btnTry2;
+        private System.Windows.Forms.Button btnTry3;
+        private System.Windows.Forms.TextBox txtStatus;
+        private System.Windows.Forms.TabControl tabControl;
+        private System.Windows.Forms.TabPage tabCheck;
+        private System.Windows.Forms.TabPage tabOptions;
+        private System.Windows.Forms.CheckBox chkVariableCalls;
+        private System.Windows.Forms.TextBox txtVariableNames;
+        private System.Windows.Forms.Button btnReset;
+        private System.Windows.Forms.Label lblSortHeader;
+        private System.Windows.Forms.CheckBox chkSortLocations;
+        private System.Windows.Forms.CheckBox chkSortObjects;
+        private System.Windows.Forms.CheckBox chkSortVariables;
+        private System.Windows.Forms.Button btnReload;
+        private System.Windows.Forms.Label lblSystemVariables;
+        private System.Windows.Forms.TextBox txtSystemVariables;
+        private System.Windows.Forms.CheckBox chkAero;
+        private System.Windows.Forms.TextBox txtSystemAeroVars;
+        private System.Windows.Forms.Button btnTry4;
+        private System.Windows.Forms.CheckBox chkActions;
+        private System.Windows.Forms.TabPage tabTranslate;
+        private System.Windows.Forms.GroupBox grpCsvDelimiter;
+        private System.Windows.Forms.RadioButton radComma;
+        private System.Windows.Forms.RadioButton radSemicolon;
+        private System.Windows.Forms.Button btnExportCsv;
+        private System.Windows.Forms.TextBox edtSuffixCsv;
+        private System.Windows.Forms.Button btnTranslateFromCsv;
+        private System.Windows.Forms.Label lblSuffixCsv;
+        private System.Windows.Forms.CheckBox chkIgnoreEmptyTranslationsCsv;
+        private System.Windows.Forms.CheckBox chkCurlyParse;
+        private System.Windows.Forms.GroupBox grpTranslateCsv;
+        private System.Windows.Forms.Button btnBeautify;
+        private System.Windows.Forms.ProgressBar progressBar1;
+        private System.Windows.Forms.Button btnCancel;
+    }
+}
+

+ 591 - 0
QSP/qsp-analyser/QSP_Analyser/MainForm.cs

@@ -0,0 +1,591 @@
+using System;
+using System.Collections.Generic;
+using System.Collections;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Windows.Forms;
+using System.IO;
+using System.Threading;
+
+namespace Analyser
+{
+    public partial class MainForm : Form
+    {
+        //Глобальные переменные II
+        QSPGameCode game;
+
+
+        //Глобальные переменные
+        ArrayList ObjectsAdded;
+        ArrayList ObjectsDeleted;
+
+        bool inited = false;
+        string logText = "";
+        static BackgroundWorker _bw;
+
+        public MainForm()
+        {
+            InitializeComponent();
+            _bw = new BackgroundWorker
+            {
+                WorkerReportsProgress = true,
+                WorkerSupportsCancellation = true
+            };
+            _bw.DoWork += bw_DoWork;
+            _bw.ProgressChanged += bw_ProgressChanged;
+            _bw.RunWorkerCompleted += bw_RunWorkerCompleted;
+        }
+
+        private void btnBrowse_Click(object sender, EventArgs e)
+        {
+            //выбираем файл
+            if (dlgOpen.ShowDialog() == DialogResult.OK)
+            {
+                Properties.Settings.Default.filepath = dlgOpen.FileName;
+                txtStatus.Clear();
+                logText = "";
+                ClearMains();
+                ParseFile();
+            }
+        }
+
+        private delegate void PrintErrorsDelegate();
+        private void PrintErrors()
+        {
+
+            if (this.InvokeRequired)
+            {
+                // Pass the same function to BeginInvoke,
+                // but the call would come on the correct
+                // thread and InvokeRequired will be false.
+                this.BeginInvoke(new PrintErrorsDelegate(PrintErrors));
+
+                return;
+            }
+            //Выводим ошибки и ворнинги
+            //Log("Строка #" + Convert.ToString(game.GetErrorLine()) + ": " + game.GetError());
+            Log("No of errors: " + Common.GetErrorsCount() + ", warnings: " + Common.GetWarningsCount());
+            List<Common.QspError> errors = Common.GetErrors();
+            foreach (Common.QspError error in errors)
+            {
+                int err_line = game.GetLocation(error.locationName).GetLine() + error.line;
+                string errorMessage = "Location \"" + error.locationName + "\", Line #" + Convert.ToString(err_line) + " : " + error.text;
+                if (error.isError)
+                {
+                    Log("Error, " + errorMessage);
+                }
+                else
+                {
+                    Log("Warning, " + errorMessage);
+                }
+            }
+            PrintLog();
+        }
+
+        private void bw_DoWork(object sender, DoWorkEventArgs e)
+        {
+            //Устанаваливаем настройки парсера
+            List<string> systemVars = new List<string>(txtSystemVariables.Lines);
+            if (chkAero.Checked)
+                systemVars.AddRange(txtSystemAeroVars.Lines);
+            Common.SetConfig(new List<string>(txtVariableNames.Lines), systemVars, chkCurlyParse.Checked);
+            if (CheckForFile(edtFile.Text, true))
+            {
+                game.ParseGame(edtFile.Text, sender, e);
+                if (!e.Cancel)
+                { 
+                    this.Log("The file was read successfully");
+                    this.PrintLog();
+                }
+            }
+            else
+            {
+                this.Log("File was not read.");
+                PrintLog();
+            }
+        }
+
+        private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
+        {
+
+            this.PrintErrors();
+            Common.ClearNonGameErrors();
+            this.PrintLog();
+        }
+
+        private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
+        {
+            progressBar1.Value = e.ProgressPercentage;
+        }
+
+
+        private void ParseFile()
+        {
+            Log("Trying to read the file ...");
+            PrintLog();
+            _bw.RunWorkerAsync();
+
+        }
+
+        private void btnReset_Click(object sender, EventArgs e)
+        {
+            Analyser.Properties.Settings.Default.Reset();
+        }
+
+        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            Analyser.Properties.Settings.Default.Save();
+        }
+
+        private void MainForm_Load(object sender, EventArgs e)
+        {
+            this.Text += "   v " + System.Windows.Forms.Application.ProductVersion;
+        }
+
+        public void Log(string line)
+        {
+            logText += line + Environment.NewLine;
+        }
+
+        private delegate void PrintLogDelegate();
+        private void PrintLog()
+        {
+            if (this.InvokeRequired)
+            {
+                // Pass the same function to BeginInvoke,
+                // but the call would come on the correct
+                // thread and InvokeRequired will be false.
+                this.BeginInvoke(new PrintLogDelegate(PrintLog));
+
+                return;
+            }
+            txtStatus.Text = logText;
+        }
+
+        private void ClearMains()
+        {
+            txtList1.Clear();
+            txtList2.Clear();
+            txtList3.Clear();
+        }
+
+        //Выводим список значений в textbox, перед списком выводим заголовок
+        private void PrintArray(Control textbox, ArrayList val, string header)
+        {
+            if (textbox.Text.Length > 0)
+                textbox.Text += Environment.NewLine;
+            if (header.Length > 0)
+                textbox.Text += "[" + header + "]" + Environment.NewLine;
+            string s = String.Join(Environment.NewLine, (string[])val.ToArray(typeof(string)));
+            textbox.Text += s;
+        }
+
+        private ArrayList SubstractArray(ArrayList search_in, ArrayList search_for)
+        {
+            ArrayList res = new ArrayList();
+            string tosearch = Environment.NewLine + String.Join(Environment.NewLine, (string[])search_in.ToArray(typeof(string))) + Environment.NewLine;
+            tosearch = tosearch.ToUpper();
+            foreach (string titem in search_for)
+            {
+                if (!tosearch.Contains(Environment.NewLine + titem.ToUpper() + Environment.NewLine))
+                    res.Add(titem);
+            }
+            return res;
+        }
+
+        private bool CheckForFile(string filename, bool silent)
+        {
+            if (filename != "")
+            {
+                if (File.Exists(filename))
+                {
+                    return true;
+                }
+                else
+                {
+                    if (!silent)
+                        MessageBox.Show("Input file was not found!");
+                }
+            }
+            else
+            {
+                if (!silent)
+                    MessageBox.Show("Select input file!");
+            }
+            return false;
+        }
+
+        private void SortArray(ArrayList arr)
+        {
+            string[] tarr = (string[])arr.ToArray(typeof(string));
+            Array.Sort(tarr);
+            arr.Clear();
+            arr.AddRange(tarr);
+        }
+
+        //************************************************************
+        //************************************************************
+        //************************************************************
+
+//Локации
+        private void btnTry1_Click(object sender, EventArgs e)
+        {
+            ClearMains();
+
+            ArrayList LocationsDefined = new ArrayList();
+            ArrayList LocationsReferenced = new ArrayList();
+            ArrayList LocationsUnDefined = new ArrayList();
+            ArrayList LocationsUnReferenced = new ArrayList();
+
+            foreach (Common.QspLocationLink loc in Common.locationLinks)
+            {
+                if (loc.LocationExists)
+                    LocationsDefined.Add(loc.LocationName);
+                if (loc.LocationCalled)
+                    LocationsReferenced.Add(loc.LocationName);
+                if (!loc.LocationExists)
+                    LocationsUnDefined.Add(loc.LocationName);
+                if (!loc.LocationCalled)
+                    LocationsUnReferenced.Add(loc.LocationName);
+            }
+
+            if (chkSortLocations.Checked)
+            {
+                SortArray(LocationsDefined);
+                SortArray(LocationsReferenced);
+                SortArray(LocationsUnDefined);
+                SortArray(LocationsUnReferenced);
+            }
+
+            Log("We process the names of locations ...");
+            PrintArray(txtList1, LocationsDefined, "Existing locations");
+            Log("Added locations: " + LocationsDefined.Count.ToString());
+
+            Log("We process the reference to locations...");
+            PrintArray(txtList2, LocationsReferenced, "References to locations");
+            Log("Added reference to location: " + LocationsReferenced.Count.ToString());
+
+            Log("We begin to search for incorrect links ...");
+            PrintArray(txtList3, LocationsUnDefined, "Incorrect links");
+            Log("Found incorrect links: " + LocationsUnDefined.Count.ToString());
+
+            Log("We begin to search for lost locations - those for which there are no references ...");
+            PrintArray(txtList3, LocationsUnReferenced, "Lost locations");
+            Log("Found lost locations: " + LocationsUnReferenced.Count.ToString());
+            
+            PrintLog();
+        }
+
+//Переменные
+        private void btnTry2_Click(object sender, EventArgs e)
+        {
+            ClearMains();
+
+            ArrayList TextVars = new ArrayList();
+            ArrayList NumericVars = new ArrayList();
+            ArrayList TextVars_unassigned = new ArrayList();
+            ArrayList NumericVars_unassigned = new ArrayList();
+            ArrayList TextVars_unused = new ArrayList();
+            ArrayList NumericVars_unused = new ArrayList();
+
+            Log("Search for variables ...");
+
+            foreach (Common.QspVariable var in Common.vars)
+            {
+                if (var.IsString)
+                {
+                    if (!var.Assigned)
+                        TextVars_unassigned.Add(var.Name);
+                    if (!var.Used)
+                        TextVars_unused.Add(var.Name);
+                    TextVars.Add(var.Name);
+                }
+                else
+                {
+                    if (!var.Assigned)
+                        NumericVars_unassigned.Add(var.Name);
+                    if (!var.Used)
+                        NumericVars_unused.Add(var.Name);
+                    NumericVars.Add(var.Name);
+                }
+            }
+
+            if (chkSortVariables.Checked)
+            {
+                SortArray(TextVars);
+                SortArray(NumericVars);
+            }
+            PrintArray(txtList1, TextVars, "String variables");
+            PrintArray(txtList2, NumericVars, "Numeric variables");
+
+            Log("Added variables: " + Common.vars.Count.ToString());
+            
+            if (chkSortVariables.Checked)
+                SortArray(TextVars_unassigned);
+            PrintArray(txtList3, TextVars_unassigned, "no init variables:");
+            Log("Found using of uninitialized text variables: " + TextVars_unassigned.Count.ToString());
+            if (chkSortVariables.Checked)
+                SortArray(NumericVars_unassigned);
+            PrintArray(txtList3, NumericVars_unassigned, "");
+            Log("Found using of uninitialized numeric variables: " + NumericVars_unassigned.Count.ToString());
+
+            if (chkSortVariables.Checked)
+                SortArray(TextVars_unused);
+            PrintArray(txtList3, TextVars_unused, "Unused variables:");
+            Log("Found unused string variables: " + TextVars_unused.Count.ToString());
+            if (chkSortVariables.Checked)
+                SortArray(NumericVars_unused);
+            PrintArray(txtList3, NumericVars_unused, "");
+            Log("Found unused numeric variables: " + NumericVars_unused.Count.ToString());
+
+            PrintLog();
+        }
+
+//Предметы
+        private void btnTry3_Click(object sender, EventArgs e)
+        {
+            ClearMains();
+
+            ArrayList ObjectsAdded = new ArrayList();
+            ArrayList ObjectsDeleted = new ArrayList();
+            ArrayList ObjectsUnDefined = new ArrayList();
+            ArrayList ObjectsLost = new ArrayList();
+
+            foreach (Common.QspObj obj in Common.objects)
+            {
+                if (obj.Added)
+                    ObjectsAdded.Add(obj.Name);
+                if (obj.Removed)
+                    ObjectsDeleted.Add(obj.Name);
+                if (!obj.Added)
+                    ObjectsUnDefined.Add(obj.Name);
+                if (!obj.Removed)
+                    ObjectsLost.Add(obj.Name);
+            }
+
+            if (chkSortObjects.Checked)
+            {
+                SortArray(ObjectsAdded);
+                SortArray(ObjectsDeleted);
+                SortArray(ObjectsUnDefined);
+                SortArray(ObjectsLost);
+            }
+
+            Log("Search of items...");
+            PrintArray(txtList1, ObjectsAdded, "Added items");
+            PrintArray(txtList2, ObjectsDeleted, "Remove item");
+            Log("Items adding: " + ObjectsAdded.Count.ToString());
+            Log("Items removing: " + ObjectsDeleted.Count.ToString());
+
+            Log("Search of nonexisting items...");
+            PrintArray(txtList3, ObjectsUnDefined, "Invalid deletion");
+            Log("Found invalid deletions: " + ObjectsUnDefined.Count.ToString());
+
+            Log("Looking for lost items - those that are not deleted during the game ...");
+            PrintArray(txtList3, ObjectsLost, "Lost items");
+            Log("Lost items found: " + ObjectsLost.Count.ToString());
+
+            PrintLog();
+        }
+
+//Действия
+        private void btnTry4_Click(object sender, EventArgs e)
+        {
+            ClearMains();
+
+            ArrayList ActsAdded = new ArrayList();
+            ArrayList ActsDeleted = new ArrayList();
+            ArrayList ActsUnDefined = new ArrayList();
+
+            foreach (Common.QspAct act in Common.acts)
+            {
+                if (act.Added)
+                    ActsAdded.Add(act.Name);
+                if (act.Removed)
+                    ActsDeleted.Add(act.Name);
+                if (!act.Added)
+                    ActsUnDefined.Add(act.Name);
+            }
+
+            if (chkSortObjects.Checked)
+            {
+                SortArray(ActsAdded);
+                SortArray(ActsDeleted);
+                SortArray(ActsUnDefined);
+            }
+
+            Log("Search for actions...");
+            PrintArray(txtList1, ActsAdded, "Add an action");
+            PrintArray(txtList2, ActsDeleted, "Remove an action");
+            Log("Added action: " + ActsAdded.Count.ToString());
+            Log("Removed action: " + ActsDeleted.Count.ToString());
+
+            Log("We begin to search for deletion of nonexistent actions...");
+            PrintArray(txtList3, ActsUnDefined, "Invalid deletion");
+            Log("Invalid deletions found: " + ActsUnDefined.Count.ToString());
+
+            PrintLog();
+        }
+
+        //************************************************************
+        //************************************************************
+        //************************************************************
+
+        private void btnReload_Click(object sender, EventArgs e)
+        {
+            txtStatus.Clear();
+            logText = "";
+            ClearMains();
+            ParseFile();
+        }
+
+        private void setBindingContext(Control ctrl)
+        {
+            ctrl.Visible = true;
+            if (ctrl.HasChildren)
+                foreach (Control child in ctrl.Controls)
+                    setBindingContext(child);
+        }
+
+        private void MainForm_Shown(object sender, EventArgs e)
+        {
+            if (!inited)
+            {
+                setBindingContext(this);
+                btnBrowse.Select();
+
+
+                game = new QSPGameCode();
+                ParseFile();
+
+
+                ObjectsDeleted = new ArrayList();
+                ObjectsAdded = new ArrayList();
+                inited = true;
+            }
+        }
+
+        private void PrintNonGameErrors()
+        {
+            List<Common.QspError> errors = Common.GetErrors();
+            foreach (Common.QspError error in errors)
+            {
+                if (error.isError && (error.line == Common.INVALID_INDEX))
+                {
+                    MessageBox.Show("Error: " + error.text);
+                }
+            }
+            Common.ClearNonGameErrors();
+        }
+
+        private void btnExportCsv_Click(object sender, EventArgs e)
+        {
+            //Делаем экспорт текста в csv
+            string FileName = edtFile.Text;
+            if (CheckForFile(FileName, false))
+            {
+                if (Common.GetErrorsCount() > 0)
+                {
+                    MessageBox.Show("There are syntax errors in the file, export is not possible!");
+                    return;
+                }
+
+                edtFile.Enabled = false;
+                btnBrowse.Enabled = false;
+
+                bool success = false;
+                if (radComma.Checked)
+                {
+                    success = Common.ExportToCsv(FileName, ",");
+                }
+                else
+                {
+                    success = Common.ExportToCsv(FileName, ";");
+                }
+                if (!success)
+                {
+                    PrintNonGameErrors();
+                }
+
+                edtFile.Enabled = true;
+                btnBrowse.Enabled = true;
+            }
+        }
+
+        private void btnTranslateFromCsv_Click(object sender, EventArgs e)
+        {
+            //Делаем перевод текста на основе csv
+            string FileName = edtFile.Text;
+            if (CheckForFile(FileName, false))
+            {
+                if (Common.GetErrorsCount() > 0)
+                {
+                    MessageBox.Show("There are syntax errors in the file, export is not possible!");
+                    return;
+                }
+
+                string CsvFile = Common.GenerateCsvName(FileName);
+                if (!CheckForFile(FileName, true))
+                {
+                    MessageBox.Show("CSV file was not found!");
+                }
+
+                if (edtSuffixCsv.Text.Trim(Common.WhiteSpace).Length == 0)
+                {
+                    MessageBox.Show("Enter an extension of the conversion file.");
+                }
+
+                edtFile.Enabled = false;
+                btnBrowse.Enabled = false;
+
+                bool IgnoreEmptyTranslations = chkIgnoreEmptyTranslationsCsv.Checked;
+                bool success = false;
+                if (radComma.Checked)
+                {
+                    success = Common.TranslateFromCsv(FileName, edtSuffixCsv.Text, IgnoreEmptyTranslations, ",");
+                }
+                else
+                {
+                    success = Common.TranslateFromCsv(FileName, edtSuffixCsv.Text, IgnoreEmptyTranslations, ";");
+                }
+                if (!success)
+                {
+                    PrintNonGameErrors();
+                }
+
+                edtFile.Enabled = true;
+                btnBrowse.Enabled = true;
+            }
+        }
+
+        private void btnBeautify_Click(object sender, EventArgs e)
+        {
+            string FileName = edtFile.Text;
+            if (CheckForFile(FileName, false))
+            {
+                edtFile.Enabled = false;
+                btnBrowse.Enabled = false;
+
+                bool success = false;
+                success = game.Beautify(FileName);
+                if (!success)
+                {
+                    PrintNonGameErrors();
+                }
+
+                edtFile.Enabled = true;
+                btnBrowse.Enabled = true;
+            }
+        }
+
+        private void btnCancel_Click(object sender, EventArgs e)
+        {
+            _bw.CancelAsync();
+            Log("Cancelled loading of file.");
+            PrintLog();
+        }
+    }
+}

+ 123 - 0
QSP/qsp-analyser/QSP_Analyser/MainForm.resx

@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="dlgOpen.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>

+ 20 - 0
QSP/qsp-analyser/QSP_Analyser/Program.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+
+namespace Analyser
+{
+    static class Program
+    {
+        /// <summary>
+        /// The main entry point for the application.
+        /// </summary>
+        [STAThread]
+        static void Main()
+        {
+            Application.EnableVisualStyles();
+            Application.SetCompatibleTextRenderingDefault(false);
+            Application.Run(new MainForm());
+        }
+    }
+}

+ 36 - 0
QSP/qsp-analyser/QSP_Analyser/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("QSP Analyser")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Ghetto")]
+[assembly: AssemblyProduct("QSP Analyser")]
+[assembly: AssemblyCopyright("Copyright © Ghetto 2009")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("50a10fb9-5ab6-4d57-bbfa-ef9a0ef30b18")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.3.1.0")]

+ 63 - 0
QSP/qsp-analyser/QSP_Analyser/Properties/Resources.Designer.cs

@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Analyser.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Analyser.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+    }
+}

+ 117 - 0
QSP/qsp-analyser/QSP_Analyser/Properties/Resources.resx

@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>

+ 281 - 0
QSP/qsp-analyser/QSP_Analyser/Properties/Settings.Designer.cs

@@ -0,0 +1,281 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Analyser.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.1.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("")]
+        public string filepath {
+            get {
+                return ((string)(this["filepath"]));
+            }
+            set {
+                this["filepath"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool EnableVariableCalls {
+            get {
+                return ((bool)(this["EnableVariableCalls"]));
+            }
+            set {
+                this["EnableVariableCalls"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("$COUNTER\r\n$ONGLOAD\r\n$ONGSAVE\r\n$ONNEWLOC\r\n$ONACTSEL\r\n$ONOBJSEL\r\n$ONOBJADD\r\n$ONOBJD" +
+            "EL\r\n$USERCOM")]
+        public string VariableNames {
+            get {
+                return ((string)(this["VariableNames"]));
+            }
+            set {
+                this["VariableNames"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool EnableSortingLocations {
+            get {
+                return ((bool)(this["EnableSortingLocations"]));
+            }
+            set {
+                this["EnableSortingLocations"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool EnableSortingVariables {
+            get {
+                return ((bool)(this["EnableSortingVariables"]));
+            }
+            set {
+                this["EnableSortingVariables"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool EnableSortingObjects {
+            get {
+                return ((bool)(this["EnableSortingObjects"]));
+            }
+            set {
+                this["EnableSortingObjects"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("FSIZE\r\nFCOLOR\r\nBCOLOR\r\nLCOLOR\r\nUSEHTML\r\n$FNAME\r\n$BACKIMAGE\r\nNOSAVE\r\nDISABLESCROLL" +
+            "\r\nDISABLESUBEX\r\nDEBUG\r\n$COUNTER\r\n$ONGLOAD\r\n$ONGSAVE\r\n$ONNEWLOC\r\n$ONACTSEL\r\n$ONOB" +
+            "JSEL\r\n$ONOBJADD\r\n$ONOBJDEL\r\n$USERCOM\r\nARGS\r\n$ARGS\r\nRESULT\r\n$RESULT")]
+        public string SystemVariables {
+            get {
+                return ((string)(this["SystemVariables"]));
+            }
+            set {
+                this["SystemVariables"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool EnableAero {
+            get {
+                return ((bool)(this["EnableAero"]));
+            }
+            set {
+                this["EnableAero"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute(@"SCROLL_SPEED
+$UP_ARROW_IMAGE
+$DOWN_ARROW_IMAGE
+HIDE_SCROLL_ARROWS
+$STYLESHEET
+DISABLESHADE
+DISABLEAUTOREF
+$NEWLOC_EFFECT
+NEWLOC_EFFECT_TIME
+NEWLOC_EFFECT_SEQ
+$TOPIMAGE
+INTEGRATED_ACTIONS
+MAINDESC_X
+MAINDESC_Y
+MAINDESC_W
+MAINDESC_H
+$MAIN_FORMAT
+$MAINDESC_BACKIMAGE
+STATDESC_X
+STATDESC_Y
+STATDESC_W
+STATDESC_H
+$STAT_FORMAT
+$STATDESC_BACKIMAGE
+ACTIONS_X
+ACTIONS_Y
+ACTIONS_W
+ACTIONS_H
+$ACTION_FORMAT
+$SEL_ACTION_FORMAT
+$ACTIONS_BACKIMAGE
+OBJECTS_X
+OBJECTS_Y
+OBJECTS_W
+OBJECTS_H
+$OBJECT_FORMAT
+$SEL_OBJECT_FORMAT
+$OBJECTS_BACKIMAGE
+USERINPUT_X
+USERINPUT_Y
+USERINPUT_W
+USERINPUT_H
+VIEW_X
+VIEW_Y
+VIEW_W
+VIEW_H
+$VIEW_EFFECT
+VIEW_EFFECT_TIME
+ALWAYS_SHOW_VIEW
+$INPUT_BACKIMAGE
+INPUT_X
+INPUT_Y
+$INPUT_FORMAT
+INPUT_TEXT_X
+INPUT_TEXT_Y
+INPUT_TEXT_W
+INPUT_TEXT_H
+INPUT_BAR_X
+INPUT_BAR_Y
+INPUT_BAR_W
+INPUT_BAR_H
+$INPUT_OK_IMAGE
+INPUT_OK_X
+INPUT_OK_Y
+$INPUT_CANCEL_IMAGE
+INPUT_CANCEL_X
+INPUT_CANCEL_Y
+$INPUT_EFFECT
+INPUT_EFFECT_TIME
+$MSG_BACKIMAGE
+MSG_X
+MSG_Y
+$MSG_FORMAT
+MSG_TEXT_X
+MSG_TEXT_Y
+MSG_TEXT_W
+MSG_TEXT_H
+$MSG_OK_IMAGE
+MSG_OK_X
+MSG_OK_Y
+$MSG_EFFECT
+MSG_EFFECT_TIME
+FIXED_SIZE_MENU
+MENU_PADDING
+MENU_BORDER
+MENU_BORDER_COLOR
+$MENU_BACKIMAGE
+MENU_X
+MENU_Y
+$MENU_FORMAT
+$SEL_MENU_FORMAT
+MENU_LIST_X
+MENU_LIST_Y
+MENU_LIST_W
+MENU_LIST_H
+$MENU_EFFECT
+MENU_EFFECT_TIME")]
+        public string AeroSystemVars {
+            get {
+                return ((string)(this["AeroSystemVars"]));
+            }
+            set {
+                this["AeroSystemVars"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool EnableSortingActions {
+            get {
+                return ((bool)(this["EnableSortingActions"]));
+            }
+            set {
+                this["EnableSortingActions"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("_tr")]
+        public string CsvTranslationSuffix {
+            get {
+                return ((string)(this["CsvTranslationSuffix"]));
+            }
+            set {
+                this["CsvTranslationSuffix"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool IgnoreEmptyTranslationsCsv {
+            get {
+                return ((bool)(this["IgnoreEmptyTranslationsCsv"]));
+            }
+            set {
+                this["IgnoreEmptyTranslationsCsv"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool EnableCurlyParsing {
+            get {
+                return ((bool)(this["EnableCurlyParsing"]));
+            }
+            set {
+                this["EnableCurlyParsing"] = value;
+            }
+        }
+    }
+}

+ 172 - 0
QSP/qsp-analyser/QSP_Analyser/Properties/Settings.settings

@@ -0,0 +1,172 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="Analyser.Properties" GeneratedClassName="Settings">
+  <Profiles />
+  <Settings>
+    <Setting Name="filepath" Type="System.String" Scope="User">
+      <Value Profile="(Default)" />
+    </Setting>
+    <Setting Name="EnableVariableCalls" Type="System.Boolean" Scope="User">
+      <Value Profile="(Default)">True</Value>
+    </Setting>
+    <Setting Name="VariableNames" Type="System.String" Scope="User">
+      <Value Profile="(Default)">$COUNTER
+$ONGLOAD
+$ONGSAVE
+$ONNEWLOC
+$ONACTSEL
+$ONOBJSEL
+$ONOBJADD
+$ONOBJDEL
+$USERCOM</Value>
+    </Setting>
+    <Setting Name="EnableSortingLocations" Type="System.Boolean" Scope="User">
+      <Value Profile="(Default)">True</Value>
+    </Setting>
+    <Setting Name="EnableSortingVariables" Type="System.Boolean" Scope="User">
+      <Value Profile="(Default)">True</Value>
+    </Setting>
+    <Setting Name="EnableSortingObjects" Type="System.Boolean" Scope="User">
+      <Value Profile="(Default)">True</Value>
+    </Setting>
+    <Setting Name="SystemVariables" Type="System.String" Scope="User">
+      <Value Profile="(Default)">FSIZE
+FCOLOR
+BCOLOR
+LCOLOR
+USEHTML
+$FNAME
+$BACKIMAGE
+NOSAVE
+DISABLESCROLL
+DISABLESUBEX
+DEBUG
+$COUNTER
+$ONGLOAD
+$ONGSAVE
+$ONNEWLOC
+$ONACTSEL
+$ONOBJSEL
+$ONOBJADD
+$ONOBJDEL
+$USERCOM
+ARGS
+$ARGS
+RESULT
+$RESULT</Value>
+    </Setting>
+    <Setting Name="EnableAero" Type="System.Boolean" Scope="User">
+      <Value Profile="(Default)">True</Value>
+    </Setting>
+    <Setting Name="AeroSystemVars" Type="System.String" Scope="User">
+      <Value Profile="(Default)">SCROLL_SPEED
+$UP_ARROW_IMAGE
+$DOWN_ARROW_IMAGE
+HIDE_SCROLL_ARROWS
+$STYLESHEET
+DISABLESHADE
+DISABLEAUTOREF
+$NEWLOC_EFFECT
+NEWLOC_EFFECT_TIME
+NEWLOC_EFFECT_SEQ
+$TOPIMAGE
+INTEGRATED_ACTIONS
+MAINDESC_X
+MAINDESC_Y
+MAINDESC_W
+MAINDESC_H
+$MAIN_FORMAT
+$MAINDESC_BACKIMAGE
+STATDESC_X
+STATDESC_Y
+STATDESC_W
+STATDESC_H
+$STAT_FORMAT
+$STATDESC_BACKIMAGE
+ACTIONS_X
+ACTIONS_Y
+ACTIONS_W
+ACTIONS_H
+$ACTION_FORMAT
+$SEL_ACTION_FORMAT
+$ACTIONS_BACKIMAGE
+OBJECTS_X
+OBJECTS_Y
+OBJECTS_W
+OBJECTS_H
+$OBJECT_FORMAT
+$SEL_OBJECT_FORMAT
+$OBJECTS_BACKIMAGE
+USERINPUT_X
+USERINPUT_Y
+USERINPUT_W
+USERINPUT_H
+VIEW_X
+VIEW_Y
+VIEW_W
+VIEW_H
+$VIEW_EFFECT
+VIEW_EFFECT_TIME
+ALWAYS_SHOW_VIEW
+$INPUT_BACKIMAGE
+INPUT_X
+INPUT_Y
+$INPUT_FORMAT
+INPUT_TEXT_X
+INPUT_TEXT_Y
+INPUT_TEXT_W
+INPUT_TEXT_H
+INPUT_BAR_X
+INPUT_BAR_Y
+INPUT_BAR_W
+INPUT_BAR_H
+$INPUT_OK_IMAGE
+INPUT_OK_X
+INPUT_OK_Y
+$INPUT_CANCEL_IMAGE
+INPUT_CANCEL_X
+INPUT_CANCEL_Y
+$INPUT_EFFECT
+INPUT_EFFECT_TIME
+$MSG_BACKIMAGE
+MSG_X
+MSG_Y
+$MSG_FORMAT
+MSG_TEXT_X
+MSG_TEXT_Y
+MSG_TEXT_W
+MSG_TEXT_H
+$MSG_OK_IMAGE
+MSG_OK_X
+MSG_OK_Y
+$MSG_EFFECT
+MSG_EFFECT_TIME
+FIXED_SIZE_MENU
+MENU_PADDING
+MENU_BORDER
+MENU_BORDER_COLOR
+$MENU_BACKIMAGE
+MENU_X
+MENU_Y
+$MENU_FORMAT
+$SEL_MENU_FORMAT
+MENU_LIST_X
+MENU_LIST_Y
+MENU_LIST_W
+MENU_LIST_H
+$MENU_EFFECT
+MENU_EFFECT_TIME</Value>
+    </Setting>
+    <Setting Name="EnableSortingActions" Type="System.Boolean" Scope="User">
+      <Value Profile="(Default)">True</Value>
+    </Setting>
+    <Setting Name="CsvTranslationSuffix" Type="System.String" Scope="User">
+      <Value Profile="(Default)">_tr</Value>
+    </Setting>
+    <Setting Name="IgnoreEmptyTranslationsCsv" Type="System.Boolean" Scope="User">
+      <Value Profile="(Default)">True</Value>
+    </Setting>
+    <Setting Name="EnableCurlyParsing" Type="System.Boolean" Scope="User">
+      <Value Profile="(Default)">True</Value>
+    </Setting>
+  </Settings>
+</SettingsFile>

+ 26 - 0
QSP/qsp-analyser/QSP_Analyser/Properties/app.manifest

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <assemblyIdentity version="1.0.0.0" name="MyApplication.app" />
+  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+    <security>
+      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
+        <!-- UAC Manifest Options
+            If you want to change the Windows User Account Control level replace the 
+            requestedExecutionLevel node with one of the following.
+
+        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
+        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
+        <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />
+
+            If you want to utilize File and Registry Virtualization for backward 
+            compatibility then delete the requestedExecutionLevel node.
+        -->
+        <requestedExecutionLevel level="asInvoker" uiAccess="false" />
+      </requestedPrivileges>
+      <applicationRequestMinimum>
+        <PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" />
+        <defaultAssemblyRequest permissionSetReference="Custom" />
+      </applicationRequestMinimum>
+    </security>
+  </trustInfo>
+</asmv1:assembly>

+ 2244 - 0
QSP/qsp-analyser/QSP_Analyser/QSPGameCode.cs

@@ -0,0 +1,2244 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.ComponentModel;
+
+namespace Analyser
+{
+    public class Location : Common
+    {
+        QSPGameCode m_gamecode;
+        string m_name;
+        int m_line;
+        bool m_start; //Стартовая локация
+        List<string> location_codeline_text;
+        Dictionary<int, int> location_codeline_level;
+
+        int currentLine;
+        bool currentRoot;
+
+        enum ControlBlockType
+        {
+            None,
+            SL_If,
+            SL_Else,
+            SL_Act,
+            ML_If,
+            ML_Else,
+            ML_Act,
+            IfCondition,
+            ElseIfCondition,
+            ActCondition
+        }
+        
+        struct ControlLine
+        {
+            public ControlBlockType controlBlock;
+            public int line;
+        }
+
+        public Location(QSPGameCode code, string name, int line, bool start)
+        {
+            m_gamecode = code;
+            m_name = name;
+            m_line = line;
+            m_start = start;
+            location_codeline_text = null;
+            location_codeline_level = null;
+        }
+
+        public string GetName()
+        {
+            return m_name;
+        }
+
+        public int GetLine()
+        {
+            return m_line;
+        }
+
+        public int GetCodeLinesCount()
+        {
+            return location_codeline_text.Count;
+        }
+
+        public void GetCodeLine(int lineNum, ref string text, ref int level)
+        {
+            //Нужно для утилиты форматирования
+            int realNum = lineNum + 1;
+            text = location_codeline_text[lineNum];
+            if (location_codeline_level.ContainsKey(realNum))
+                level = location_codeline_level[realNum];
+            else
+                level = INVALID_INDEX;
+            return;
+        }
+
+        new void SubmitError(string text, int line)
+        {
+            if (currentRoot)
+                Common.SubmitError(text, line);
+            else
+                Common.SubmitError(text, currentLine);
+        }
+
+        new void SubmitWarning(string text, int line)
+        {
+            if (currentRoot)
+                Common.SubmitWarning(text, line);
+            else
+                Common.SubmitWarning(text, currentLine);
+        }
+
+        bool qspCompileExprPushOpCode(ref int[] opStack, ref int opSp, ref int[] argStack, ref int argSp, int opCode)
+        {
+            if ((opSp == QSP_STACKSIZE - 1) || (argSp == QSP_STACKSIZE - 1))
+            {
+                SubmitError("Quite complicated expression", currentLine);
+                return false;
+            }
+            opStack[++opSp] = opCode;
+            argStack[++argSp] = (opCode < (int)QspFunctionType.First_Function) ? qspOps[opCode].MinArgsCount : 0;
+            return true;
+        }
+
+        bool qspAppendToCompiled(ref int itemsCount)
+        {
+            if (itemsCount == QSP_MAXITEMS)
+            {
+                SubmitError("Quite many arguments in the expression", currentLine);
+                return false;
+            }
+            ++itemsCount;
+            return true;
+        }
+
+        public bool ParseLocation(List<string> code, bool root)
+        {
+            int quote = (int)QuoteType.None;
+            if (root)
+            {
+                currentRoot = true;
+                currentLine = 0;
+                location_codeline_text = new List<string>(code);
+                location_codeline_level = new Dictionary<int, int>();
+            }
+
+            //Склеиваем строки
+            List<int> lineIndexes = new List<int>();
+            List<string> escapedLines = new List<string>();
+            int linesCount = code.Count;
+            int oldLine = 0;
+            int curLine = 0;
+            int curlyLevel = 0;
+            string extraLine = "";
+            while (curLine < linesCount)
+            {
+                string line = code.ToArray()[curLine];
+                int pos = 0;
+                while (pos < line.Length)
+                {
+                    char c = line[pos];
+                    if (c == '\'')
+                    {
+                        //Апостроф
+                        if (quote == (int)QuoteType.None)
+                        {
+                            quote = (int)QuoteType.Single;
+                        }
+                        else if (quote == (int)QuoteType.Single)
+                        {
+                            if ((pos + 1 < line.Length) && (line[pos + 1] == '\''))
+                            {
+                                //Экранированный апостроф
+                                pos++;
+                            }
+                            else
+                            {
+                                quote = (int)QuoteType.None;
+                            }
+                        }
+                    }
+                    else if (c == '"')
+                    {
+                        //Кавычка
+                        if (quote == (int)QuoteType.None)
+                        {
+                            quote = (int)QuoteType.Double;
+                        }
+                        else if (quote == (int)QuoteType.Double)
+                        {
+                            if ((pos + 1 < line.Length) && (line[pos + 1] == '"'))
+                            {
+                                //Экранированная кавычка
+                                pos++;
+                            }
+                            else
+                            {
+                                quote = (int)QuoteType.None;
+                            }
+                        }
+                    }
+                    else if (quote == (int)QuoteType.None)
+                    {
+                        if (c == '{')
+                        {
+                            curlyLevel++;
+                        }
+                        else if (c == '}')
+                        {
+                            if (curlyLevel == 0)
+                            {
+                                SubmitError("Closing curly brace without opening one", oldLine + 1);
+                                return false;
+                            }
+                            curlyLevel--;
+                        }
+                    }
+                    pos++;
+                }
+
+                if ((curlyLevel > 0) || (quote != (int)QuoteType.None) || line.EndsWith(" _"))
+                {
+                    if (line.EndsWith(" _"))
+                        line = line.Substring(0, line.Length - 2);
+                    extraLine += line;
+                    if (curlyLevel > 0)
+                        extraLine += "\n";//Вставляем разделитель для строк, потом по нему "разобьем" строки
+                    if (curLine == linesCount - 1)
+                    {
+                        lineIndexes.Add(oldLine + 1);
+                        string escaped = extraLine + line;
+                        escapedLines.Add(escaped.Trim(WhiteSpace));
+                    }
+                }
+                else
+                {
+                    lineIndexes.Add(oldLine + 1);
+                    string escaped = extraLine + line;
+                    escapedLines.Add(escaped.Trim(WhiteSpace));
+                    oldLine = curLine + 1;
+                    extraLine = "";
+                }
+                curLine++;
+            }
+            //Проверка на незакрытые в конце локации многострочные строки
+            if (quote != (int)QuoteType.None)
+            {
+                SubmitError("Unclosed string", oldLine + 1);
+                return false;
+            }
+            //Проверка на незакрытые в конце локации фигурные скобки
+            if (curlyLevel > 0)
+            {
+                SubmitError("Unclosed curly bracket", oldLine + 1);
+                return false;
+            }
+
+            //TODO
+            // FOR
+            // перечисления asd|12|ddd
+
+            //Разбираем код
+
+            int lineNum = 0;
+            int linePlainNum = 0;
+            string block = "";
+            string quotedText = "";
+            int controlBlock = (int)ControlBlockType.None;
+            Stack<ControlLine> ControlStack = new Stack<ControlLine>();
+            List<string> blockGroup = new List<string>();
+            List<bool> blockInGroupIsText = new List<bool>();
+
+            int groupInnerCounter = 0;
+
+            bool blockStarted = false;
+            bool blockCompleted = false;
+            bool blockGroupStarted = false;
+            bool blockGroupCompleted = false;
+            bool quotedTextCompleted = false;
+
+            string rawText = "";
+            string debugText = "";
+            foreach (string line in escapedLines)
+            {
+                lineNum = lineIndexes[linePlainNum];
+                linePlainNum++;
+
+                int startIndentLevel = 0;
+                int endIndentLevel = 0;
+                if (currentRoot)
+                {
+                    currentLine = lineNum;
+                    //Вычисляем уровень вложенности(для утилиты форматирования кода)
+                    int stackSize = ControlStack.Count;
+                    if (stackSize > 0)
+                        startIndentLevel = stackSize;
+                }
+
+                int pos = 0;
+                int firstSymbolPos = INVALID_INDEX;
+                int blockStartPos = INVALID_INDEX;
+                int lastIfPos = INVALID_INDEX;
+                int lastActPos = INVALID_INDEX;
+                int bracketLevel = 0;
+
+                bool comment = false;
+                bool label = false;
+                string labelText = "";
+                bool singleBlockGroup = false;
+                
+                //Разбор строки
+                while (pos < line.Length)
+                {
+                    bool appendDelimiter = false;
+                    String delimiterToAppend = "";
+                    char c = line[pos];
+                    if ((c.ToString().IndexOfAny(WhiteSpace) != 0) && (firstSymbolPos == INVALID_INDEX))
+                    {
+                        firstSymbolPos = pos;
+                    }
+                    if (c == '\'')
+                    {
+                        //Апостроф
+                        if (quote == (int)QuoteType.None)
+                        {
+                            quote = (int)QuoteType.Single;
+
+                            quotedText = "";
+                            if (blockStarted && !comment)
+                                blockCompleted = true;
+
+                            //для отладки
+                            if (rawText.Length == 0)
+                                rawText += c;
+                            else
+                                rawText += Environment.NewLine + c;
+                        }
+                        else if (quote == (int)QuoteType.Single)
+                        {
+                            if ((pos + 1 < line.Length) && (line[pos + 1] == '\''))
+                            {
+                                //Экранированный апостроф
+                                pos++;
+                                quotedText += c;
+                            }
+                            else
+                            {
+                                quote = (int)QuoteType.None;
+                                if (!comment && !label)
+                                    quotedTextCompleted = true;
+                            }
+
+                            //для отладки
+                            rawText += c;
+                        }
+                        else
+                        {
+                            quotedText += c;
+
+                            //для отладки
+                            rawText += c;
+                        }
+                    }
+                    else if (c == '"')
+                    {
+                        //Кавычка
+                        if (quote == (int)QuoteType.None)
+                        {
+                            quote = (int)QuoteType.Double;
+
+                            quotedText = "";
+                            if (blockStarted && !comment)
+                                blockCompleted = true;
+
+                            //для отладки
+                            if (rawText.Length == 0)
+                                rawText += c;
+                            else
+                                rawText += Environment.NewLine + c;
+                        }
+                        else if (quote == (int)QuoteType.Double)
+                        {
+                            if ((pos + 1 < line.Length) && (line[pos + 1] == '"'))
+                            {
+                                //Экранированная кавычка
+                                pos++;
+                                quotedText += c;
+                            }
+                            else
+                            {
+                                quote = (int)QuoteType.None;
+                                if (!comment && !label)
+                                    quotedTextCompleted = true;
+                            }
+
+                            //для отладки
+                            rawText += c;
+                        }
+                        else
+                        {
+                            quotedText += c;
+
+                            //для отладки
+                            rawText += c;
+                        }
+                    }
+                    else if (comment)
+                    {
+                        //Здесь игнорируем все до самого конца строки, но учитываем переводы строк внутри кавычек и апострофов.
+                    }
+                    else if (quote != (int)QuoteType.None)
+                    {
+                        //Строка текста внутри кавычек или апострофов
+                        quotedText += c;
+
+                        //для отладки
+                        rawText += c;
+                    }
+                    else if (c == '{')
+                    {
+                        if (blockStarted && !comment)
+                            blockCompleted = true;
+
+                        //Записываем содержимое фигурных скобок
+                        string curlyText = "";
+                        curlyLevel = 1;
+                        pos++;
+                        int curlyQuote = (int)QuoteType.None;
+                        while (pos < line.Length)
+                        {
+                            char c2 = line[pos];
+
+                            if (c2 == '\'')
+                            {
+                                //Апостроф
+                                if (curlyQuote == (int)QuoteType.None)
+                                {
+                                    curlyQuote = (int)QuoteType.Single;
+                                }
+                                else if (curlyQuote == (int)QuoteType.Single)
+                                {
+                                    if ((pos + 1 < line.Length) && (line[pos + 1] == '\''))
+                                    {
+                                        //Экранированный апостроф
+                                        curlyText += c2;
+                                        pos++;
+                                        c2 = line[pos];
+                                    }
+                                    else
+                                    {
+                                        curlyQuote = (int)QuoteType.None;
+                                    }
+                                }
+                            }
+                            else if (c2 == '"')
+                            {
+                                //Кавычка
+                                if (curlyQuote == (int)QuoteType.None)
+                                {
+                                    curlyQuote = (int)QuoteType.Double;
+                                }
+                                else if (curlyQuote == (int)QuoteType.Double)
+                                {
+                                    if ((pos + 1 < line.Length) && (line[pos + 1] == '"'))
+                                    {
+                                        //Экранированная кавычка
+                                        curlyText += c2;
+                                        pos++;
+                                        c2 = line[pos];
+                                    }
+                                    else
+                                    {
+                                        curlyQuote = (int)QuoteType.None;
+                                    }
+                                }
+                            }
+                            else if (curlyQuote == (int)QuoteType.None)
+                            {
+                                if (c2 == '{')
+                                {
+                                    curlyLevel++;
+                                }
+                                else if (c2 == '}')
+                                {
+                                    curlyLevel--;
+                                    if (curlyLevel == 0)
+                                        break;
+                                }
+                            }
+                            curlyText += c2;
+                            pos++;
+                        }
+                        if (curlyLevel > 0)
+                        {
+                            SubmitError("Internal error of the analyzer - unclosed curly bracket \"{\"", currentLine);
+                            break;
+                        }
+
+                        if (curlyParsing)
+                        {
+                            //Парсим содержимое фигурных скобок
+                            List<string> curlyLines = new List<string>(curlyText.Split('\n'));
+                            currentRoot = false;
+                            ParseLocation(curlyLines, currentRoot);
+                            currentRoot = root;
+                            //Добавляем пустую "строку в кавычках", чтобы анализатор не ругался на отсутствие параметра
+                            quotedText = "";
+                        }
+                        else
+                        {
+                            quotedText = curlyText;
+                        }
+                        quotedTextCompleted = true;
+                    }
+                    else
+                    {
+                        //Обычные символы
+                        if (label)
+                        {
+                            if (c == '&')
+                            {
+                                if (labelText.Trim(WhiteSpace).Equals(":"))
+                                {
+                                    SubmitError("Empty label", lineNum);
+                                    return false;
+                                }
+                                if (quote != (int)QuoteType.None)
+                                {
+                                    SubmitError("Unclosed string in the label name", lineNum);
+                                    return false;
+                                }
+                                label = false;
+                            }
+                            else
+                            {
+                                labelText += c;
+                            }
+                        }
+                        else if ((c == ':') && ((controlBlock == (int)ControlBlockType.IfCondition) ||
+                                           (controlBlock == (int)ControlBlockType.ElseIfCondition)))
+                        {
+                            //Разбор условия
+                            if (blockStarted)
+                                blockCompleted = true;
+                            blockGroupCompleted = true;
+
+                            //Двоеточие после условия
+                            if ((pos == line.Length - 1))
+                            {
+                                //В конце строки - многострочный IF или ELSEIF
+                                if (firstSymbolPos == lastIfPos)
+                                {
+                                    if (controlBlock == (int)ControlBlockType.IfCondition)
+                                    {
+                                        ControlLine cline;
+                                        cline.line = lineNum;
+                                        cline.controlBlock = ControlBlockType.ML_If;
+                                        ControlStack.Push(cline);
+                                    }
+                                    else
+                                    {
+                                        ControlLine cline = ControlStack.Pop();
+                                        if (cline.controlBlock != ControlBlockType.ML_If)
+                                        {
+                                            SubmitError("ELSEIF without IF", lineNum);
+                                            return false;
+                                        }
+                                        cline.line = lineNum;
+                                        ControlStack.Push(cline);
+                                    }
+                                    controlBlock = (int)ControlBlockType.ML_If;
+                                }
+                                else
+                                {
+                                    if (controlBlock == (int)ControlBlockType.IfCondition)
+                                        SubmitError("Multiline IF should be placed at the beginning of the line", lineNum);
+                                    else
+                                        SubmitError("Multiline ELSEIF should be placed at the beginning of the line", lineNum);
+                                    return false;
+                                }
+                            }
+                            else if (controlBlock == (int)ControlBlockType.IfCondition)
+                            {
+                                //Строка не заканчивается - однострочный IF
+                                if (controlBlock == (int)ControlBlockType.IfCondition)
+                                {
+                                    ControlLine cline;
+                                    cline.line = lineNum;
+                                    cline.controlBlock = ControlBlockType.SL_If;
+                                    ControlStack.Push(cline);
+
+                                    controlBlock = (int)cline.controlBlock;
+                                    groupInnerCounter = 0;
+                                }
+                                else
+                                {
+                                    SubmitError("ELSEIF cannot be used in single line IF", lineNum);
+                                    return false;
+                                }
+                            }
+                            else
+                            {
+                                SubmitError("An operator cannot be placed after colon\":\" in multiline ELSEIF", lineNum);
+                                return false;
+                            }
+                        }
+                        else if ((c == ':') && (controlBlock == (int)ControlBlockType.ActCondition))
+                        {
+                            //Разбор аргумента
+                            if (blockStarted)
+                                blockCompleted = true;
+                            blockGroupCompleted = true;
+
+                            //Двоеточие после ACT
+                            if (pos == line.Length - 1)
+                            {
+                                //В конце строки - многострочный ACT
+                                if (firstSymbolPos == lastActPos)
+                                {
+                                    controlBlock = (int)ControlBlockType.ML_Act;
+                                    ControlLine cline;
+                                    cline.line = lineNum;
+                                    cline.controlBlock = ControlBlockType.ML_Act;
+                                    ControlStack.Push(cline);
+                                }
+                                else
+                                {
+                                    SubmitError("Multiline ACT should be placed at the beginning of the line", lineNum);
+                                    return false;
+                                }
+                            }
+                            else
+                            {
+                                //Строка не заканчивается - однострочный ACT
+                                controlBlock = (int)ControlBlockType.SL_Act;
+                                groupInnerCounter = 0;
+                            }
+                        }
+                        else if (!comment && (c == '!') && !blockGroupStarted && !blockStarted)
+                        {
+                            //Начало комментария
+                            comment = true;
+                        }
+                        else if ((c == ':') && (firstSymbolPos == pos))
+                        {
+                            //Начало метки
+                            label = true;
+                        }
+                        else if (c.ToString().IndexOfAny(Delimiters) == 0)
+                        {
+                            if ((c == '&') && (bracketLevel == 0))
+                            {
+                                if (controlBlock == (int)ControlBlockType.IfCondition)
+                                {
+                                    //В условии IF недопустимо использование "&" вне скобок
+                                    SubmitError("Redundant \"&\": perhaps should be \"AND\"", lineNum);
+                                    return false;
+                                }
+                                else if (controlBlock == (int)ControlBlockType.ActCondition)
+                                {
+                                    //В названии ACT недопустимо использование "&" вне скобок
+                                    SubmitError("Redundant \"&\"", lineNum);
+                                    return false;
+                                }
+                                else
+                                {
+                                    if (blockStarted)
+                                        blockCompleted = true;
+                                    if (blockGroupStarted)
+                                        blockGroupCompleted = true;
+                                    if (blockStarted && !blockGroupStarted)
+                                        singleBlockGroup = true;
+                                }
+                            }
+                            else if (blockStarted && (c == ' ') && StartOfMultiWordOperator(block))
+                            {
+                                //Составной оператор - DEL ACT, DEL OBJ
+                                block += c;
+                            }
+                            else if (blockStarted && (c == ' ') && (qspGetStatCode(block) == (int)QspStatementType.Close) &&
+                                     (line.Length > pos + 3) && line.Substring(pos + 1, 3).Equals("ALL", StringComparison.OrdinalIgnoreCase))
+                            {
+                                //CLOSE ALL
+                                block += c;
+                            }
+                            else if (!blockStarted && (c == '*'))
+                            {
+                                //Возможно, *PL, *P, *NL
+                                blockStarted = true;
+                                blockCompleted = false;
+                                block += c;
+                                blockStartPos = pos;
+                            }
+                            else if (!blockStarted && (c == '['))
+                            {
+                                //Квадратная скобка должна идти вплотную к имени массива
+                                SubmitError("A square bracket has to be placed just behind the name of the array, with no spaces", lineNum);
+                                return false;
+                            }
+                            else
+                            {
+                                //Самостоятельные знаки
+                                if (c == '(')
+                                {
+                                    bracketLevel++;
+                                }
+                                else if (c == ')')
+                                {
+                                    if (bracketLevel == 0)
+                                    {
+                                        SubmitError("Redundant bracket \")\"", lineNum);
+                                        return false;
+                                    }
+                                    bracketLevel--;
+                                }
+                                bool whiteSpace = c.ToString().IndexOfAny(WhiteSpace) == 0;
+
+                                //Особый учет для последовательностей >=, => и т.д.
+                                bool comparer = pos + 1 < line.Length;
+                                String cmp = "";
+                                if (comparer)
+                                {
+                                    cmp = line.Substring(pos, 2);
+                                    comparer = cmp.Equals("<=") || cmp.Equals(">=") || cmp.Equals("=>") || cmp.Equals("=<") || cmp.Equals("<>") ||
+                                               cmp.Equals("+=") || cmp.Equals("-=");
+                                }
+                                if (comparer)
+                                {
+                                    //<= >= => =< <> += -=
+                                    if (blockStarted)
+                                    {
+                                        appendDelimiter = true;
+                                        delimiterToAppend = cmp;
+                                    }
+                                    else
+                                    {
+                                        blockStarted = true;
+                                        blockStartPos = pos;
+                                        block = cmp;
+                                    }
+                                    blockCompleted = true;
+                                    pos++;
+                                }
+                                else if (blockStarted)
+                                {
+                                    blockCompleted = true;
+                                    if (!whiteSpace)
+                                    {
+                                        appendDelimiter = true;
+                                        delimiterToAppend += c;
+                                    }
+                                    else
+                                    {
+                                        //Обрабатываем END IF, END ACT
+                                        int blockCode = qspGetStatCode(block);
+                                        if (blockCode == (int)QspStatementType.End)
+                                        {
+                                            int nextPos = line.LastIndexOfAny(WhiteSpace, blockStartPos + block.Length) + 1;
+                                            if (nextPos < line.Length)
+                                            {
+                                                int delimPos = line.IndexOfAny(Delimiters, nextPos);
+                                                string nextWord = "";
+                                                if (delimPos == INVALID_INDEX)
+                                                    nextWord = line.Substring(nextPos);
+                                                else
+                                                    nextWord = line.Substring(nextPos, delimPos - nextPos);
+                                                int nextCode = qspGetStatCode(nextWord);
+                                                if ((nextCode == (int)QspStatementType.If) || (nextCode == (int)QspStatementType.Act))
+                                                {
+                                                    pos = nextPos + nextWord.Length - 1;
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                                else if (!whiteSpace)
+                                {
+                                    blockStarted = true;
+                                    blockCompleted = true;
+                                    blockStartPos = pos;
+                                    block += c;
+                                }
+                            }
+                        }
+                        else
+                        {
+                            //Просто буквы
+                            if (!blockStarted)
+                            {
+                                blockStarted = true;
+                                blockCompleted = false;
+                                blockStartPos = pos;
+                            }
+                            block += c;
+                        }
+                    }
+                    //Последний символ в строке
+                    if (blockStarted && (pos == line.Length - 1))
+                    {
+                        blockCompleted = true;
+                    }
+
+                    if (blockCompleted || quotedTextCompleted)
+                    {
+                        if (!quotedTextCompleted && (block.Length == 0))
+                        {
+                            SubmitError("Internal error of analyzer! Empty block!", lineNum);
+                            return false;
+                        }
+                        debugText += "[" + block + "] ";
+                        bool skip = false;
+                        int blockCode = qspGetStatCode(block);
+
+                        if (blockCode == (int)QspStatementType.If)
+                        {
+                            controlBlock = (int)ControlBlockType.IfCondition;
+                            debugText += "<IfCondition> ";
+                            lastIfPos = blockStartPos;
+                        }
+                        if (blockCode == (int)QspStatementType.Act)
+                        {
+                            controlBlock = (int)ControlBlockType.ActCondition;
+                            debugText += "<ActCondition> ";
+                            lastActPos = blockStartPos;
+                        }
+                        if (blockCode == (int)QspStatementType.ElseIf)
+                        {
+                            if (controlBlock == (int)ControlBlockType.ML_If)
+                            {
+                                controlBlock = (int)ControlBlockType.ElseIfCondition;
+                                debugText += "<ElseIfCondition> ";
+                                lastIfPos = blockStartPos;
+                            }
+                            else
+                            {
+                                SubmitError("ELSEIF без IF", lineNum);
+                                return false;
+                            }
+                        }
+                        if (blockCode == (int)QspStatementType.Else)
+                        {
+                            if (controlBlock == (int)ControlBlockType.ML_If)
+                            {
+                                if (firstSymbolPos == blockStartPos)
+                                {
+                                    if ((blockStartPos + block.Length == line.Length) || (line.Substring(blockStartPos + block.Length).Trim(WhiteSpace).Equals(":")))
+                                    {
+                                        controlBlock = (int)ControlBlockType.ML_Else;
+                                        
+                                        ControlStack.Pop();
+                                        ControlLine cline;
+                                        cline.controlBlock = ControlBlockType.ML_Else;
+                                        cline.line = lineNum;
+                                        ControlStack.Push(cline);
+                                    }
+                                    else
+                                    {
+                                        SubmitError("An operator cannot be placed after multiline ELSE", lineNum);
+                                        return false;
+                                    }
+                                }
+                                else
+                                {
+                                    SubmitError("Multiline ELSE should be at the beginning of the line", lineNum);
+                                    return false;
+                                }
+                            }
+                            else
+                            {
+                                if (controlBlock == (int)ControlBlockType.SL_Act)
+                                {
+                                    if (groupInnerCounter > 0)
+                                    {
+                                        if ((ControlStack.Peek().controlBlock == ControlBlockType.SL_If) && (ControlStack.Peek().line == lineNum))
+                                        {
+                                            if (blockGroupStarted)
+                                            {
+                                                blockGroupCompleted = true;
+                                            }
+                                        }
+                                        else
+                                        {
+                                            SubmitError("ELSE without IF", lineNum);
+                                            return false;
+                                        }
+                                    }
+                                    else
+                                    {
+                                        SubmitError("Invalid notation of single line ACT", lineNum);
+                                        return false;
+                                    }
+                                }
+                                else if (controlBlock == (int)ControlBlockType.SL_If)
+                                {
+                                    if (blockGroupStarted)
+                                    {
+                                        blockGroupCompleted = true;
+                                    }
+                                    else if (groupInnerCounter == 0)
+                                    {
+                                        SubmitError("After single line IF has to be any operators before ELSE", lineNum);
+                                        return false;
+                                    }
+                                }
+                                else
+                                {
+                                    SubmitError("ELSE without IF", lineNum);
+                                    return false;
+                                }
+                                //Это правильный ELSE
+                                if (blockStartPos + block.Length < line.Length)
+                                {
+                                    string restLine = line.Substring(blockStartPos + block.Length);
+                                    if (restLine.Trim(WhiteSpace).StartsWith(":"))
+                                    {
+                                        pos += restLine.IndexOf(':') + 1;
+                                    }
+                                }
+                                ControlStack.Pop();
+                                controlBlock = (int)ControlBlockType.SL_Else;
+                                groupInnerCounter = 0;
+                            }
+                            skip = true;
+                        }
+                        if (blockCode == (int)QspStatementType.End)
+                        {
+                            if (ControlStack.Count > 0)
+                            {
+                                ControlStack.Pop();
+                                if (ControlStack.Count > 0)
+                                {
+                                    ControlLine cline = ControlStack.Peek();
+                                    controlBlock = (int)cline.controlBlock;
+                                }
+                                else
+                                {
+                                    controlBlock = (int)ControlBlockType.None;
+                                }
+                            }
+                            else
+                            {
+                                SubmitError("Redundant END", lineNum);
+                                return false;
+                            }
+                            skip = true;
+                        }
+                        if (!skip)
+                        {
+                            if (!blockGroupStarted)
+                            {
+                                blockGroupStarted = true;
+                                groupInnerCounter++;
+                                if (singleBlockGroup)
+                                {
+                                    singleBlockGroup = false;
+                                    blockGroupCompleted = true;
+                                }
+                            }
+                            if (quotedTextCompleted)
+                            {
+                                blockGroup.Add(quotedText);
+                                blockInGroupIsText.Add(true);
+                                quotedTextCompleted = false;
+                            }
+                            else
+                            {
+                                if ((blockCode == (int)QspStatementType.Unknown) && (block.Length > 1))
+                                {
+                                    //Обрабатываем попытки "склеить" некоторые последовательности символов
+                                    string first = block.Substring(0, 1);
+                                    if (first.Equals("*"))
+                                    {
+                                        //Если была неудачная попытка прочесть *NL, *P, и т.д., "разделяем" блок на части
+                                        blockGroup.Add(first);
+                                        blockInGroupIsText.Add(false);
+                                        block = block.Substring(1);
+                                    }
+                                }
+                                blockGroup.Add(block);
+                                blockInGroupIsText.Add(false);
+                            }
+                            if (appendDelimiter)
+                            {
+                                blockGroup.Add(delimiterToAppend);
+                                blockInGroupIsText.Add(false);
+                            }
+                            if (blockGroupStarted && (pos == line.Length - 1))
+                            {
+                                blockGroupCompleted = true;
+                            }
+                        }
+                        block = "";
+                        blockCompleted = false;
+                        blockStarted = false;
+                    }
+                    if (blockGroupCompleted)
+                    {
+                        //Разбор аргументов
+                        if (blockGroup.Count == 0)
+                        {
+                            SubmitError("Internal error of the analyzer! Empty block!", lineNum);
+                            return false;
+                        }
+                        if (!CheckBlockGroup(blockGroup, blockInGroupIsText))
+                            return false;
+                        blockGroup.Clear();
+                        blockInGroupIsText.Clear();
+                        blockGroupStarted = false;
+                        blockGroupCompleted = false;
+                    }
+
+                    pos++;
+                }
+                
+                //Строка закончилась
+
+                if (bracketLevel>0)
+                {
+                    SubmitError("Redundant bracket \"(\"", lineNum);
+                    return false;
+                }
+                if (controlBlock == (int)ControlBlockType.IfCondition)
+                {
+                    SubmitError("IF without \":\"", lineNum);
+                    return false;
+                }
+                if (controlBlock == (int)ControlBlockType.ActCondition)
+                {
+                    SubmitError("ACT without \":\"", lineNum);
+                    return false;
+                }
+                if ((controlBlock == (int)ControlBlockType.SL_Act) || (controlBlock == (int)ControlBlockType.SL_If) || (controlBlock == (int)ControlBlockType.SL_Else))
+                {
+                    if (groupInnerCounter > 0)
+                    {
+                        while ((ControlStack.Count > 0) && (ControlStack.Peek().controlBlock == ControlBlockType.SL_If))
+                            ControlStack.Pop();
+                        if (ControlStack.Count > 0)
+                        {
+                            ControlLine cline = ControlStack.Peek();
+                            controlBlock = (int)cline.controlBlock;
+                        }
+                        else
+                        {
+                            controlBlock = (int)ControlBlockType.None;
+                        }
+                    }
+                    else if (controlBlock == (int)ControlBlockType.SL_Act)
+                    {
+                        SubmitError("Invalid notation of single line ACT", lineNum);
+                        return false;
+                    }
+                    else if (controlBlock == (int)ControlBlockType.SL_If)
+                    {
+                        SubmitError("Invalid notation of single line IF", lineNum);
+                        return false;
+                    }
+                    else if (controlBlock == (int)ControlBlockType.SL_Else)
+                    {
+                        SubmitError("In single line IF has to be any operators after ELSE", lineNum);
+                        return false;
+                    }
+                }
+
+                //для отладки
+                if (line.Length > 0)
+                {
+                    debugText += Environment.NewLine;
+                }
+                
+                if (currentRoot)
+                {
+                    //Вычисляем уровень вложенности(для утилиты форматирования кода)
+                    int stackSize = ControlStack.Count;
+                    int level = 0;
+                    if (stackSize > 0)
+                    {
+                        endIndentLevel = stackSize;
+                        ControlLine cline = ControlStack.Peek();
+                        int b = (int)cline.controlBlock;
+                        bool openingLine = cline.line == currentLine;
+                        if (openingLine && ((b == (int)ControlBlockType.ML_Act) || (b == (int)ControlBlockType.ML_If)))
+                        {
+                            level = startIndentLevel;
+                        }
+                        else if (openingLine && (b == (int)ControlBlockType.ML_Else))
+                        {
+                            level = startIndentLevel - 1;
+                        }
+                        else
+                        {
+                            level = endIndentLevel;
+                        }
+                    }
+                    location_codeline_level.Add(currentLine, level);
+                }
+            }
+            //Проверка на незакрытые в конце локации многострочные IF и ACT
+            if (ControlStack.Count > 0)
+            {
+                ControlLine cline = ControlStack.Pop();
+                if ((cline.controlBlock == ControlBlockType.ML_If) || (cline.controlBlock == ControlBlockType.ML_Else))
+                {
+                    SubmitError("Multi line IF without END", cline.line);
+                    return false;
+                }
+                else
+                {
+                    SubmitError("Multi line ACT without END", cline.line);
+                    return false;
+                }
+            }
+
+            AddLocationLink(m_name, true, m_start);
+
+            return true;
+        }
+
+        bool CheckBlockGroup(List<string> blockGroup, List<bool> blockInGroupIsText)
+        {
+            //Разбор аргументов для операторов ACT, IF, прочих операторов и функций.
+            int blockCode = qspGetStatCode(blockGroup.ToArray()[0]);
+            if (blockInGroupIsText[0])
+                blockCode = (int)QspStatementType.Unknown;
+            bool isSetOp = blockCode == (int)QspStatementType.Set;
+            if ((blockCode == (int)QspStatementType.Unknown) || isSetOp)
+            {
+                //Это присваивание?
+                int setpos = FindInTopBracketLevel(blockGroup, blockInGroupIsText, "=");
+                if (setpos == INVALID_INDEX)
+                    setpos = FindInTopBracketLevel(blockGroup, blockInGroupIsText, "+=");
+                if (setpos == INVALID_INDEX)
+                    setpos = FindInTopBracketLevel(blockGroup, blockInGroupIsText, "-=");
+                if (isSetOp && (setpos == INVALID_INDEX))
+                {
+                    SubmitError("Not found the char \"=\"", currentLine);
+                    return false;
+                }
+                if (setpos != INVALID_INDEX)
+                {
+                    //Присваивание
+                    if ((setpos == 0) || (isSetOp && (setpos == 1)))
+                    {
+                        SubmitError("The name of a variable before the character \"=\" is not specified!", currentLine);
+                        return false;
+                    }
+                    int last = blockGroup.Count - 1;
+                    if (setpos==last)
+                    {
+                        SubmitError("It should be a value after char \"=\"", currentLine);
+                        return false;
+                    }
+
+                    //Проверяем левую часть
+                    int start = 0;
+                    if (isSetOp)
+                        start = 1;
+                    int count = setpos - start;
+                    List<string> args = new List<string>();
+                    List<bool> types = new List<bool>();
+                    args = blockGroup.GetRange(start, count);
+                    types = blockInGroupIsText.GetRange(start, count);
+                    if (!CheckLeftAssign(args, types))
+                        return false;
+
+                    string assignedVarName = args[0];
+
+                    //Проверяем правую часть
+                    start = setpos + 1;
+                    count = last - start + 1;
+                    args = blockGroup.GetRange(start, count);
+                    types = blockInGroupIsText.GetRange(start, count);
+                    if (!CheckExpression(args, types))
+                        return false;
+
+                    //Засчитываем присваивание некоторым переменным как обращение к локации
+                    if ((count == 1) && types[0] && ListContainsIgnoreCase(callerVariables, assignedVarName))
+                    {
+                        AddLocationLink(args[0], false, true);
+                    }
+                }
+                else
+                {
+                    //Если оператор неизвестен, пытаемся разобрать выражение
+                    if (!CheckExpression(blockGroup, blockInGroupIsText))
+                        return false;
+
+                    //Разбираем код в ссылках <a href="EXEC:GOTO 'loc1'">
+                    if ((blockGroup.Count == 1) && (blockInGroupIsText[0]))
+                    {
+                        ParseExecInOutputText(blockGroup[0]);
+                    }
+                }
+            }
+            else if ((blockCode == (int)QspStatementType.If) || (blockCode == (int)QspStatementType.ElseIf))
+            {
+                int start = 1;
+                int count = blockGroup.Count - 1;
+                if (count > 0)
+                {
+                    List<string> args = blockGroup.GetRange(start, count);
+                    List<bool> types = blockInGroupIsText.GetRange(start, count);
+                    if (!CheckExpression(args, types))
+                        return false;
+                }
+                else
+                {
+                    if (blockCode == (int)QspStatementType.If)
+                    {
+                        SubmitError("Operator IF without condition", currentLine);
+                    }
+                    else
+                    {
+                        SubmitError("Operator ELSEIF without condition", currentLine);
+                    }
+                    return false;
+                }
+            }
+            else
+            {
+                //Если оператор известен, проверяем его аргументы.
+                int count = blockGroup.Count - 1;
+                List<string> args = new List<string>();
+                List<bool> types = new List<bool>();
+                if (count > 0)
+                {
+                    args = blockGroup.GetRange(1, count);
+                    types = blockInGroupIsText.GetRange(1, count);
+                }
+
+                if (!CheckStatementArgs(blockCode, args, types))
+                    return false;
+            }
+
+            //Проверяем подвыражения вида <<$var>> в любых строках
+            for (int i = 0; i < blockGroup.Count; i++)
+            {
+                if (blockInGroupIsText[i])
+                {
+                    if (!ParseSubExpressions(blockGroup[i]))
+                        return false;
+                }
+            }
+            return true;
+        }
+
+        bool CheckStatementArgs(int code, List<string> argsSrc, List<bool> typesSrc)
+        {
+            int count = argsSrc.Count;
+            List<string> args = new List<string>();
+            List<bool> types = new List<bool>();
+            if (count > 0)
+            {
+                if ((count > 1) && argsSrc.ToArray()[0].Equals("(") && !typesSrc.ToArray()[0] &&
+                    argsSrc.ToArray()[count - 1].Equals(")") && !typesSrc.ToArray()[count - 1])
+                {
+                    //Игнорируем одну пару скобок по краям
+                    args = argsSrc.GetRange(1, count - 2);
+                    types = typesSrc.GetRange(1, count - 2);
+                }
+                else
+                {
+                    args = argsSrc.GetRange(0, count);
+                    types = typesSrc.GetRange(0, count);
+                }
+            }
+            count = args.Count;
+
+            if ((count == 1) && types[0])
+            {
+                //Отмечаем в списке явные ссылки на локации
+                if ((code == (int)QspStatementType.GoSub) || (code == (int)QspStatementType.GoTo) ||
+                 (code == (int)QspStatementType.XGoTo))
+                {
+                    AddLocationLink(args[0], false, true);
+                }
+                //Разбираем код в ссылках <a href="EXEC:GOTO 'loc1'">
+                else if ((code == (int)QspStatementType.P) || (code == (int)QspStatementType.PL) ||
+                    (code == (int)QspStatementType.NL) || (code == (int)QspStatementType.MP) ||
+                    (code == (int)QspStatementType.MPL) || (code == (int)QspStatementType.MNL)) 
+                {
+                    ParseExecInOutputText(args[0]);
+                }
+                //Отмечаем в списке добавленные предметы
+                else if (code == (int)QspStatementType.AddObj)
+                {
+                    AddObj(args[0], true, false);
+                }
+                //Отмечаем в списке удаленные предметы
+                else if (code == (int)QspStatementType.DelObj)
+                {
+                    AddObj(args[0], false, true);
+                }
+                //Отмечаем в списке добавленные действия
+                else if (code == (int)QspStatementType.Act)
+                {
+                    AddAct(args[0], true, false);
+                }
+                //Отмечаем в списке удаленные действия
+                else if (code == (int)QspStatementType.DelAct)
+                {
+                    AddAct(args[0], false, true);
+                }
+            }
+
+            int minArgCount = qspStats[code].MinArgsCount;
+            int maxArgCount = qspStats[code].MaxArgsCount;
+            int argCount = 0;
+            int curIndex = 0;
+            List<string> expr = new List<string>();
+            if (count > 0)
+            {
+                while (true)
+                {
+                    if (argCount == maxArgCount)
+                    {
+                        SubmitError("Too many arguments for the operator", currentLine);
+                        return false;
+                    }
+
+                    int index = FindInTopBracketLevel(args, types, ",", curIndex);
+                    if (index != INVALID_INDEX)
+                    {
+                        if (index > curIndex)
+                        {
+                            if (!CheckExpression(args.GetRange(curIndex, index - curIndex), types.GetRange(curIndex, index - curIndex)))
+                                return false;
+                        }
+                        else
+                        {
+                            SubmitError("Argument can not be empty", currentLine);
+                            return false;
+                        }
+                    }
+                    else
+                    {
+                        if (!CheckExpression(args.GetRange(curIndex, count - curIndex), types.GetRange(curIndex, count - curIndex)))
+                            return false;
+                    }
+                    argCount++;
+                    if (index == INVALID_INDEX)
+                        break;
+                    curIndex = index + 1;
+                    if (curIndex == count)
+                    {
+                        SubmitError("Argument can not be empty", currentLine);
+                        return false;
+                    }
+                }
+            }
+            if (argCount < minArgCount)
+            {
+                SubmitError("The operator requires more arguments", currentLine);
+                return false;
+            }
+            return true;
+        }
+
+        bool CheckExpression(List<string> args, List<bool> types)
+        {
+            //Проверка выражения
+            int[] opStack = new int[QSP_STACKSIZE];
+            int[] argStack = new int[QSP_STACKSIZE];
+
+	        bool waitForOperator = false;
+            int opCode, itemsCount = 0, opSp = -1, argSp = -1;
+	        if (!qspCompileExprPushOpCode(ref opStack, ref opSp, ref argStack, ref argSp, (int)QspFunctionType.Start))
+                return false;
+            int argIndex = 0;
+	        while (argIndex <= args.Count)
+	        {
+                String s = "";
+                if (argIndex < args.Count)
+                    s = args[argIndex];
+		        if (waitForOperator)
+		        {
+			        opCode = qspGetFunctionCode(s, false);
+                    String nextArg = "";
+                    bool nextArgIsString = false;
+                    bool hasNextArg = argIndex + 1 < args.Count;
+                    if (hasNextArg)
+                    {
+                        nextArg = args[argIndex + 1];
+                        nextArgIsString = types[argIndex + 1];
+                    }
+                    if (opCode == (int)QspFunctionType.Unknown || opCode >= (int)QspFunctionType.First_Function)
+			        {
+                        SubmitError("Unknown action in the expression", currentLine);
+				        break;
+			        }
+                    if (((opCode == (int)QspFunctionType.And) || (opCode == (int)QspFunctionType.Or) || (opCode == (int)QspFunctionType.Mod)) &&
+                        !(hasNextArg && (nextArgIsString || nextArg.Equals("(") || (nextArg.IndexOfAny(Delimiters) == INVALID_INDEX)))
+                        )
+			        {
+                        SubmitError("Syntax error", currentLine);
+				        break;
+			        }
+                    bool bError = false;
+			        while (qspOps[opCode].Priority <= qspOps[opStack[opSp]].Priority && qspOps[opStack[opSp]].Priority != 127)
+			        {
+                        if (opStack[opSp] >= (int)QspFunctionType.First_Function) ++argStack[argSp];
+                        if (!qspAppendToCompiled(ref itemsCount))
+                        {
+                            bError = true;
+                            break;
+                        }
+				        if (--opSp < 0 || --argSp < 0)
+				        {
+                            SubmitError("Syntax error", currentLine);
+                            bError = true;
+					        break;
+				        }
+			        }
+                    if (bError) 
+                        break;
+			        switch (opCode)
+			        {
+                    case (int)QspFunctionType.End:
+				        if (opSp > 0)
+				        {
+                            SubmitError("Closing bracket not found", currentLine);
+                            bError = true;
+                            break;
+				        }
+				        return itemsCount > 0;
+                    case (int)QspFunctionType.CloseBracket:
+                        if (opStack[opSp] != (int)QspFunctionType.OpenBracket)
+				        {
+                            SubmitError("Opening bracket not found", currentLine);
+                            bError = true;
+                            break;
+				        }
+				        opCode = opStack[--opSp];
+                        if (opCode >= (int)QspFunctionType.First_Function)
+				        {
+                            if (argStack[argSp] + 1 < qspOps[opCode].MinArgsCount || argStack[argSp] + 1 > qspOps[opCode].MaxArgsCount)
+                            {
+                                SubmitError("Invalid number of arguments", currentLine);
+                                bError = true;
+                            }
+				        }
+				        else
+					        --argSp;
+				        break;
+                    case (int)QspFunctionType.Comma:
+                        if ((opSp > 0) && opStack[opSp - 1] >= (int)QspFunctionType.First_Function)
+				        {
+					        if (++argStack[argSp] > qspOps[opStack[opSp - 1]].MaxArgsCount)
+					        {
+                                SubmitError("Invalid number of arguments", currentLine);
+                                bError = true;
+                                break;
+					        }
+				        }
+				        else
+				        {
+                            if (!qspCompileExprPushOpCode(ref opStack, ref opSp, ref argStack, ref argSp, (int)QspFunctionType.Comma))
+                            {
+                                bError = true;
+                                break;
+                            }
+				        }
+				        waitForOperator = false;
+				        break;
+			        default:
+                        if (!qspCompileExprPushOpCode(ref opStack, ref opSp, ref argStack, ref argSp, opCode))
+                        {
+                            bError = true;
+                            break;
+                        }
+				        waitForOperator = false;
+				        break;
+			        }
+			        if (bError)
+                        break;
+		        }
+		        else
+		        {
+                    if ((argIndex < args.Count) && !types[argIndex] && IsNumber(s))
+			        {
+                        if (opStack[opSp] == (int)QspFunctionType.Minus)
+				        {
+					        --opSp;
+					        --argSp;
+				        }
+				        if (!qspAppendToCompiled(ref itemsCount))
+				            break;
+				        waitForOperator = true;
+			        }
+                    else if ((argIndex < args.Count) && types[argIndex])
+			        {
+				        if (!qspAppendToCompiled(ref itemsCount))
+				            break;
+				        waitForOperator = true;
+			        }
+			        else if (s.Equals("+"))
+			        {
+			        }
+			        else if (s.Equals("-"))
+			        {
+                        if (!qspCompileExprPushOpCode(ref opStack, ref opSp, ref argStack, ref argSp, (int)QspFunctionType.Minus))
+                            break;
+			        }
+			        else if (s.Equals("("))
+			        {
+                        if (!qspCompileExprPushOpCode(ref opStack, ref opSp, ref argStack, ref argSp, (int)QspFunctionType.OpenBracket))
+				            break;
+			        }
+			        else if (s.Equals(")"))
+			        {
+				        opCode = opStack[opSp];
+                        if (opCode != (int)QspFunctionType.OpenBracket)
+				        {
+                            if (opCode >= (int)QspFunctionType.First_Function)
+                                SubmitError("Invalid number of arguments", currentLine);
+					        else
+                                SubmitError("Syntax error", currentLine);
+					        break;
+				        }
+				        opCode = opStack[--opSp];
+                        if (opCode < (int)QspFunctionType.First_Function)
+				        {
+                            SubmitError("Syntax error", currentLine);
+					        break;
+				        }
+				        if (qspOps[opCode].MinArgsCount > 0)
+				        {
+                            SubmitError("Invalid number of arguments", currentLine);
+					        break;
+				        }
+				        if (!qspAppendToCompiled(ref itemsCount))
+				            break;
+				        --opSp;
+				        --argSp;
+				        waitForOperator = true;
+			        }
+			        else if ((argIndex < args.Count) && s.IndexOfAny(Delimiters) != 0)
+			        {
+                        if (s.IndexOfAny(Delimiters) != INVALID_INDEX)
+                        {
+                            SubmitError("Internal error of the analyzer: Invalid characters in the variable name", currentLine);
+                            break;
+                        }
+
+                        opCode = qspGetFunctionCode(s, true);
+                        if (opCode >= (int)QspFunctionType.First_Function)
+				        {
+                            if ((args.Count - argIndex > 1) && (args[argIndex + 1].Equals("(") && !types[argIndex + 1]))
+					        {
+						        if (!qspCompileExprPushOpCode(ref opStack, ref opSp, ref argStack, ref argSp, opCode))
+						            break;
+                                if (!qspCompileExprPushOpCode(ref opStack, ref opSp, ref argStack, ref argSp, (int)QspFunctionType.OpenBracket))
+						            break;
+                                argIndex++;
+						        --argSp;
+					        }
+					        else if (qspOps[opCode].MinArgsCount < 2)
+					        {
+						        if (qspOps[opCode].MinArgsCount > 0)
+						        {
+							        if (!qspCompileExprPushOpCode(ref opStack, ref opSp, ref argStack, ref argSp, opCode))
+							            break;
+						        }
+						        else
+						        {
+				                    if (!qspAppendToCompiled(ref itemsCount))
+				                        break;
+							        waitForOperator = true;
+						        }
+					        }
+					        else
+					        {
+                                SubmitError("Brackets not found", currentLine);
+                                break;
+					        }
+				        }
+				        else
+				        {
+                            int optArgsCount = 0;
+
+                            //Проверяем выражение(индекс массива)
+                            if ((args.Count - argIndex > 1) && (args[argIndex + 1].Equals("[") && !types[argIndex + 1]))
+                            {
+                                int optIndex = argIndex + 2;
+                                int level = 1;
+                                bool bFound = false;
+                                while (optIndex < args.Count)
+                                {
+                                    if (args[optIndex].Equals("[") && !types[optIndex])
+                                    {
+                                        level++;
+                                    }
+                                    else if (args[optIndex].Equals("]") && !types[optIndex])
+                                    {
+                                        level--;
+                                        if (level == 0)
+                                        {
+                                            bFound = true;
+                                            break;
+                                        }
+                                    }
+                                    optIndex++;
+                                }
+                                if (level > 0)
+                                {
+                                    SubmitError("Unclosed parenthesis \"[\"", currentLine);
+                                    break;
+                                }
+                                if (bFound)
+                                    optArgsCount = optIndex - argIndex;
+                            }
+                            List<string> subArgs = args.GetRange(argIndex, optArgsCount + 1);
+                            List<bool> subTypes = types.GetRange(argIndex, optArgsCount + 1);
+
+                            if (!CheckVariable(subArgs, subTypes, false))
+                                break;
+                            
+                            argIndex += optArgsCount;
+
+				            if (!qspAppendToCompiled(ref itemsCount))
+				                break;
+					        waitForOperator = true;
+				        }
+			        }
+			        else
+			        {
+                        if (opStack[opSp] >= (int)QspFunctionType.First_Function)
+                            SubmitError("Invalid number of arguments", currentLine);
+                        else
+                            SubmitError("Syntax error", currentLine);
+                        break;
+			        }
+		        }
+                argIndex++;
+	        }
+            return false;
+        }
+
+        bool CheckVariable(List<string> args, List<bool> types, bool assignment)
+        {
+            //Проверка имени переменной
+            if ((args.Count == 0) || (args[0].Length == 0) || types[0])
+            {
+                SubmitError("Internal error of the analyzer: empty name of variable!", currentLine);
+                return false;
+            }
+
+            string name = args[0];
+            int code1 = qspGetStatCode(name);
+            int code2 = qspGetFunctionCode(name, true);
+            if ((code1 != (int)QspStatementType.Unknown) || (code2 != (int)QspFunctionType.Unknown))
+            {
+                SubmitError("QSP Keyword \"" + name + "\" cannot be used as a variable name", currentLine);
+                return false;
+            }
+
+            //Проверяем имя переменной на валидность
+            //В имени переменной разрешены все символы, кроме DELIMS и цифры в начале имени
+            //Перед именем переменной может находиться префикс "$"
+            string checkName = name;
+            if (checkName.StartsWith("$"))
+                checkName = checkName.Substring(1);
+            // $ =
+            if (checkName.Length == 0)
+            {
+                SubmitError("Invalid variable name \"" + name + "\"", currentLine);
+                return false;
+            }
+            // 1asd =
+            if (checkName.Substring(0, 1).IndexOfAny(Digits) != INVALID_INDEX)
+            {
+                SubmitError("Variable name \"" + name + "\" cannot start with a digit", currentLine);
+                return false;
+            }
+            // /asd =
+            if (checkName.IndexOfAny(Delimiters) != INVALID_INDEX)
+            {
+                SubmitError("Invalid symbols in the name of the variable \"" + name + "\"", currentLine);
+                return false;
+            }
+
+            //Проверяем переменную на "смешанные раскладки"
+            if ((checkName.IndexOfAny(LatinLetters) != INVALID_INDEX) && (checkName.IndexOfAny(RussianLetters) != INVALID_INDEX))
+            {
+                SubmitWarning("English and Russian symbols are used simultaneously in the name of varible \"" + name + "\" , possibly a typo", currentLine);
+            }
+
+            //Проверяем выражение(индекс массива)
+            if (args.Count > 1)
+            {
+                if (args.Count > 2 && args[1].Equals("[") && !types[1] &&
+                                        args[args.Count - 1].Equals("]") && !types[args.Count - 1])
+                {
+                    int start = 2;
+                    int count = args.Count - 3;
+                    if (count > 0)
+                    {
+                        List<string> argsCut = args.GetRange(start, count);
+                        List<bool> typesCut = types.GetRange(start, count);
+                        if (!CheckExpression(argsCut, typesCut))
+                            return false;
+                    }
+                }
+                else
+                {
+                    SubmitError("Invalid expression", currentLine);
+                    return false;
+                }
+            }
+
+            //Сохраняем имя переменной в глобальном списке
+            if (!assignment)
+            {
+                bool usedBySystem = ListContainsIgnoreCase(systemVariables, name);
+                AddVar(name, usedBySystem, true);
+            }
+
+            return true;
+        }
+        
+        bool CheckLeftAssign(List<string> args, List<bool> types)
+        {
+            //Проверка имени переменной(слева от знака "=" в операции присваивания)
+            if ((args.Count == 0) || (args[0].Length == 0) || types[0])
+            {
+                //Текстовая строка
+                SubmitError("Name of the variable should be before char \"=\" in the assignment operation", currentLine);
+                return false;
+            }
+
+            if (!CheckVariable(args, types, true))
+                return false;
+
+            //Сохраняем имя переменной в глобальном списке
+            bool usedBySystem = ListContainsIgnoreCase(systemVariables, args[0]);
+            AddVar(args[0], true, usedBySystem);
+
+            return true;
+        }
+
+        int FindInTopBracketLevel(List<string> args, List<bool> types, string what)
+        {
+            return FindInTopBracketLevel(args, types, what, 0);
+        }
+
+        int FindInTopBracketLevel(List<string> args, List<bool> types, string what, int startIndex)
+        {
+            //Ищем знак "=" или запятую вне скобок
+            int bracketLevel = 0;
+            for (int i = startIndex; i < args.Count; i++)
+            {
+                if (types[i])
+                    continue;
+                string block = args[i];
+                if (block.Equals("("))
+                {
+                    bracketLevel++;
+                }
+                else if (block.Equals(")"))
+                {
+                    bracketLevel--;
+                }
+                else if (block.Equals(what) && (bracketLevel == 0))
+                {
+                    return i;
+                }
+            }
+            return INVALID_INDEX;
+        }
+
+        void ParseExecInOutputText(string text)
+        {
+            //Разбираем код в ссылках <a href="EXEC:GOTO 'loc1'">
+            int pos = 0;
+
+            //Строим "карту" подвыражений.
+            //Если подвыражения в строке содержат ошибки, то разбирать теги нет смысла.
+            List<int> subExpMap = new List<int>();
+            if (!ParseSubExpressions(text, ref subExpMap))
+                return;
+            int subExpSkipped = 0;
+
+            while (pos < text.Length)
+            {
+                pos = text.IndexOf('<', pos);
+                if (pos == INVALID_INDEX)
+                    break;
+
+                if (subExpMap.Count / 2 > subExpSkipped)
+                {
+                    int subExpStartPos = subExpMap[subExpSkipped * 2];
+                    int subExpEndPos = subExpMap[subExpSkipped * 2 + 1];
+                    if (subExpStartPos == pos)
+                    {
+                        //Пропускаем подвыражения вне тегов
+                        subExpSkipped++;
+                        pos = subExpEndPos + 1;
+                        continue;
+                    }
+                }
+
+                //Разбираем содержимое угловых скобок
+                //Внутри HTML-тега кавычки экранируются не через дублирование, как в QSP, а через "\",
+                //причем экранирование требуется только внутри окавыченной строки.
+                List<string> blockGroup = new List<string>();
+                List<bool> blockInGroupIsText = new List<bool>();
+                int firstBlockPosition = INVALID_INDEX;
+
+                string quotedText = "";
+                string block = "";
+                bool tagClosed = false;
+                bool quotedTextCompleted = false;
+                bool blockCompleted = false;
+                pos++;
+                int startPos = pos;
+                if ((pos < text.Length) && (text[pos] == '/'))
+                    startPos++;
+                int tagQuote = (int)QuoteType.None;
+                while (!tagClosed && (pos < text.Length))
+                {
+                    if (subExpMap.Count / 2 > subExpSkipped)
+                    {
+                        int subExpStartPos = subExpMap[subExpSkipped * 2];
+                        int subExpEndPos = subExpMap[subExpSkipped * 2 + 1];
+                        if (subExpStartPos == pos)
+                        {
+                            //Пропускаем подвыражения вне тегов
+                            subExpSkipped++;
+                            string subExpText = text.Substring(pos, subExpEndPos - pos + 1);
+                            if (tagQuote == (int)QuoteType.None)
+                                block += subExpText;
+                            else
+                                quotedText += subExpText;
+                            pos = subExpEndPos + 1;
+                            continue;
+                        }
+                    }
+
+                    char c2 = text[pos];
+
+                    if (tagQuote != (int)QuoteType.None)
+                    {
+                        //Апостроф либо кавычка
+                        if (((tagQuote == (int)QuoteType.Single) && (c2 == '\'')) ||
+                            ((tagQuote == (int)QuoteType.Double) && (c2 == '"')))
+                        {
+                            if ((pos - 1 > 0) && (text[pos - 1] == '\\'))
+                            {
+                                //Экранированный апостроф либо кавычка
+                                if (!quotedTextCompleted)
+                                    quotedText = quotedText.Substring(0, quotedText.Length - 1) + c2;
+                            }
+                            else
+                            {
+                                tagQuote = (int)QuoteType.None;
+                                quotedTextCompleted = true;
+                            }
+                        }
+                        else if (!quotedTextCompleted)
+                        {
+                            quotedText += c2;
+                        }
+                    }
+                    else if (c2 == '>')
+                    {
+                        tagClosed = true;
+                    }
+                    else if ((block.Length == 0) && (c2 == '\''))
+                    {
+                        tagQuote = (int)QuoteType.Single;
+                    }
+                    else if ((block.Length == 0) && (c2 == '"'))
+                    {
+                        tagQuote = (int)QuoteType.Double;
+                    }
+                    else if (c2.ToString().IndexOfAny(WhiteSpace) == 0)
+                    {
+                        if (block.Length > 0)
+                        {
+                            blockCompleted = true;
+                        }
+                    }
+                    else if (c2 == '=')
+                    {
+                        if (block.Length > 0)
+                        {
+                            blockGroup.Add(block);
+                            blockInGroupIsText.Add(false);
+                        }
+                        block = "=";
+                        blockCompleted = true;
+                    }
+                    else
+                    {
+                        if (firstBlockPosition == INVALID_INDEX)
+                        {
+                            firstBlockPosition = pos - startPos;
+                        }
+                        block += c2;
+                    }
+                    if (tagClosed)
+                    {
+                        if (block.Length > 0)
+                            blockCompleted = true;
+                    }
+
+                    if (blockCompleted)
+                    {
+                        blockGroup.Add(block);
+                        blockInGroupIsText.Add(false);
+                        blockCompleted = false;
+                        block = "";
+                    }
+                    if (quotedTextCompleted)
+                    {
+                        blockGroup.Add(quotedText);
+                        blockInGroupIsText.Add(true);
+                        quotedTextCompleted = false;
+                        quotedText = "";
+                    }
+
+                    pos++;
+                }
+                
+                if (tagQuote == (int)QuoteType.Single)
+                {
+                    SubmitWarning("Unclosed apostrophe inside the tag", currentLine);
+                    break;
+                }
+                else if (tagQuote == (int)QuoteType.Double)
+                {
+                    SubmitWarning("Unclosed quote inside the tag", currentLine);
+                    break;
+                }
+                if (!tagClosed)
+                {
+                    SubmitWarning("Unclosed tag",currentLine);
+                    break;
+                }
+                if (firstBlockPosition > 0)
+                {
+                    SubmitWarning("The name of the tag should follow immediately after the opening angle bracket, without spaces", currentLine);
+                    break;
+                }
+
+
+                //Ищем HREF в атрибутах тега A
+                int hrefIndex = INVALID_INDEX;
+                if ((blockGroup.Count > 3) && (blockGroup[0].Equals("A", StringComparison.OrdinalIgnoreCase)) && !blockInGroupIsText[0])
+                {
+                    for (int i = 1; i + 2 < blockGroup.Count; i++)
+                    {
+                        if (blockGroup[i].Equals("HREF", StringComparison.OrdinalIgnoreCase) && !blockInGroupIsText[i] &&
+                            blockGroup[i + 1].Equals("=") && !blockInGroupIsText[i + 1])
+                        {
+                            hrefIndex = i + 2;
+                        }
+                    }
+                }
+
+                if (hrefIndex != INVALID_INDEX)
+                {
+                    string hrefText = blockGroup[hrefIndex];
+                    int execKeywordLength = "EXEC:".Length;
+                    if (hrefText.StartsWith("EXEC:", StringComparison.OrdinalIgnoreCase) && (hrefText.Length > execKeywordLength))
+                    {
+                        string execText = hrefText.Substring(execKeywordLength);
+                        List<int> subExpMapExec = new List<int>();
+                        ParseSubExpressions(execText, ref subExpMapExec);
+                        if (subExpMapExec.Count == 0)
+                        {
+                            //В EXEC не разбираем код с подвыражениями, это невозможно без интерпретации
+                            List<string> tagLines = new List<string>(execText.Split('\n'));
+                            bool wasRoot = currentRoot;
+                            currentRoot = false;
+                            ParseLocation(tagLines, currentRoot);
+                            currentRoot = wasRoot;
+                        }
+                    }
+                }
+            }
+        }
+
+        bool ParseSubExpressions(string text)
+        {
+            List<int> dummy = null;
+            return ParseSubExpressions(text, ref dummy);
+        }
+        bool ParseSubExpressions(string text, ref List<int> subExpMap)
+        {
+            bool quiet = subExpMap != null;
+            //Разбираем подвыражения - <<$var>>
+            if (quiet)
+                subExpMap.Clear();
+            int pos = 0;
+            bool valid = true;
+            while (valid && pos < text.Length)
+            {
+                pos = text.IndexOf("<<", pos);
+                if (pos == INVALID_INDEX)
+                    break;
+                if (quiet)
+                    subExpMap.Add(pos);
+                //Разбираем содержимое двойных угловых скобок
+                string subText = "";
+                bool subClosed = false;
+                pos += 2;
+                int subQuote = (int)QuoteType.None;
+                int curlyLevel = 0;
+                while (pos < text.Length)
+                {
+                    char c2 = text[pos];
+
+                    if (subQuote == (int)QuoteType.None)
+                    {
+                        if ((c2 == '>') && (pos + 1 < text.Length) && (text[pos + 1] == '>') && (curlyLevel == 0))
+                        {
+                            subClosed = true;
+                            break;
+                        }
+                        else if (c2 == '\'')
+                        {
+                            subQuote = (int)QuoteType.Single;
+                        }
+                        else if (c2 == '"')
+                        {
+                            subQuote = (int)QuoteType.Double;
+                        }
+                        else if (c2 == '{')
+                        {
+                            curlyLevel++;
+                        }
+                        else if (c2 == '}')
+                        {
+                            curlyLevel--;
+                        }
+                    }
+                    else if (((subQuote == (int)QuoteType.Single) && (c2 == '\'')) ||
+                             ((subQuote == (int)QuoteType.Double) && (c2 == '"')))
+
+                    {
+                        //Апостроф или кавычка
+                        if ((pos + 1 < text.Length) && (
+                            ((subQuote == (int)QuoteType.Single) && (text[pos + 1] == '\'')) ||
+                            ((subQuote == (int)QuoteType.Double) && (text[pos + 1] == '"'))))
+                        {
+                            //Экранированный апостроф либо кавычка
+                        }
+                        else
+                        {
+                            subQuote = (int)QuoteType.None;
+                        }
+                    }
+                    subText += c2;
+                    pos++;
+                }
+                if (quiet)
+                {
+                    if (subClosed)
+                        subExpMap.Add(pos + 1);
+                    else
+                        subExpMap.Add(pos - 1);
+                }
+                if (subQuote == (int)QuoteType.Single)
+                {
+                    if (!quiet)
+                        SubmitError("Unclosed apostrophe in a subexpression", currentLine);
+                    valid = false;
+                    break;
+                }
+                else if (subQuote == (int)QuoteType.Double)
+                {
+                    if (!quiet)
+                        SubmitError("Unclosed quote in a subexpression", currentLine);
+                    valid = false;
+                    break;
+                }
+                else if (curlyLevel != 0)
+                {
+                    if (!quiet)
+                        SubmitError("Unclosed curly bracket in a subexpression", currentLine);
+                    valid = false;
+                    break;
+                }
+                if (!subClosed)
+                {
+                    if (!quiet)
+                        SubmitError("Unclosed subexpression", currentLine);
+                    valid = false;
+                    break;
+                }
+                if (subText.Trim(WhiteSpace).Length == 0)
+                {
+                    if (!quiet)
+                        SubmitError("Empty subexpression", currentLine);
+                    valid = false;
+                    break;
+                }
+
+                if (!quiet)
+                {
+                    //Парсим подвыражение как исполняемый код.
+                    //Для того, чтобы строка считалась именно выражением, добавляем ''+ в начало
+                    subText = "''+" + subText;
+                    List<string> subLines = new List<string>(subText.Split('\n'));
+                    bool wasRoot = currentRoot;
+                    currentRoot = false;
+                    valid = ParseLocation(subLines, currentRoot);
+                    currentRoot = wasRoot;
+                }
+            }
+            return valid;
+        }
+    }
+
+    public class QSPGameCode : Common
+    {
+        Hashtable m_LocationsByName;
+        List<Location> m_LocationsByOrder;
+        Location m_lastLocation;
+
+        public QSPGameCode()
+        {
+            m_LocationsByName = new Hashtable();
+            m_LocationsByOrder = new List<Location>();
+            m_lastLocation = null;
+        }
+
+        public bool ParseGame(string fileName, object sender, DoWorkEventArgs e)
+        {
+            int totalLines = 0;
+            StreamReader rTl = new StreamReader(fileName);
+            while (rTl.ReadLine() != null) { totalLines++; };
+            m_LocationsByName.Clear();
+            m_LocationsByOrder.Clear();
+            ClearErrors();
+            m_lastLocation = null;
+            currentLocation = "";
+
+            vars = new List<QspVariable>();
+            locationLinks = new List<QspLocationLink>();
+            objects = new List<QspObj>();
+            acts = new List<QspAct>();
+
+            StreamReader fi = null;
+            if (!OpenStreamForReading(ref fi, fileName))
+            {
+                return false;
+            }
+            string s;
+            int line_counter = 0;
+            List<string> locationCode = new List<string>();
+            bool inside = false;
+            while ((s = fi.ReadLine()) != null)
+            {
+                line_counter++;
+                string trimmed = s.Trim(WhiteSpace);
+                if ((trimmed.Length > 0) && (trimmed[0] == '#'))
+                {
+                    //имя локации
+                    string locName = trimmed.Substring(1).Trim(WhiteSpace);
+                    if (!AddLocation(locName, line_counter))
+                    {
+                        fi.Close();
+                        return false;
+                    }
+                    currentLocation = locName;
+                    inside = true;
+                }
+                else if ((trimmed.Length > 38) && trimmed.StartsWith("--- ") && trimmed.EndsWith(" ---------------------------------"))
+                {
+                    inside = false;
+                    Location lastLoc = GetLastLocation();
+                    if (lastLoc != null)
+                    {
+                        lastLoc.ParseLocation(locationCode, true);
+                        locationCode.Clear();
+                        currentLocation = "";
+                    }
+                }
+                else
+                {
+                    if (inside && GetLastLocation() != null)
+                        locationCode.Add(s);
+                }
+                (sender as BackgroundWorker).ReportProgress(Convert.ToInt32(((double)line_counter/(double)totalLines) * 100));
+                if ((sender as BackgroundWorker).CancellationPending)
+                {
+                    e.Cancel = true;
+                    return true;
+                }
+            }
+            fi.Close();
+            return true;
+        }
+
+        public bool AddLocation(string name, int line)
+        {
+            if (name.Length <= 0)
+            {
+                SubmitError("Empty name of location", line);
+                return false;
+            }
+            if (m_LocationsByName.ContainsKey(name))
+            {
+                SubmitError("Location named " + name + " exist already", line);
+                return false;
+            }
+            Location newLoc = new Location(this, name, line, m_LocationsByOrder.Count == 0);
+            m_LocationsByName.Add(name, newLoc);
+            m_LocationsByOrder.Add(newLoc);
+            m_lastLocation = newLoc;
+            return true;
+        }
+
+        public Location GetLastLocation()
+        {
+            return m_lastLocation;
+        }
+
+        public Hashtable GetLocationsByName()
+        {
+            return m_LocationsByName;
+        }
+
+        public Location GetLocation(string locationName)
+        {
+            Location loc = (Location)m_LocationsByName[locationName];
+            return loc;
+        }
+
+        public bool Beautify(string fileName)
+        {
+            //Причесываем код - добавляем пробелов
+            StreamWriter fo = null;
+            if (!OpenStreamForWriting(ref fo, fileName))
+                return false;
+
+            for (int i = 0; i < m_LocationsByOrder.Count; i++)
+            {
+                Location loc = (Location)m_LocationsByOrder[i];
+                fo.WriteLine("# " + loc.GetName());
+                for (int j = 0; j < loc.GetCodeLinesCount(); j++)
+                {
+                    string text = "";
+                    int level = INVALID_INDEX;
+                    loc.GetCodeLine(j, ref text, ref level);
+                    if (level != INVALID_INDEX)
+                    {
+                        text = new string(' ', level * 4) + text.TrimStart(WhiteSpace);
+                    }
+                    fo.WriteLine(text);
+                }
+                fo.WriteLine("--- " + loc.GetName() + " ---------------------------------");
+                fo.WriteLine();
+            }
+            fo.Close();
+            return true;
+        }
+    }
+}

+ 141 - 0
QSP/qsp-analyser/QSP_Analyser/QSP_Analyser.csproj

@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{0EB1C8F9-E5A2-4C13-8ED2-C1897332F197}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Analyser</RootNamespace>
+    <AssemblyName>QSP_Analyser</AssemblyName>
+    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <StartupObject>Analyser.Program</StartupObject>
+    <ManifestCertificateThumbprint>4BF816F664C87F6B56DA3F2582A6A8BDC305FB9C</ManifestCertificateThumbprint>
+    <ManifestKeyFile>QSP_Analyser_TemporaryKey.pfx</ManifestKeyFile>
+    <GenerateManifests>true</GenerateManifests>
+    <TargetZone>LocalIntranet</TargetZone>
+    <ApplicationManifest>Properties\app.manifest</ApplicationManifest>
+    <SignManifests>false</SignManifests>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <UpgradeBackupLocation>
+    </UpgradeBackupLocation>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <PublishUrl>C:\Site\QSP\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <PublishWizardCompleted>true</PublishWizardCompleted>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Deployment" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Common.cs" />
+    <Compile Include="MainForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="MainForm.Designer.cs">
+      <DependentUpon>MainForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <EmbeddedResource Include="MainForm.resx">
+      <DependentUpon>MainForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Resources.resx</DependentUpon>
+      <DesignTime>True</DesignTime>
+    </Compile>
+    <None Include="app.config" />
+    <None Include="Properties\app.manifest" />
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+    </None>
+    <Compile Include="Properties\Settings.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Settings.settings</DependentUpon>
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>
+    </Compile>
+    <Compile Include="QSPGameCode.cs" />
+    <Compile Include="Settings.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+      <Visible>False</Visible>
+      <ProductName>Профиль клиента .NET Framework</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 2.0 %28x86%29</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.0 %28x86%29</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

+ 16 - 0
QSP/qsp-analyser/QSP_Analyser/QSP_Analyser.csproj.user

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <PublishUrlHistory />
+    <InstallUrlHistory />
+    <SupportUrlHistory />
+    <UpdateUrlHistory />
+    <BootstrapperUrlHistory />
+    <ErrorReportUrlHistory />
+    <FallbackCulture>en-US</FallbackCulture>
+    <VerifyUploadedFiles>false</VerifyUploadedFiles>
+  </PropertyGroup>
+  <PropertyGroup>
+    <EnableSecurityDebugging>false</EnableSecurityDebugging>
+  </PropertyGroup>
+</Project>

+ 28 - 0
QSP/qsp-analyser/QSP_Analyser/Settings.cs

@@ -0,0 +1,28 @@
+namespace Analyser.Properties {
+    
+    
+    // This class allows you to handle specific events on the settings class:
+    //  The SettingChanging event is raised before a setting's value is changed.
+    //  The PropertyChanged event is raised after a setting's value is changed.
+    //  The SettingsLoaded event is raised after the setting values are loaded.
+    //  The SettingsSaving event is raised before the setting values are saved.
+    internal sealed partial class Settings {
+        
+        public Settings() {
+            // // To add event handlers for saving and changing settings, uncomment the lines below:
+            //
+            // this.SettingChanging += this.SettingChangingEventHandler;
+            //
+            // this.SettingsSaving += this.SettingsSavingEventHandler;
+            //
+        }
+        
+        private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
+            // Add code to handle the SettingChangingEvent event here.
+        }
+        
+        private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
+            // Add code to handle the SettingsSaving event here.
+        }
+    }
+}

+ 178 - 0
QSP/qsp-analyser/QSP_Analyser/app.config

@@ -0,0 +1,178 @@
+<?xml version="1.0"?>
+<configuration>
+	<configSections>
+		<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+			<section name="Analyser.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
+		</sectionGroup>
+	</configSections>
+	<startup/><userSettings>
+		<Analyser.Properties.Settings>
+			<setting name="filepath" serializeAs="String">
+				<value/>
+			</setting>
+			<setting name="EnableVariableCalls" serializeAs="String">
+				<value>True</value>
+			</setting>
+			<setting name="VariableNames" serializeAs="String">
+				<value>$COUNTER
+$ONGLOAD
+$ONGSAVE
+$ONNEWLOC
+$ONACTSEL
+$ONOBJSEL
+$ONOBJADD
+$ONOBJDEL
+$USERCOM</value>
+			</setting>
+			<setting name="EnableSortingLocations" serializeAs="String">
+				<value>True</value>
+			</setting>
+			<setting name="EnableSortingVariables" serializeAs="String">
+				<value>True</value>
+			</setting>
+			<setting name="EnableSortingObjects" serializeAs="String">
+				<value>True</value>
+			</setting>
+			<setting name="SystemVariables" serializeAs="String">
+				<value>FSIZE
+FCOLOR
+BCOLOR
+LCOLOR
+USEHTML
+$FNAME
+$BACKIMAGE
+NOSAVE
+DISABLESCROLL
+DISABLESUBEX
+DEBUG
+$COUNTER
+$ONGLOAD
+$ONGSAVE
+$ONNEWLOC
+$ONACTSEL
+$ONOBJSEL
+$ONOBJADD
+$ONOBJDEL
+$USERCOM
+ARGS
+$ARGS
+RESULT
+$RESULT</value>
+			</setting>
+			<setting name="EnableAero" serializeAs="String">
+				<value>True</value>
+			</setting>
+			<setting name="AeroSystemVars" serializeAs="String">
+				<value>SCROLL_SPEED
+$UP_ARROW_IMAGE
+$DOWN_ARROW_IMAGE
+HIDE_SCROLL_ARROWS
+$STYLESHEET
+DISABLESHADE
+DISABLEAUTOREF
+$NEWLOC_EFFECT
+NEWLOC_EFFECT_TIME
+NEWLOC_EFFECT_SEQ
+$TOPIMAGE
+INTEGRATED_ACTIONS
+MAINDESC_X
+MAINDESC_Y
+MAINDESC_W
+MAINDESC_H
+$MAIN_FORMAT
+$MAINDESC_BACKIMAGE
+STATDESC_X
+STATDESC_Y
+STATDESC_W
+STATDESC_H
+$STAT_FORMAT
+$STATDESC_BACKIMAGE
+ACTIONS_X
+ACTIONS_Y
+ACTIONS_W
+ACTIONS_H
+$ACTION_FORMAT
+$SEL_ACTION_FORMAT
+$ACTIONS_BACKIMAGE
+OBJECTS_X
+OBJECTS_Y
+OBJECTS_W
+OBJECTS_H
+$OBJECT_FORMAT
+$SEL_OBJECT_FORMAT
+$OBJECTS_BACKIMAGE
+USERINPUT_X
+USERINPUT_Y
+USERINPUT_W
+USERINPUT_H
+VIEW_X
+VIEW_Y
+VIEW_W
+VIEW_H
+$VIEW_EFFECT
+VIEW_EFFECT_TIME
+ALWAYS_SHOW_VIEW
+$INPUT_BACKIMAGE
+INPUT_X
+INPUT_Y
+$INPUT_FORMAT
+INPUT_TEXT_X
+INPUT_TEXT_Y
+INPUT_TEXT_W
+INPUT_TEXT_H
+INPUT_BAR_X
+INPUT_BAR_Y
+INPUT_BAR_W
+INPUT_BAR_H
+$INPUT_OK_IMAGE
+INPUT_OK_X
+INPUT_OK_Y
+$INPUT_CANCEL_IMAGE
+INPUT_CANCEL_X
+INPUT_CANCEL_Y
+$INPUT_EFFECT
+INPUT_EFFECT_TIME
+$MSG_BACKIMAGE
+MSG_X
+MSG_Y
+$MSG_FORMAT
+MSG_TEXT_X
+MSG_TEXT_Y
+MSG_TEXT_W
+MSG_TEXT_H
+$MSG_OK_IMAGE
+MSG_OK_X
+MSG_OK_Y
+$MSG_EFFECT
+MSG_EFFECT_TIME
+FIXED_SIZE_MENU
+MENU_PADDING
+MENU_BORDER
+MENU_BORDER_COLOR
+$MENU_BACKIMAGE
+MENU_X
+MENU_Y
+$MENU_FORMAT
+$SEL_MENU_FORMAT
+MENU_LIST_X
+MENU_LIST_Y
+MENU_LIST_W
+MENU_LIST_H
+$MENU_EFFECT
+MENU_EFFECT_TIME</value>
+			</setting>
+			<setting name="EnableSortingActions" serializeAs="String">
+				<value>True</value>
+			</setting>
+			<setting name="CsvTranslationSuffix" serializeAs="String">
+				<value>_tr</value>
+			</setting>
+			<setting name="IgnoreEmptyTranslationsCsv" serializeAs="String">
+				<value>True</value>
+			</setting>
+			<setting name="EnableCurlyParsing" serializeAs="String">
+				<value>True</value>
+			</setting>
+		</Analyser.Properties.Settings>
+	</userSettings>
+</configuration>

BIN
QSP/sound/codec_aiff.dll


BIN
QSP/sound/codec_asf.dll


BIN
QSP/sound/codec_dls.dll


BIN
QSP/sound/codec_flac.dll


BIN
QSP/sound/codec_fsb.dll


BIN
QSP/sound/codec_it.dll


BIN
QSP/sound/codec_midi.dll


BIN
QSP/sound/codec_mod.dll


BIN
QSP/sound/codec_mpeg.dll


BIN
QSP/sound/codec_oggvorbis.dll


BIN
QSP/sound/codec_playlist.dll


BIN
QSP/sound/codec_s3m.dll


BIN
QSP/sound/codec_tag.dll


BIN
QSP/sound/codec_vag.dll


BIN
QSP/sound/codec_wav.dll


BIN
QSP/sound/codec_xm.dll


BIN
QSP/sound/output_dsound.dll


+ 3 - 0
To_do_list

@@ -66,6 +66,9 @@ JulienJaden:
 (R) Re-coding "tanNicholas" and adding additional scenes for more variation
 (F) Long-term idea: A romance between Sveta and Nicholas (Tanya's stepdad)?
 
+centerflag982:
+(A) Figure out how the hell Git works
+
 Up for grabs:
 While working on the sexm, I was like, man it sucks we don't have boyfriends in the boyStat, we should really add them. Then I was like, yeah but then we would need to give them each a name. Then I was like we could give them a blurb of personality on the wiki FAQ that we could later add in. Like a bit about their family, goals in life etc. To give them a bit more. split them up into 3 groups, shy group, normal, bad boy, do 5 to 7 boys for each group. get a image of each one, a name for each one, a boystat entry for each one then do a personality blurb.
 Then when you ran into a boy to date it would always be one of them. With them each having a name, the code could be written to never pull the same guy twice. So in different play throughs you might date the same guy, but during a single play through you should never date the same guy twice.

+ 1 - 2
glife-notepad++

@@ -263,7 +263,6 @@
 			<File name="locations\gaptek" />
 			<File name="locations\garfather" />
 			<File name="locations\gargazel" />
-			<File name="locations\garmassiv" />
 			<File name="locations\gdk" />
 			<File name="locations\gdkbibl" />
 			<File name="locations\gdkin" />
@@ -506,6 +505,7 @@
 			<File name="locations\Nord" />
 			<File name="locations\NormPR" />
 			<File name="locations\npc" />
+			<File name="locations\npc_age" />
 			<File name="locations\npc_intro" />
 			<File name="locations\npcbreeder" />
 			<File name="locations\npccleanc" />
@@ -583,7 +583,6 @@
 			<File name="locations\pornhist" />
 			<File name="locations\pornschedule" />
 			<File name="locations\pornstudio" />
-			<File name="locations\portmirror" />
 			<File name="locations\portnoi" />
 			<File name="locations\portnoi2" />
 			<File name="locations\postdeliveries" />

+ 75 - 44
glife.qproj

@@ -3,6 +3,7 @@
   <Structure>
     <Location name="start"/>
     <Location name="version"/>
+    <Location name="history"/>
     <Location name="gameover"/>
     <Location name="begin"/>
     <Location name="onobjsel"/>
@@ -14,6 +15,8 @@
       <Location name="LOCA"/>
       <Location name="saveg"/>
       <Location name="inputProcessing"/>
+      <Location name="restoreposition"/>
+      <Location name="saveposition"/>
     </Folder>
     <Folder name="clothing">
       <Location name="clothing"/>
@@ -54,6 +57,17 @@
       <Location name="$attrib_shoe_gandm"/>
       <Location name="$attrib_shoe_trainers"/>
     </Folder>
+    <Folder name="underwear">
+      <Location name="underwear"/>
+      <Location name="bras"/>
+      <Location name="$bra_image"/>
+      <Location name="panties"/>
+      <Location name="$panty_image"/>
+    </Folder>
+    <Folder name="Accessories">
+      <Location name="purses"/>
+      <Location name="$purse_image"/>
+    </Folder>
     <Folder name="Stats">
       <Location name="DNA"/>
       <Location name="body"/>
@@ -69,6 +83,7 @@
       <Location name="stat_display"/>
       <Location name="stat_sklattrib"/>
       <Location name="fame"/>
+      <Location name="traits"/>
       <Location name="din_bad"/>
       <Location name="din_van"/>
       <Location name="statBat"/>
@@ -111,6 +126,7 @@
     <Folder name="Prehistory">
       <Location name="preSYS"/>
       <Location name="preTG"/>
+      <Location name="preNT"/>
       <Location name="preCUST"/>
       <Location name="preALT"/>
     </Folder>
@@ -120,13 +136,16 @@
       <Location name="npcgenext"/>
       <Location name="npcpreservec"/>
       <Location name="npcrnamefile"/>
+      <Location name="npcbreeder"/>
       <Location name="npcstatic1"/>
       <Location name="npcstatic2"/>
       <Location name="npcstatic3"/>
       <Location name="npcstatic4"/>
-	  <Location name="npcstatic5"/>
-	  <Location name="npc_intro"/>
+      <Location name="npcstatic5"/>
+      <Location name="npc_intro"/>
+      <Location name="npc_age"/>
       <Location name="saveupdater"/>
+	  <location name="NPCChanger"/>
     </Folder>
     <Folder name="Combat">
       <Location name="fight"/>
@@ -167,6 +186,7 @@
       <Location name="metro_events"/>
       <Location name="events"/>
       <Location name="street_event"/>
+      <Location name="noticeboard"/>
     </Folder>
     <Folder name="Post office">
       <Location name="postoffice"/>
@@ -261,7 +281,6 @@
       <Location name="sexdvanadva"/>
       <Location name="sexdvoe"/>
       <Location name="svidboy"/>
-      <Location name="vecher"/>
       <Location name="Vnlake1"/>
       <Location name="Vnlake2"/>
       <Location name="WorkHosp"/>
@@ -298,13 +317,15 @@
     <Folder name="Parent's Apartment">
       <Location name="bedrPar"/>
       <Location name="bedrPar2"/>
-      <Location name="seeparentsex"/>
       <Location name="sitrPar"/>
       <Location name="vanrPar"/>
       <Location name="kuhrPar"/>
       <Location name="korrPar"/>
       <Location name="selfplay"/>
       <Location name="gtelefon"/>
+    </Folder>
+    <Folder name="Family">
+      <Location name="seeparentsex"/>
       <Location name="father"/>
       <Location name="fathersex"/>
       <Location name="dinfather"/>
@@ -316,19 +337,6 @@
       <Location name="sisterQW"/>
       <Location name="dinsister"/>
       <Location name="family"/>
-      <Location name="Snpc"/>
-      <Location name="cumreaction"/>
-      <Location name="izdevat"/>
-      <Location name="kotovtalker"/>
-      <Location name="nogorslut"/>
-      <Location name="yesgorslut"/>
-      <Location name="Sgrup1"/>
-      <Location name="Sgrup2"/>
-      <Location name="Sgrup3"/>
-      <Location name="Sgrup4"/>
-      <Location name="Sgrup5"/>
-      <Location name="Sgrup"/>
-      <Location name="SgrupDisco"/>
     </Folder>
     <Folder name="Generic boyfriend">
       <Location name="Gnpc"/>
@@ -358,6 +366,7 @@
     <Folder name="Dima Nosov">
       <Location name="dimaRudeEv"/>
       <Location name="dimaHome"/>
+      <Location name="dimaRevenge"/>
       <Location name="dimaGoHome2"/>
       <Location name="dinnpc"/>
       <Location name="DimkaWarning"/>
@@ -473,7 +482,6 @@
       <Location name="pavCommercial"/>
       <Location name="pavCommercialOffices"/>
       <Location name="leonid"/>
-      <Location name="garmassiv"/>
       <Location name="gargazel"/>
       <Location name="garfather"/>
       <Location name="Gshveyfab"/>
@@ -487,22 +495,12 @@
       <Location name="DanceWhore7"/>
       <Location name="DanceWhore8"/>
       <Location name="soniaDisco"/>
-      <Location name="gschool_grounds"/>
-      <Location name="gschool_lessons"/>
-      <Location name="gschool_lunch"/>
-      <Location name="gschool_office"/>
-      <Location name="gschool_events"/>
-      <Location name="gschool_gossip"/>
-      <Location name="gschool_boys_bathroom"/>
-      <Location name="gschool_girls_bathroom"/>
-      <Location name="gschool_sex"/>
-      <Location name="gschool_detention"/>
       <Location name="gkafe"/>
       <Location name="motherkafeboss"/>
       <Location name="glake"/>
       <Location name="gLakeNude"/>
       <Location name="gLakeNudeEvent"/>
-      <Location name="gLakeNudeForest"/>	  
+      <Location name="gLakeNudeForest"/>
       <Location name="LakeBoyZ"/>
       <Location name="gpoli"/>
       <Location name="therapist"/>
@@ -530,6 +528,34 @@
       <Location name="MagEncounterFairy"/>
       <Location name="ParChurch"/>
       <Location name="ParChurch2"/>
+      <Location name="brothel"/>
+    </Folder>
+    <Folder name="School">
+      <Location name="gschool_grounds"/>
+      <Location name="gschool_lessons"/>
+      <Location name="gschool_lunch"/>
+      <Location name="gschool_office"/>
+      <Location name="gschool_events"/>
+      <Location name="gschool_gossip"/>
+      <Location name="gschool_boys_bathroom"/>
+      <Location name="gschool_girls_bathroom"/>
+      <Location name="gschool_sex"/>
+      <Location name="gschool_detention"/>
+      <Location name="gschool_randperson"/>
+      <Location name="Sgrup1"/>
+      <Location name="Sgrup2"/>
+      <Location name="Sgrup3"/>
+      <Location name="Sgrup4"/>
+      <Location name="Sgrup5"/>
+      <Location name="Sgrup"/>
+      <Location name="nogorslut"/>
+      <Location name="yesgorslut"/>
+    </Folder>
+    <Folder name="Shared_appartment">
+      <Location name="pavSharedApt"/>
+      <Location name="pavShared_gp"/>
+      <Location name="pavShared_nd"/>
+      <Location name="pavShared_sp"/>
     </Folder>
     <Folder name="House of Culture">
       <Location name="gdk"/>
@@ -549,6 +575,11 @@
       <Location name="krupo"/>
       <Location name="kruchess"/>
       <Location name="VoltrenerSexShower"/>
+      <Location name="Snpc"/>
+      <Location name="cumreaction"/>
+      <Location name="izdevat"/>
+      <Location name="kotovtalker"/>
+      <Location name="SgrupDisco"/>
     </Folder>
     <Folder name="Event gym town">
       <Location name="danceGev"/>
@@ -638,6 +669,7 @@
       <Location name="din_npc"/>
       <Location name="podezdM"/>
       <Location name="sexm"/>
+      <Location name="dateM"/>
       <Location name="kinoM"/>
       <Location name="parkM"/>
       <Location name="kafeM"/>
@@ -666,9 +698,6 @@
       <Location name="dorm"/>
       <Location name="downlibrary"/>
       <Location name="fit"/>
-      <Location name="foto"/>
-      <Location name="foto_albums"/>
-      <Location name="foto_models"/>
       <Location name="talent_agency"/>
       <Location name="lab"/>
       <Location name="tatiana_missions"/>
@@ -689,6 +718,13 @@
       <Location name="zoomagazine"/>
       <Location name="budgetclothes"/>
     </Folder>
+    <Folder name="Photo studio">
+      <Location name="foto"/>
+      <Location name="foto_events"/>
+      <Location name="foto_albums"/>
+      <Location name="foto_models"/>
+      <Location name="anastasia_escort"/>
+    </Folder>
     <Folder name="North Side">
       <Location name="Nord"/>
       <Location name="Terminal"/>
@@ -752,13 +788,11 @@
       <Location name="boyfrend"/>
       <Location name="boy_likes"/>
       <Location name="boylove"/>
-      <Location name="svi"/>
-      <Location name="svidan"/>
     </Folder>
     <Folder name="University">
       <Location name="island"/>
       <Location name="dolls"/>
-      <Location name="party"/>
+      <Location name="vecher"/>
       <Location name="obkitchen"/>
       <Location name="obroom"/>
       <Location name="Vika"/>
@@ -818,17 +852,9 @@
     <Folder name="Quest">
       <Location name="qwBarPolet"/>
       <Location name="qwBarPoletToilet"/>
-      <Location name="qwbereg"/>
-      <Location name="qwbereg2"/>
       <Location name="qwIzoldaApp"/>
       <Location name="qwloc"/>
-      <Location name="qwloc2"/>
-      <Location name="qwloc3"/>
-      <Location name="qwloc4"/>
       <Location name="qwmeet"/>
-      <Location name="qwmeet2"/>
-      <Location name="qwmeet3"/>
-      <Location name="qwpaluba"/>
     </Folder>
     <Folder name="Prostitution">
       <Location name="Prostitute"/>
@@ -874,16 +900,21 @@
       <Location name="Menu.Treatment"/>
     </Folder>
     <Folder name="Game Menu">
+      <Location name="$menu_setting"/>
       <Location name="$menu_skills"/>
       <Location name="$menu_descrip"/>
       <Location name="$menu_statistika"/>
+      <Location name="$menu_calendar"/>
       <Location name="$menu_reputation"/>
+      <Location name="$menu_traits"/>
       <Location name="$menu_mobila"/>
       <Location name="$menu_magic"/>
       <Location name="$menu_pain"/>
       <Location name="$menu_face"/>
       <Location name="$menu_body"/>
       <Location name="$menu_clothes"/>
+      <Location name="$menu_bra"/>
+      <Location name="$menu_panties"/>
       <Location name="$menu_shoes"/>
       <Location name="$menu_tattoos"/>
       <Location name="$menu_pirs"/>
@@ -906,7 +937,6 @@
       <Location name="balkon2"/>
       <Location name="dom_gor"/>
       <Location name="comendant"/>
-      <Location name="portmirror"/>
       <Location name="buklinik"/>
       <Location name="buklinik_event"/>
     </Folder>
@@ -928,6 +958,7 @@
       <Location name="$buy_item"/>
       <Location name="$buy_single_item"/>
       <Location name="$face_image"/>
+      <Location name="$body_image"/>
     </Folder>
     <Folder name="Female wrestling">
       <Location name="generation"/>

+ 2 - 6
locations/BDSM_Club

@@ -15,10 +15,8 @@ if $ARGS[0] = 'Hos':
 end
 
 if $ARGS[0] = 'start':
-	$metkaM = $ARGS[0]
-	$locM = $CURLOC
-	$metka = $ARGS[0]
-	$loc = $CURLOC
+	$metka = 'start'
+	$loc = 'BDSM_Club'
     $location_type = 'public_outdoors'
 	cls
 	minut += 10
@@ -177,8 +175,6 @@ if $ARGS[0] = 'd_start':
 end
 
 if $ARGS[0] = 'reception':
-	$metkaM = $ARGS[0]
-	$locM = $CURLOC
     $location_type = 'event'
 	cls
 	gs 'stat'

+ 16 - 16
locations/BDman

@@ -19,8 +19,8 @@ if $ARGS[0] = 'givi':
 	figurBoy = 2
 	!!0 - chest less 3, 1 breast 3-4, 2 breasts bigger 4
 	titBoy = 1
-	!!favorite hair color 0 - brunette, 1 - haired, 2 - Redhead, 3 - blonde
-	haerBoy = 3
+	!!favorite hair color 0 - black, 1 - brown, 2 - redhead, 3 - blonde
+	hairBoy = 3
 	!!character 0 - soft, 1 -norm 2 - aggressor
 	harakBoy = 2
 	!!perversity
@@ -47,8 +47,8 @@ if $ARGS[0] = 'ashot':
 	figurBoy = 2
 	!!0 - chest less 3, 1 breast 3-4, 2 breasts bigger 4
 	titBoy = 2
-	!!favorite hair color 0 - brunette, 1 - haired, 2 - Redhead, 3 - blonde
-	haerBoy = 3
+	!!favorite hair color 0 - black, 1 - brown, 2 - redhead, 3 - blonde
+	hairBoy = 3
 	!!character 0 - soft, 1 -norm 2 - aggressor
 	harakBoy = 2
 	!!perversity
@@ -75,8 +75,8 @@ if $ARGS[0] = 'arthur':
 	figurBoy = 2
 	!!0 - chest less 3, 1 breast 3-4, 2 breasts bigger 4
 	titBoy = 2
-	!!favorite hair color 0 - brunette, 1 - haired, 2 - Redhead, 3 - blonde
-	haerBoy = 3
+	!!favorite hair color 0 - black, 1 - brown, 2 - redhead, 3 - blonde
+	hairBoy = 3
 	!!character 0 - soft, 1 -norm 2 - aggressor
 	harakBoy = 2
 	!!perversity
@@ -103,8 +103,8 @@ if $ARGS[0] = 'abdula':
 	figurBoy = 2
 	!!0 - chest less 3, 1 breast 3-4, 2 breasts bigger 4
 	titBoy = 2
-	!!favorite hair color 0 - brunette, 1 - haired, 2 - Redhead, 3 - blonde
-	haerBoy = 3
+	!!favorite hair color 0 - black, 1 - brown, 2 - redhead, 3 - blonde
+	hairBoy = 3
 	!!character 0 - soft, 1 -norm 2 - aggressor
 	harakBoy = 2
 	!!perversity
@@ -131,8 +131,8 @@ if $ARGS[0] = 'hasan':
 	figurBoy = 2
 	!!0 - chest less 3, 1 breast 3-4, 2 breasts bigger 4
 	titBoy = 2
-	!!favorite hair color 0 - brunette, 1 - haired, 2 - Redhead, 3 - blonde
-	haerBoy = 3
+	!!favorite hair color 0 - black, 1 - brown, 2 - redhead, 3 - blonde
+	hairBoy = 3
 	!!character 0 - soft, 1 -norm 2 - aggressor
 	harakBoy = 2
 	!!perversity
@@ -159,8 +159,8 @@ if $ARGS[0] = 'kamil':
 	figurBoy = 2
 	!!0 - chest less 3, 1 breast 3-4, 2 breasts bigger 4
 	titBoy = 2
-	!!favorite hair color 0 - brunette, 1 - haired, 2 - Redhead, 3 - blonde
-	haerBoy = 3
+	!!favorite hair color 0 - black, 1 - brown, 2 - redhead, 3 - blonde
+	hairBoy = 3
 	!!character 0 - soft, 1 -norm 2 - aggressor
 	harakBoy = 2
 	!!perversity
@@ -187,8 +187,8 @@ if $ARGS[0] = 'aslan':
 	figurBoy = 2
 	!!0 - chest less 3, 1 breast 3-4, 2 breasts bigger 4
 	titBoy = 2
-	!!favorite hair color 0 - brunette, 1 - haired, 2 - Redhead, 3 - blonde
-	haerBoy = 3
+	!!favorite hair color 0 - black, 1 - brown, 2 - redhead, 3 - blonde
+	hairBoy = 3
 	!!character 0 - soft, 1 -norm 2 - aggressor
 	harakBoy = 2
 	!!perversity
@@ -215,8 +215,8 @@ if $ARGS[0] = 'muhtar':
 	figurBoy = 2
 	!!0 - chest less 3, 1 breast 3-4, 2 breasts bigger 4
 	titBoy = 2
-	!!favorite hair color 0 - brunette, 1 - haired, 2 - Redhead, 3 - blonde
-	haerBoy = 3
+	!!favorite hair color 0 - black, 1 - brown, 2 - redhead, 3 - blonde
+	hairBoy = 3
 	!!character 0 - soft, 1 -norm 2 - aggressor
 	harakBoy = 2
 	!!perversity

+ 3 - 46
locations/BDsex

@@ -497,7 +497,7 @@ if $ARGS[0] = 'end':
 		pcs_hairbsh = 1
 		pcs_makeup = 1
 		dynamic $showerdin
-		'<center><img <<$set_imgh>> src="images/shared/home/bathroom/dush.gif"></center>'
+		'<center><video src="images/shared/home/bathroom/dush.mp4"></center>'
 		'You go into the bathroom and turn on the shower, lathering body and washing as well as you can.'
 		act 'Leave':dynamic $brodilr
 	elseif harakBoy = 1:
@@ -788,57 +788,14 @@ if $ARGS[0] = 'an':
 	!!	!!gs 'BDsex', 'ancum'
 	!!end
 
-	if analplugin = 1:
-		!!WD:No Anal Lube if Anal Plug
-		!!analpluginbonus = 10
-		lubonus = 15
-		analplugin = 0
-		'<<$boydesc>> pulls the plug out of your narrow and tight ass.'
-		gs 'arousal', 'anal_dildo', 15, 'sub'
-		gs 'stat'
-	end
-
-	if dick < pcs_ass:pcs_ass += 1
-
-	if lubri = 0:
-		lubonus = 2
-		'You have no lube, forcing <<$boydesc>>  to spit on on his fingers, using saliva to lubricate your ass.'
-		gs 'arousal', 'anal_finger', 5, 'sub'
-		gs 'stat'
-	elseif lubri > 0:
-		lubri -= 1
-		lubonus = 10
-		'You take a tube of lubricant and hand it to the guy, watching as he he squeezes a little on his palm and rubs your anus.'
-		gs 'arousal', 'anal_finger', 5, 'sub'
-		gs 'stat'
-	end
-
-	if lubonus = 0:
-		if lubri > 0:
-			lubri -= 1
-			lubonus = 10
-			'You take a tube of lubricant and hand it to the guy, watching as he he squeezes a little on his palm and rubs your anus.'
-			gs 'arousal', 'anal_finger', 5, 'sub'
-			gs 'stat'
-		else
-			lubonus = 2
-			'You do not have any lubricant so <<$boydesc>> spits on his fingers and uses saliva to lubricate your ass.'
-			gs 'arousal', 'anal_finger', 5, 'sub'
-			gs 'stat'
-		end
-	end
-
+	gs 'dinsex','boy_wants_anal'
 	'<<$boydesc>> lays you on your stomach on the bed, spreading your ass apart as he begins to massage and open your anus with his fingers, first one, then two.'
 	gs 'arousal', 'anal_finger', 5, 'sub'
-	gs 'stat'
-	if pcs_ass < 10:'You groan in pain as his third finger invades your ass.'
-	if pcs_ass >= 10:'You feel your asshole stretch to accommodate his third finger.'
-
+	if pcs_ass < 10:'You groan in pain as his third finger invades your ass.' else 'You feel your asshole stretch to accommodate his third finger.'
 	'<<$boydesc>> abruptly pulls his fingers out of your ass and you feel his hard cock rest against your hole.'
 
 	if pcs_ass + lubonus < dick:'You scream and bite your lip at the sharp pain when the <<dick>> member centimetre enters your ass.'
 	if pcs_ass + lubonus >= dick:'You groan and a satisfying fullness spreads through you as the <<dick>> member centimeter dick forces its way into your ass.'
-
 	'<<$boydesc>> stops his assault for a moment, giving your ass time to adapt to the cock invading it before he starts you again, this time even more insistent.'
 	gs 'arousal', 'anal', 20, 'sub'
 	gs 'stat'

+ 21 - 21
locations/BelSex

@@ -34,7 +34,7 @@ if $ARGS[0] = 'bj1':
 	bj_temp += 1
 	belact -= 1
 	picrand = rand(0,12)
-	'<center><img src="images/shared/sex/blowjob/bj<<picrand>>.gif"></center>'
+	'<center><video src="images/shared/sex/blowjob/bj<<picrand>>.mp4"></center>'
 	'You take <<$boydesc>>''s <<dick>> cm cock in your mouth and begin stimulating his glans. You can clearly see on <<$boydesc>>''s face that he''s getting irritated at you for trying to prolonge things and just wants you to suck him off quickly.'
 	'You do your best to suck him off, trying to go deep as possible, but <<$boydesc>> is not pleased. He grabs you by the back of your head and begins forcing it closer and closer towards his fat stomach. You start gagging but he just tells you to relax your throat and it will all be fine.'
 
@@ -50,7 +50,7 @@ if $ARGS[0] = 'bj1':
 			gs 'cum_manage'
 			gs'stat'
 			picrand = rand(0,10)
-			'<center><img src="images/shared/sex/cum/mouth/cum<<picrand>>.gif"></center>'
+			'<center><video src="images/shared/sex/cum/mouth/cum<<picrand>>.mp4"></center>'
 			'<<$boydesc>> indicates that he''s about to come, telling you to "Open wide, <<$pcs_nickname>>. You''re going to swallow every little drop."'
 			'You meekly nod and let out "Yesh, Mr. Bely..." doing as he says, opening your mouth as wide as you can. He jerks himself off all over your face and you soon feel his warm jets of sperm landing on your left cheek. He adjusts his aim a bit and some of it ends up in your mouth as well. You decide to just sit there with your eyes closed and your mouth open until he tells you otherwise, doing your best to ignore the taste.'
 			gs 'arousal', 'end'
@@ -80,7 +80,7 @@ if $ARGS[0] = 'bj2':
 	bj_temp += 1
 	belact -= 1
 	picrand = rand(0,12)
-	'<center><img src="images/shared/sex/blowjob/bj<<picrand>>.gif"></center>'
+	'<center><video src="images/shared/sex/blowjob/bj<<picrand>>.mp4"></center>'
 	'You look at <<$boydesc>> with lust in your eyes. Dropping down on your knees without being asked, you unbutton his pants, exposing his full erect cock. Wrapping your <<$liptalk>> around his strong and warm cock, you quickly begin by sucking the head, caressing it with your tongue and lips.'
 	'<<$boydesc>> lets out a small groan, clearly enjoying himself. Turned on by seeing <<$boydesc>> enjoying the blowjob, you start sucking his cock while caressing his balls.'
 
@@ -96,7 +96,7 @@ if $ARGS[0] = 'bj2':
 			gs 'cum_manage'
 			gs'stat'
 			picrand = rand(0,10)
-			'<center><img src="images/shared/sex/cum/mouth/cum<<picrand>>.gif"></center>'
+			'<center><video src="images/shared/sex/cum/mouth/cum<<picrand>>.mp4"></center>'
 			'Redoubling your efforts, you reach the base of his wet cock with your <<$liptalk>>. <<$boydesc>> stares you in the face while your lips glide up and down on his hard dick. You know he must be close now.'
 			'You don''t want him to cum yet so you switch it up, using your tongue instead, sliding up and down his shaft, pulling out all of your tricks to make him feel good. You even use some techniques you learned to stall his orgasm for a moment, making it all the more intense for him when he shoots his load into your mouth.'
 			gs 'arousal', 'end'
@@ -126,7 +126,7 @@ if $ARGS[0] = 'bj3':
 	bj_temp += 1
 	belact -= 1
 	picrand = rand(0,12)
-	'<center><img src="images/shared/sex/blowjob/bj<<picrand>>.gif"></center>'
+	'<center><video src="images/shared/sex/blowjob/bj<<picrand>>.mp4"></center>'
 	'"Get down on your knees!" he commands. Unfazed by his boldness, you kneel down in front of him and lick up and down his length a few times before you take his <<dick>> cm cock into your mouth. As his cock enters, a rank odor enters your nostrils. You disregard the nasty aroma and begin moving your tongue around the head and you suck his dick as you start bobbing your head up and down while your hands take turns playing with his hairy balls. It''s hard for you to decide whether you want to move slowly and tease him, or speed up to avoid getting caught, but what you are doing seems to be to his liking.'
 	'"Good girl", he whispers, "I knew you could suck cock as soon as I saw you." His praise causes you to smile a little around his dick and you take him a little deeper in response.'
 	
@@ -142,7 +142,7 @@ if $ARGS[0] = 'bj3':
 			gs 'cum_manage'
 			gs'stat'
 			picrand = rand(0,10)
-			'<center><img src="images/shared/sex/cum/mouth/cum<<picrand>>.gif"></center>'
+			'<center><video src="images/shared/sex/cum/mouth/cum<<picrand>>.mp4"></center>'
 			'Instead, <<$boydesc>> starts jerking off, telling you "I''ll be done soon, <<$pcs_nickname>>. I want you to swallow every little drop." He doesn''t last much longer and cums all over your face.'
 			'He squeezes the last few drops of sperm into your mouth and then sticks his dick in your mouth. You swallow his cum obediently and then suck his dick clean, licking every tasty inch of it you can reach. Once he goes soft in your mouth, he pulls out his cock.' 
 			gs 'arousal', 'end'
@@ -172,7 +172,7 @@ if $ARGS[0] = 'vaginal1':
 	belact -= 1
 	sex_temp += 1
 	picrand = rand(0,7)
-	'<center><img src="images/characters/pavlovsk/vadim/sex/mitka<<picrand>>.gif"></center>'
+	'<center><video src="images/characters/pavlovsk/vadim/sex/mitka<<picrand>>.mp4"></center>'
 	'<<$boydesc>> lifts you up, grabs you by the hair, and shoves you onto the bed. You land on your back, as he quickly moves in, you spread your legs. He starts touching your pussy lips with his fat fingers, you let out a moan as he penetrates you with his finger.'
 	'"That''s enough, you''re all wet and ready now." he says. He grabs hold of his penis slowly slides his member into your wet cunt, softly parting your nether lips. As your pussy walls envelops his cock you let out a soft moan.'
 	'Hanging over you, looking into your eyes he starts build up quite a bit of speed. "You''re a pretty good fuck <<$pcs_nickname>>, but I''ve had better." he says as his sweat drips all over you.'
@@ -184,7 +184,7 @@ if $ARGS[0] = 'vaginal1':
 		gs 'cum_call', '', 'Bely'
 		gs 'cum_manage'
 		gs'stat'
-		'<center><img src="images/shared/sex/cum/vagcreampie/creampie3.gif"></center>'
+		'<center><video src="images/shared/sex/cum/vagcreampie/creampie3.mp4"></center>'
 		'<<$boydesc>>''s movements speed up as he keeps pounding you balls deep without showing any signs of slowing down. You think this will go on for a while, but suddenly you hear <<$boydesc>> grunting while cumming deep inside you.'
 		act'Take a shower':gt 'BelSex', 'shower'
 	end
@@ -207,7 +207,7 @@ if $ARGS[0] = 'vaginal2':
 	belact -= 1
 	sex_temp += 1
 	picrand = rand(0,7)
-	'<center><img src="images/characters/pavlovsk/vadim/sex/mitka<<picrand>>.gif"></center>'
+	'<center><video src="images/characters/pavlovsk/vadim/sex/mitka<<picrand>>.mp4"></center>'
 	'<<$boydesc>> lifts you up, grabs you by the hair, and shoves you onto the bed. His cock, well greased from the blowjob, easily slides into your pussy.' 
 	'You feel his glans stretching the inner walls of your pussy and you let out a loud moan with each penetration. As he keeps fucking you it doesn''t take long before you get accustomed to his movements.'
 	'"Let''s see how deep I can go," he says as he rams his cock so deep that your pubes touch. You scream out loud, breathing fast and heavily and he continues pounding you.'
@@ -219,7 +219,7 @@ if $ARGS[0] = 'vaginal2':
 		gs 'cum_call', '', 'Bely'
 		gs 'cum_manage'
 		gs'stat'
-		'<center><img src="images/shared/sex/cum/vagcreampie/creampie1.gif"></center>'
+		'<center><video src="images/shared/sex/cum/vagcreampie/creampie1.mp4"></center>'
 		'<<$boydesc>> groans loudly. His cock stiffens as you feel a jet of warm sperm hitting deep inside your womb.'
 		act'Take a shower':gt 'BelSex', 'shower'
 	end
@@ -242,7 +242,7 @@ if $ARGS[0] = 'doggy':
 	belact -= 1
 	sex_temp += 1
 	picrand = rand(1,5)
-	'<center><img src="images/shared/sex/vag/doggy/vagdog<<picrand>>.jpg"></center>'
+	'<center><img <<$set_imgh>> src="images/shared/sex/vag/doggy/vagdog<<picrand>>.jpg"></center>'
 	'With his cock rock hard and nicely wet he lifts your body, turns you around, and tells you to get on all fours on the floor. He gets down on his knees. Streching your butt cheeks slowly, he runs his shaft along your wet pussy, teasing you, all of a sudden he shoves his cock into your pussy and starts pounding away, not caring about your enjoyment. He just wants to fuck.'
 	'Holding you by the hips, he pounds on without slowing the pace, only occasionally stopping to catch a breath. "Isn''t he going to slow down soon?" you think to yourself. But you''ve underestimated him, instead he grabs your hair and pushes himself even deeper inside.'
 	'You moan loudly as he rams his cock deeper and deeper. You hear him panting and grunting he must''ve reached his limit...'
@@ -254,7 +254,7 @@ if $ARGS[0] = 'doggy':
 		gs 'cum_call', '', 'Bely'
 		gs 'cum_manage'
 		gs'stat'
-		'<center><img src="images/shared/sex/cum/vagcreampie/creampie4.gif"></center>'
+		'<center><video src="images/shared/sex/cum/vagcreampie/creampie4.mp4"></center>'
 		'<<$boydesc>> keeps on pounding you from behind. You feel his cock getting stiffer and twitching inside of you. You turn your head and look him in the eyes, pleading that he pulls out and cums on your ass instead. But <<$boydesc>> isn''t budging. He keeps on going, pulling your hips towards him, filling your womb with splashes of semen.'
 		act'Take a shower':gt 'BelSex', 'shower'
 	end
@@ -277,7 +277,7 @@ if $ARGS[0] = 'cowgirl':
 	belact -= 1
 	sex_temp += 1
 	picrand = rand(1,6)
-	'<center><img src="images/shared/sex/vag/cowgirl/vagcow<<picrand>>.gif"></center>'
+	'<center><img <<$set_imgh>> src="images/shared/sex/vag/cowgirl/vagcow<<picrand>>.jpg"></center>'
 	'<<$boydesc>> lies on the bed. He smirks as he tells you that you''ll be doing all the work today. You look at him, still a bit confused after the blowjob you''ve given him. Wasn''t that enough? "Don''t waste my time <<$pcs_nickname>>. Come here!" Not daring to do upset him even more, you crawl on top of <<$boydesc>> and guide his cock inside your vagina.'
 	'He grabs your hips, controlling the rhythm as you to ride him. He wants it fast. Fast, deep and hard, without any regard to you, or that he actually bumps into your cervix in this position. You keep riding him at the same rhythm as he moves his hands grabbing you breasts instead.'
 	'Unable to think of anything but the pleasure, you moan so loudly that you are almost screaming. Wanting to ride out this intense feeling, you completely forget that you’’re supposed to please <<$boydesc>> as you orgasm while riding him.'
@@ -290,7 +290,7 @@ if $ARGS[0] = 'cowgirl':
 		gs 'cum_call', '', 'Bely'
 		gs 'cum_manage'
 		gs'stat'
-		'<center><img src="images/shared/sex/cum/vagcreampie/creampie2.gif"></center>'
+		'<center><video src="images/shared/sex/cum/vagcreampie/creampie2.mp4"></center>'
 		'You keep switching the tempo as you ride <<$boydesc>>, from the looks on his face he''s ready to explode. You speed up even more wanting him to finish as soon as possible. As you''re thinking about pulling out not wanting him to cum inside you, you realize that you are too late. <<$boydesc>> suddenly explodes inside of you.'
 		act'Take a shower':gt 'BelSex', 'shower'
 	end
@@ -312,7 +312,7 @@ end
 if $ARGS[0] = 'anal1':
 	belact -= 1
 	anal_temp += 1
-	'<center><img src="images/shared/sex/anal/piledriver/kotovsexanal36.gif"></center>'
+	'<center><video src="images/shared/sex/anal/piledriver/kotovsexanal36.mp4"></center>'
 	'<<$boydesc>> begins rubbing the tip of his dick against you anus. Before you can even protest, his <<dick>> cm cock has already painfully penetrated your ass. You instinctively want to flinch away, but he grabs your hips with surprising strength and forces his dick as far into your ass as he can... before he starts hammering away.'
 	'"All the other girls I''ve fucked over the years loved getting their ass destroyed," he informs you between slaps of flesh against flesh. "I hope you don''t mind." The only response you manage to let out is a little squeak as if you''re giving him permission to continue on, not that he needs it.'
 	
@@ -324,7 +324,7 @@ if $ARGS[0] = 'anal1':
 		gs 'cum_manage'
 		gs'stat'
 		picrand = rand(1,2)
-		'<center><img src="images/shared/sex/cum/analcreampie/cumanal<<picrand>>.gif"></center>'
+		'<center><video src="images/shared/sex/cum/analcreampie/cumanal<<picrand>>.mp4"></center>'
 		'You can tell <<$boydesc>> is close to his orgasm. He huffs and puffs quite heavily now. Seconds later he firmly grabs your hips, his movements more erratic, and you feel his cock spasming inside you as he shoots his cum deep inside your asshole. The cum feels kind of warm inside you, and it slowly dribbles from you asshole once he pulls out his cock.'
 		
 		act'Take a shower':gt 'BelSex', 'shower'
@@ -335,7 +335,7 @@ if $ARGS[0] = 'anal2':
 	belact -= 1
 	anal_temp += 1
 	picrand = rand(30,34)
-	'<center><img src="images/shared/sex/anal/cowgirl/kotovsexanal<<picrand>>.gif"></center>'
+	'<center><video src="images/shared/sex/anal/cowgirl/kotovsexanal<<picrand>>.mp4"></center>'
 	'<<$boydesc>> lies on the bed, as you climb on top of him. <<$boydesc>> grabs hold of his cock, guiding his cock inside your tight anus.'
 	'You gasp as you start moving back and forth, controlling the rhythm as you ride him. First, slowly, as you adjust yourself. Soon enough you''re speeding up: fast, deep, and hard. You feel a sharp pain that quickly turns into a pleasant ache. You keep riding him at the same pace as he begins panting more and more.'
 	
@@ -346,7 +346,7 @@ if $ARGS[0] = 'anal2':
 		gs 'cum_call', 'anus', 'Bely'
 		gs 'cum_manage'
 		gs'stat'
-		'<center><img src="images/shared/sex/cum/analcreampie/analcum.jpg"></center>'
+		'<center><img <<$set_imgh>> src="images/shared/sex/cum/analcreampie/analcum.jpg"></center>'
 		'You can tell <<$boydesc>> is close to his orgasm. His cock is stiff and has gotten larger inside your anus. Seconds later he firmly grabs your hips and you feel his cock spasming inside you as he shoots his cum deep inside your asshole. The cum feels kind of warm inside you, and it slowly dribbles out as you get up off of him.'
 		
 		act'Take a shower':gt 'BelSex', 'shower'
@@ -357,7 +357,7 @@ if $ARGS[0] = 'analdoggy':
 	belact -= 1
 	anal_temp += 1
 	picrand = rand(0,12)
-	'<center><img src="images/shared/sex/anal/doggy<<picrand>>.gif"></center>'
+	'<center><video src="images/shared/sex/anal/doggy<<picrand>>.mp4"></center>'
 	'<<$boydesc>> pulls his cock out of your pussy and begins to slowly rub against your asshole. "Don''t worry, <<$pcs_nickname>>. I''ll be gentle," he says grinning as he has you on all fours, wide spread.'
 	'"Enough foreplay. Your ass is ready me!" he shouts as <<$boydesc>> starts pounding himself balls deep into you immediately. You bury your face into a pillow as he pounds your asshole roughly. The pain is unbearable and you flop with your legs trying to get away, but it only encourages <<$boydesc>> on as he keep pummeling your anus.'
 
@@ -368,7 +368,7 @@ if $ARGS[0] = 'analdoggy':
 		gs 'cum_call', 'anus', 'Bely'
 		gs 'cum_manage'
 		gs'stat'
-		'<center><img src="images/shared/sex/cum/analcreampie/kafeanpie.jpg"></center>'
+		'<center><img <<$set_imgh>> src="images/shared/sex/cum/analcreampie/kafeanpie.jpg"></center>'
 		'You''re at your limit and just as you want to beg him to take it easier, you feel him twitching behind you. All of a sudden you feel his warm cum shooting inside you. It slowly dribbles down your thighs as he pulls out of you.'
 		
 		act'Take a shower':gt 'BelSex', 'shower'
@@ -386,7 +386,7 @@ if $ARGS[0] = 'shower':
 		pcs_makeup = 1
 		if frost > 0:frost = 0
 		gs'stat'
-		'<center><img src="images/shared/home/bathroom/dush.gif"></center>'
+		'<center><video src="images/shared/home/bathroom/dush.mp4"></center>'
 		'You get into the nice, hot water stream of the shower and lather your body up with a soapy sponge. You carefully make sure to wash all of his cum that''s dripping out your holes, you then shampoo your hair and rinse that out as well. You''re squeaky clean now.'
 		act 'Get out of the bathroom':
 			if belgangPay <= 0:

File diff suppressed because it is too large
+ 458 - 212
locations/Cheatmenu_din


+ 1 - 1
locations/Cum_Manage

@@ -381,7 +381,7 @@ if $ARGS[0] = '':
 			sparrage[sparrtemp] = 0
 			sparrcnt[sparrtemp] = stat['cum_count']
 
-			if tanga = 0:
+			if $pantyworntype = 'none':
 
 				if spafinloc = 2:
 					spafinloc = 1

+ 9 - 2
locations/DNA

@@ -76,13 +76,20 @@ if $ARGS[0] = 'create':
 !!If no known parentage, generate a DNA string, as Tabula Rasa
 	icr = 0
 	:DNAloop
-		$DNA += str(rand(1000000000,2147483647))
+		$DNA += str(rand(0,9)) + mid(str(rand(1000000000,1999999999)),2,9)
 	if icr < 6:$DNA += ' ' & icr += 1 & jump 'DNAloop'
 	$RESULT = $DNA
 	killvar '$DNA'
 	killvar 'icr'
 end
 
+if $ARGS[0] = 'generateM':
+	$RESULT = mid($ARGS[1],12,11) + mid($ARGS[1],34,22) + mid(func('DNA','create'),1,43)
+end
+
+if $ARGS[0] = 'generateF':
+	$RESULT = mid($ARGS[1],23,11) + mid($ARGS[1],56,21) + ' ' + mid(func('DNA','create'),1,43)
+end
 
 if $ARGS[0] = 'generate':
 !!Creating its own DNA string from parent DNAs
@@ -101,7 +108,7 @@ if $ARGS[0] = 'generate':
 	$temp[4] = $mid ($dadDNA, 12, 10)
 	!!paternal grandfather ID
 	$temp[5] = $mid ($dadDNA, 23, 10)
-	$RESULT = str(rand(1000000000,2147483647)) + ' ' + $temp[0] + ' ' + $temp[1] + ' ' + $temp[2] + ' ' + $temp[3] + ' ' + $temp[4] + ' ' + $temp[5]
+	$RESULT = str(rand(0,9)) + mid(str(rand(1000000000,1999999999)),2,9) + ' ' + $temp[0] + ' ' + $temp[1] + ' ' + $temp[2] + ' ' + $temp[3] + ' ' + $temp[4] + ' ' + $temp[5]
 	killvar 'temp'
 	killvar 'momDNA'
 	killvar 'dadDNA'

+ 6 - 6
locations/DanceWhore3

@@ -10,7 +10,7 @@ act 'Get on your knees':
 	cls
 	guy += 1
 	gs 'stat'
-	'<center><img <<$set_imgh>> src="images/shared/sex/blowjob/kotovbj50.gif"></center>'
+	'<center><video src="images/shared/sex/blowjob/kotovbj50.mp4"></center>'
 	'Doing your best to show him what a good cock sucker you are, you lick him from base to tip, and then give the head a little kiss. He gives you a little chuckle of appreciation.'
 	'When you take him fully into you mouth you looks up seeking approval.'
 	'"That''s a good girl", he says stroking your cheek.'
@@ -25,7 +25,7 @@ act 'Get on your knees':
 		act 'Relax your throat':
 			cls
 			gs 'stat'
-			'<center><img <<$set_imgh>> src="images/locations/pavlovsk/resident/apartment/shulginhome/smroom/event/rought/oral4.gif"></center>'
+			'<center><video src="images/locations/pavlovsk/resident/apartment/shulginhome/smroom/event/rought/oral4.mp4"></center>'
 
 			if pcs_throat < dick / 2:
 				pcs_mood = 5
@@ -60,7 +60,7 @@ act 'Get on your knees':
 					gs 'cum_manage'
 					swallow += 1
 					gs 'stat'
-					'<center><img <<$set_imgh>> src="images/shared/sex/cum/cumf60.gif"></center>'
+					'<center><video src="images/shared/sex/cum/cumf60.mp4"></center>'
 					'You greedily suck down as much of his cum as for can.'
 					'By the time the time he is finished your entire face feels like a wet runny mess.'
 					gs 'arousal', 'bj', 10, 'sub', 'deepthroat'
@@ -78,7 +78,7 @@ act 'Get on your knees':
 					facial += 1
 					minut += 10
 					gs 'stat'
-					'<center><img <<$set_imgh>> src="images/shared/sex/cum/cumf10.gif"></center>'
+					'<center><video src="images/shared/sex/cum/cumf10.mp4"></center>'
 					'You look him in the eye, and softly whisper: "Give it to me."'
 					'Warm jets of semen begin to splatter against your face. You make little sounds of encouragement, until with a groan, he finishes with one last spurt that hits you right on the lips.'
 					gs 'arousal', 'end'
@@ -95,7 +95,7 @@ act 'Get on your knees':
 			spafinloc = 3
 			gs 'cum_manage'
 			gs 'stat'
-			'<center><img <<$set_imgh>> src="images/locations/pavlovsk/resident/apartment/shulginhome/smroom/event/dog12.gif"></center>'
+			'<center><video src="images/locations/pavlovsk/resident/apartment/shulginhome/smroom/event/dog12.mp4"></center>'
 			'You give it a wiggle, and he says smiling: "Ha, now that''s a good girl."' 
 			dynamic $sexstart
 			dynamic $analsex
@@ -109,7 +109,7 @@ act 'Get on your knees':
 		'He speaks: "On your back now, girl. Let''s see that pretty little pussy of yours."'
 		act 'Spread your legs for him':
 			cls
-			'<center><img <<$set_imgh>> src="images/shared/sex/vag/miss/kotovsexbonus2.gif"></center>'
+			'<center><video src="images/shared/sex/vag/miss/kotovsexbonus2.mp4"></center>'
 			'Laying on your back a little thrill runs though your body, as the rough Armenian prepares to enter you.'
 			dynamic $sexstart
 			dynamic $sexstart2

+ 5 - 5
locations/DanceWhore4

@@ -31,7 +31,7 @@ act 'Show them':
 		act 'Get spit-roasted':
 			cls
 			gs 'stat'
-			'<center><img <<$set_imgh>> src="images/shared/sex/group/threesomepm8.gif"></center>'
+			'<center><video src="images/shared/sex/group/threesomepm8.mp4"></center>'
 			'You let out another playful bleat as you begin to get filled.'
 			dynamic $sexstart
 			dynamic $analsex
@@ -70,7 +70,7 @@ act 'Show them':
 					minut += 10
 					gs 'arousal', 'end'
 					gs 'stat'
-					'<center><img <<$set_imgh>> src="images/locations/pavlovsk/park/gop/sex/oral/cum/gif/cumf2.gif"></center>'
+					'<center><video src="images/locations/pavlovsk/park/gop/sex/oral/cum/gif/cumf2.mp4"></center>'
 					'Cum splatters into your mouth, and across your face. It doesn''t stop until it''s dripping from your face.'
 					'"Well done, little lamb", the man behind you praises, giving you a little smack on the ass.'
 					act 'Call a taxi': gt 'gdksport', 'cab_home'
@@ -84,7 +84,7 @@ act 'Show them':
 		act 'Enjoy':
 			cls
 			gs 'stat'
-			'<center><img <<$set_imgh>> src="images/shared/sex/group/threesomepm10.gif"></center>'
+			'<center><video src="images/shared/sex/group/threesomepm10.mp4"></center>'
 			'As you take one man''s cock into your mouth, as the man between your legs chuckles: "Wonderful, it looks like you have already been sheared."'
 			dynamic $sexstart
 			dynamic $sexstart2
@@ -109,7 +109,7 @@ act 'Show them':
 					minut += 10
 					gs 'arousal', 'end'
 					gs 'stat'
-					'<center><img <<$set_imgh>> src="images/locations/pavlovsk/resident/apartment/shulginhome/smroom/event/rought/oral1.gif"></center>'
+					'<center><video src="images/locations/pavlovsk/resident/apartment/shulginhome/smroom/event/rought/oral1.mp4"></center>'
 					'Choking slightly you frantically swallow cum, until his cock finishes pouring his seed down your throat.'
 					act 'Drive back': gt 'gdksport', 'cab_home'
 				end
@@ -124,7 +124,7 @@ act 'Show them':
 					minut += 10
 					gs 'arousal', 'end'
 					gs 'stat'
-					'<center><img <<$set_imgh>> src="images/locations/pavlovsk/park/gop/sex/oral/cum/gif/cumf2.gif"></center>'
+					'<center><video src="images/locations/pavlovsk/park/gop/sex/oral/cum/gif/cumf2.mp4"></center>'
 					'Cum splatters into your mouth, and across your face. It doesn''t stop until it''s dripping from your chin.'
 					act 'Call a taxi': gt 'gdksport', 'cab_home'
 				end

+ 1 - 1
locations/DanceWhore6

@@ -9,7 +9,7 @@ npc_Malen[$npclastgenerated] = rand(10,15)
 
 gs 'stat'
 '<center>your thoughts</center>'
-'<center><img <<$set_imgh>> src="images/shared/home/tv/seeporn.gif"></center>'
+'<center><video src="images/shared/home/tv/seeporn.mp4"></center>'
 'As the big black guy leads you into the room, your mind drifts to what you have seen watching porn.'
 'The thought of actually being one of those little white girls talking big black cock sends a thrill through you.'
 'You hope this guy lives up to the hype.'

+ 1 - 1
locations/DanceWhore7

@@ -13,7 +13,7 @@ npc_Malen[$npclastgenerated] = rand(10,15)
 
 gs 'stat'
 '<center>your thoughts</center>'
-'<center><img <<$set_imgh>> src="images/shared/home/tv/seeporn.gif"></center>'
+'<center><video src="images/shared/home/tv/seeporn.mp4"></center>'
 'As the two big black guys lead you into the room, your mind drifts to what you have seen watching porn.'
 'The thought of actually being one of those little white girls talking big black cock sends a thrill through you.'
 'Taking care of two at the same time sounds even more delightfully naughty.'

+ 1 - 1
locations/DanceWhore8

@@ -19,7 +19,7 @@ npc_Malen[$npclastgenerated] = rand(10,15)
 
 gs 'stat'
 '<center>your thoughts</center>'
-'<center><img <<$set_imgh>> src="images/shared/home/tv/seeporn.gif"></center>'
+'<center><video src="images/shared/home/tv/seeporn.mp4"></center>'
 'This is just like one of those movies you''ve seen. Three big black guys leading a young little white girl into a hotel room, oh whatever will you do?'
 '"Let''s get this party started boys", you say smiling, as you take of your top.'
 '"Aren''t you just an eager little minx", one of the men laughs, as they begin to take off their pants.'

Some files were not shown because too many files changed in this diff