code:
using HarmonyLib;
using RimWorld;
using rjw;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using Verse.AI;

namespace Rimworld_Animations
{
    [HarmonyPatch(typeof(JobDriver_Sex), "SexTick")]
    public class HarmonyPatch_SexTick
    {
        public static bool Prefix(JobDriver_Sex __instance, Pawn pawn, Thing target)
        {

			if ((target is Pawn) &&
				!(
				(target as Pawn)?.jobs?.curDriver is JobDriver_SexBaseReciever
				&&
				((target as Pawn).jobs.curDriver as JobDriver_SexBaseReciever).parteners.Any()
				&&
				((target as Pawn).jobs.curDriver as JobDriver_SexBaseReciever).parteners[0] == pawn))
            {

				__instance.ticks_left--;
                __instance.sex_ticks--;
                __instance.Orgasm();

				if (pawn.IsHashIntervalTick(__instance.ticks_between_thrusts))
				{
					__instance.ChangePsyfocus(pawn, target);
					__instance.Animate(pawn, target);
					__instance.PlaySexSound();
					if (!__instance.isRape)
					{
						pawn.GainComfortFromCellIfPossible(false);
						if (target is Pawn)
						{
							(target as Pawn).GainComfortFromCellIfPossible(false);
						}
					}
					if(!__instance.isEndytophile)
                    {
						SexUtility.DrawNude(pawn, false);
                    }
				}

				return false;
            }

            return true;
        }

    }

}


code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using rjw;
using HarmonyLib;
using Verse;
using RimWorld;
using Verse.AI;

namespace Rimworld_Animations {

    [HarmonyPatch(typeof(WorkGiver_Sex), "JobOnThing")]
    public static class HarmonyPatch_WorkGiverSex {

        public static bool Prefix(ref Job __result, ref Thing t) {

            Building_Bed bed = RestUtility.CurrentBed(t as Pawn);
            if (bed == null) {
                return false;
            }
            __result = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("JoinInBedAnimation", true), t as Pawn, bed);
            return false;

        }

    }
}

license: unknown


code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using UnityEngine;
using RimWorld;

namespace Rimworld_Animations {

    public class AnimationSettings : ModSettings {

        public static bool orgasmQuiver, rapeShiver, soundOverride = true, hearts = true, controlGenitalRotation = false, applySemenOnAnimationOrgasm = false, fastAnimForQuickie = false;
        public static bool offsetTab = false, debugMode = false;
        public static float shiverIntensity = 2f;

        public static Dictionary<string, Vector2> offsets = new Dictionary<string, Vector2>();
        public static Dictionary<string, float> rotation = new Dictionary<string, float>();

        public override void ExposeData() {

            base.ExposeData();

            Scribe_Values.Look(ref debugMode, "RJWAnimations-AnimsDebugMode", false);
            Scribe_Values.Look(ref offsetTab, "RJWAnimations-EnableOffsetTab", false);
            Scribe_Values.Look(ref controlGenitalRotation, "RJWAnimations-controlGenitalRotation", false);
            Scribe_Values.Look(ref orgasmQuiver, "RJWAnimations-orgasmQuiver");
            Scribe_Values.Look(ref fastAnimForQuickie, "RJWAnimations-fastAnimForQuickie");
            Scribe_Values.Look(ref rapeShiver, "RJWAnimations-rapeShiver");
            Scribe_Values.Look(ref hearts, "RJWAnimation-sheartsOnLovin");
            Scribe_Values.Look(ref applySemenOnAnimationOrgasm, "RJWAnimations-applySemenOnOrgasm", false);
            Scribe_Values.Look(ref soundOverride, "RJWAnimations-rjwAnimSoundOverride", true);
            Scribe_Values.Look(ref shiverIntensity, "RJWAnimations-shiverIntensity", 2f);
            //todo: save offsetsByDefName

            Scribe_Collections.Look(ref offsets, "RJWAnimations-animationOffsets");
            Scribe_Collections.Look(ref rotation, "RJWAnimations-rotationOffsets");

            //needs to be rewritten
            //probably somewhere in options?

        }

    }

    public class RJW_Animations : Mod {

        public RJW_Animations(ModContentPack content) : base(content) {
            GetSettings<AnimationSettings>();

        }

        public override void DoSettingsWindowContents(Rect inRect) {

            Listing_Standard listingStandard = new Listing_Standard();
            listingStandard.Begin(inRect);

            listingStandard.CheckboxLabeled("Enable Sound Override", ref AnimationSettings.soundOverride);
            listingStandard.CheckboxLabeled("Control Genital Rotation", ref AnimationSettings.controlGenitalRotation);
            listingStandard.CheckboxLabeled("Play Fast Animation for Quickie", ref AnimationSettings.fastAnimForQuickie);
            listingStandard.CheckboxLabeled("Apply Semen on Animation Orgasm", ref AnimationSettings.applySemenOnAnimationOrgasm);

            if(AnimationSettings.applySemenOnAnimationOrgasm) {
                listingStandard.Label("Recommended--turn down \"Cum on body percent\" in RJW settings to about 33%");
            }

            listingStandard.CheckboxLabeled("Enable Orgasm Quiver", ref AnimationSettings.orgasmQuiver);
            listingStandard.CheckboxLabeled("Enable Rape Shiver", ref AnimationSettings.rapeShiver);
            listingStandard.CheckboxLabeled("Enable hearts during lovin'", ref AnimationSettings.hearts);

            listingStandard.CheckboxLabeled("Enable Animation Manager Tab", ref AnimationSettings.offsetTab);

            listingStandard.Label("Shiver/Quiver Intensity (default 2): " + AnimationSettings.shiverIntensity);
            AnimationSettings.shiverIntensity = listingStandard.Slider(AnimationSettings.shiverIntensity, 0.0f, 12f);

            listingStandard.CheckboxLabeled("Debug Mode", ref AnimationSettings.debugMode);

            listingStandard.End();
            base.DoSettingsWindowContents(inRect);
        }

        public override void WriteSettings() {
            base.WriteSettings();
            OffsetMainButtonDefOf.OffsetManager.buttonVisible = AnimationSettings.offsetTab;

        }

        public override string SettingsCategory() {
            return "RJW Animation Settings";
        }
    }
}


code:
*.rtf	 diff=astextplain
*.RTF	 diff=astextplain
*.txt	 diff
*.TXT	 diff

repo_name: Tcallas/game

path: .gitattributes


code:
[General]
ignoreCRC=true


code:
@ECHO off

:: Set those lines to fit your setup.
:: This is where glife.qsp will be copied. If you don't want to move it just comment (::) the line below.
:: 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=..\game\engine\jack.exe
set QGEN=qgen.exe

:: The file that will be generated or open
set QSPFILE=..\game\jack.qsp

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:menu
cls
echo.
echo :: QSP Compiler and Launcher
echo.

if defined QGEN (
	if not exist "%QGEN%" (
		echo QGEN     : [ERROR] - %QGEN%  not found. Using DEFAULT application.
		set QGEN=
	) else ( echo QGEN     : [OK] - "%QGEN%")
) else echo QGEN     : [NOT DEFINED] - Using DEFAULT application.

if defined QSPGUI (
	if not exist "%QSPGUI%" (
		echo QSP EXEC : [ERROR] - %QSPGUI% not found.
		set QSPGUI=
	) else ( echo QSP EXEC : [OK] - "%QSPGUI%")
) else ( echo QSP EXEC : [NOT DEFINED] - Using Windows DEFAULT.)

if defined QSPFILE (
	if not exist "%QSPFILE%" (
		echo QSP FILE : [WARNING] - %QSPFILE% not found.
	) else ( echo QSP FILE : [OK] - "%QSPFILE%")
) else ( echo QSP FILE : [NOT DEFINED] - ERROR: CAN'T CONTINUE.)

if defined CP_TO (
	if not exist "%CP_TO%" (
		echo COPY     : [ERROR] - Destination "%CP_TO%" not found. Copy DISABLED.
		set CP_TO=
	) else ( echo COPY     : [OK] - "%CP_TO%")
) else (  echo COPY     : [DISABLED] )

echo.

if defined NOT_FOUND (
	echo ERROR: Option '%action%' wasn't recognized. Is it lowercase?
	set NOT_FOUND=
)

echo.
echo ACTIONS: (B)uild  (R)un  (F)ull  (Q)Gen  (E)xit
echo.
set /p action=Choose an action:

if defined QSPFILE (
	if %action% == b goto build
	if %action% == r goto run
	if %action% == f goto build
	if %action% == d goto build
	if %action% == q goto qgen
)

if %action% == e goto exit

set NOT_FOUND=1
goto menu

:build
echo.
echo Building ...

@ECHO ON
python txtmerge.py
txt2gam.exe jack.txt %QSPFILE% > txt2gam.log
@ECHO OFF

echo.
if defined CP_TO ( echo Copying %QSPFILE% to "%CP_TO%" ... & copy %QSPFILE% %CP_TO% > nul )

echo.
echo Done.
pause
if %action% == d ( goto run )
if %action% == f ( goto run ) else ( goto menu )

:qgen
echo.
echo Running ...
if defined CP_TO ( start %QGEN% %CP_TO%\%QSPFILE% ) else ( start %QGEN% %QSPFILE% )
goto exit

:run
echo.
echo Running ...

::if defined CP_TO ( start %QSPGUI% %CP_TO%\%QSPFILE% ) else ( start %QSPGUI% %QSPFILE% )
::if defined CP_TO ( start %QSPGUI% %CP_TO%\%QSPFILE% ) else ( cd .. & Jack-o-nine-tails.exe )
if %action% == d ( start %QSPGUI% %QSPFILE% ) else ( cd .. & Jack-o-nine-tails.exe )
:exit


code:
<?xml version="1.0" encoding="utf-8"?>
<QGen-keywords>
  <Statements>
    <Keyword name="pl" desc="PL [выражение] / *PL [выражение] - вывод текста в дополнительное / основное окно описания, затем переход на новую строку"/>
    <Keyword name="clear" desc="CLEAR / *CLEAR - очистка дополнительного / основного окна описания"/>
    <Keyword name="clr" desc="CLR / *CLR - очистка дополнительного / основного окна описания"/>
    <Keyword name="p" desc="P [выражение] / *P [выражение] - вывод текста в дополнительное / основное окно описания"/>
    <Keyword name="nl" desc="NL [выражение] / *NL [выражение] - переход на новую строку, затем вывод текста в дополнительное / основное окно описания"/>
    <Keyword name="msg" desc="MSG [выражение] - вывод сообщения в информационном окне"/>
    <Keyword name="wait" desc="WAIT [#выражение] - остановка выполнения программы на заданное количество миллисекунд"/>
    <Keyword name="act" desc="ACT [$название],[$путь к изображению]:[оператор] & [оператор] & ... - добавление действия"/>
    <Keyword name="delact" desc="DELACT [$название] / DEL ACT [$название] - удаление действия"/>
    <Keyword name="cla" desc="CLA - очистка списка действий"/>
    <Keyword name="cmdclear" desc="CMDCLEAR - очистка строки ввода"/>
    <Keyword name="cmdclr" desc="CMDCLEAR - очистка строки ввода"/>
    <Keyword name="cls" desc="CLS - очищает экран, оставляя только список предметов"/>
    <Keyword name="menu" desc="MENU [$выражение] - показ меню с заданным названием"/>
    <Keyword name="settimer" desc="SETTIMER [#выражение] - задает интервал таймера для локации-счетчика"/>
    <Keyword name="dynamic" desc="DYNAMIC [$строка кода],[параметр 1],[параметр 2], ... - динамическое выполнение кода"/>
    <Keyword name="set" desc="SET [название переменной]=[выражение] - установка значения переменной"/>
    <Keyword name="let" desc="LET [название переменной]=[выражение] - установка значения переменной"/>
    <Keyword name="killvar" desc="KILLVAR [$название],[#индекс] - удаление всех переменных / указанной переменной"/>
    <Keyword name="copyarr" desc="COPYARR [$массив-приемник],[$массив-источник] - копирование содержимого массива в другой массив"/>
    <Keyword name="addobj" desc="ADDOBJ [$название],[$путь к изображению],[#позиция] / ADD OBJ [$название],[$путь к изображению],[#позиция] - добавление предмета"/>
    <Keyword name="delobj" desc="DELOBJ [$название] / DEL OBJ [$название] - удаление предмета"/>
    <Keyword name="killobj" desc="KILLOBJ [#позиция] - удаление всех предметов / предмета в заданной позиции"/>
    <Keyword name="unselect" desc="UNSELECT - отмена выбора предмета"/>
    <Keyword name="unsel" desc="UNSEL - отмена выбора предмета"/>
    <Keyword name="killall" desc="KILLALL - удаление всех переменных и предметов"/>
    <Keyword name="opengame" desc="OPENGAME [$выражение] - загрузка состояния игры"/>
    <Keyword name="openqst" desc="OPENQST [$выражение] - открытие и запуск файла игры"/>
    <Keyword name="addqst" desc="ADDQST [$выражение] - добавление локаций из указанного файла"/>
    <Keyword name="killqst" desc="KILLQST - удаление всех добавленных через ADDQST локаций"/>
    <Keyword name="savegame" desc="SAVEGAME [$выражение] - сохранение состояния игры"/>
    <Keyword name="refint" desc="REFINT - обновление интерфейса"/>
    <Keyword name="showacts" desc="SHOWACTS [#выражение] - показ / скрытие списка действий"/>
    <Keyword name="showinput" desc="SHOWINPUT [#выражение] - показ / скрытие строки ввода"/>
    <Keyword name="showobjs" desc="SHOWOBJS [#выражение] - показ / скрытие списка предметов"/>
    <Keyword name="showstat" desc="SHOWSTAT [#выражение] - показ / скрытие дополнительного окна описания"/>
    <Keyword name="if" desc="IF [#выражение]:[оператор1] & [оператор2] & ... ELSE [оператор3] & [оператор4] & ... - условие"/>
    <Keyword name="else" desc="IF [#выражение]:[оператор1] & [оператор2] & ... ELSE [оператор3] & [оператор4] & ... - условие"/>
    <Keyword name="elseif" desc="ELSEIF [#выражение]:[оператор1] & [оператор2] & ... - альтернативное условие"/>
    <Keyword name="exit" desc="EXIT - завершение выполнения текущего кода"/>
    <Keyword name="end" desc="END - завершение многострочной формы IF / ACT"/>
    <Keyword name="jump" desc="JUMP [$выражение] - переход на указанную метку"/>
    <Keyword name="gosub" desc="GOSUB [$выражение],[параметр 1],[параметр 2], ... - обработка указанной локации"/>
    <Keyword name="gs" desc="GS [$выражение],[параметр 1],[параметр 2], ... - обработка указанной локации"/>
    <Keyword name="goto" desc="GOTO [$выражение],[параметр 1],[параметр 2], ... - переход на указанную локацию"/>
    <Keyword name="gt" desc="GT [$выражение],[параметр 1],[параметр 2], ... - переход на указанную локацию"/>
    <Keyword name="xgoto" desc="XGOTO [$выражение],[параметр 1],[параметр 2], ... - переход на указанную локацию без очистки основного окна описания"/>
    <Keyword name="xgt" desc="XGT [$выражение],[параметр 1],[параметр 2], ... - переход на указанную локацию без очистки основного окна описания"/>
    <Keyword name="play" desc="PLAY [$путь к звуковому файлу],[#громкость] - воспроизведение звукового файла с заданной громкостью"/>
    <Keyword name="close" desc="CLOSE [$путь к звуковому файлу] / CLOSE ALL - остановка проигрывания звукового файла / всех звуковых файлов"/>
    <Keyword name="view" desc="VIEW [$путь к графическому файлу] - просмотр изображения"/>
  </Statements>
  <Expressions>
    <Keyword name="and" desc="[#выражение 1] AND [#выражение 2] - логическое "и=""/>
    <Keyword name="or" desc="[#выражение 1] OR [#выражение 2] - логическое "или""/>
    <Keyword name="obj" desc="OBJ [$предмет] - проверка наличия предмета в рюкзаке"/>
    <Keyword name="loc" desc="LOC [$локация] - проверка существования локации"/>
    <Keyword name="no" desc="NO [#выражение] - отрицание"/>
    <Keyword name="mod" desc="[#выражение 1] MOD [#выражение 2] - вычисление остатка от деления"/>
    <Keyword name="desc" desc="DESC([$выражение]) - возвращает текст базового описания локации"/>
    <Keyword name="$desc" desc="$DESC([$выражение]) - возвращает текст базового описания локации"/>
    <Keyword name="iif" desc="IIF([#выражение],[выражение_да],[выражение_нет]) - возвращает одно из выражений по условию"/>
    <Keyword name="$iif" desc="$IIF([#выражение],[выражение_да],[выражение_нет]) - возвращает одно из выражений по условию"/>
    <Keyword name="input" desc="INPUT([выражение]) - показывает окно ввода текста и возвращает введенное значение"/>
    <Keyword name="$input" desc="$INPUT([выражение]) - показывает окно ввода текста и возвращает введенное значение"/>
    <Keyword name="isplay" desc="ISPLAY([$выражение]) - проверяет, проигрывается ли в текущий момент указанный файл"/>
    <Keyword name="max" desc="MAX([выражение 1],[выражение 2], ...) - возвращает максимальное из значений аргументов"/>
    <Keyword name="$max" desc="$MAX([выражение 1],[выражение 2], ...) - возвращает максимальное из значений аргументов"/>
    <Keyword name="min" desc="MIN([выражение 1],[выражение 2], ...) - возвращает минимальное из значений аргументов"/>
    <Keyword name="$min" desc="$MIN([выражение 1],[выражение 2], ...) - возвращает минимальное из значений аргументов"/>
    <Keyword name="rand" desc="RAND([#выражение 1],[#выражение 2]) - возвращает случайное число между заданными"/>
    <Keyword name="rgb" desc="RGB([#красный],[#зеленый],[#синий]) - возвращает код цвета на основе 3-х составляющих"/>
    <Keyword name="getobj" desc="GETOBJ([#позиция]) - возвращает название предмета, расположенного в заданной позиции"/>
    <Keyword name="$getobj" desc="$GETOBJ([#позиция]) - возвращает название предмета, расположенного в заданной позиции"/>
    <Keyword name="dyneval" desc="DYNEVAL([$выражение],[параметр 1],[параметр 2], ...) - возвращает значение динамически вычисленного выражения"/>
    <Keyword name="$dyneval" desc="$DYNEVAL([$выражение],[параметр 1],[параметр 2], ...) - возвращает значение динамически вычисленного выражения"/>
    <Keyword name="func" desc="FUNC([$выражение],[параметр 1],[параметр 2], ...) - обработка указанной локации как функции"/>
    <Keyword name="$func" desc="$FUNC([$выражение],[параметр 1],[параметр 2], ...) - обработка указанной локации как функции"/>
    <Keyword name="arrsize" desc="ARRSIZE([$выражение]) - возвращает число элементов в указанном массиве"/>
    <Keyword name="arrpos" desc="ARRPOS([#начальный индекс],[$имя массива],[значение]) - поиск в массиве элемента с заданным значением"/>
    <Keyword name="instr" desc="INSTR([#начальная позиция],[$текст],[$искомый текст]) - поиск вхождения текста"/>
    <Keyword name="isnum" desc="ISNUM([$выражение]) - проверяет, является ли указанная строка числом"/>
    <Keyword name="trim" desc="TRIM([$выражение]) - удаляет из текста прилегающие пробелы и символы табуляции"/>
    <Keyword name="$trim" desc="$TRIM([$выражение]) - удаляет из текста прилегающие пробелы и символы табуляции"/>
    <Keyword name="ucase" desc="UCASE([$выражение]) - преобразует маленькие буквы текста в большие"/>
    <Keyword name="$ucase" desc="$UCASE([$выражение]) - преобразует маленькие буквы текста в большие"/>
    <Keyword name="lcase" desc="LCASE([$выражение]) - преобразует большие буквы текста в маленькие"/>
    <Keyword name="$lcase" desc="$LCASE([$выражение]) - преобразует большие буквы текста в маленькие"/>
    <Keyword name="len" desc="LEN([$выражение]) - возвращает длину указанной строки"/>
    <Keyword name="mid" desc="MID([$текст],[#начало],[#длина]) - вырезает из текста строку указанной длины начиная с заданной позиции"/>
    <Keyword name="$mid" desc="$MID([$текст],[#начало],[#длина]) - вырезает из текста строку указанной длины начиная с заданной позиции"/>
    <Keyword name="replace" desc="REPLACE([$текст],[$искомый текст],[$текст для замены]) - заменяет в тексте заданную строку"/>
    <Keyword name="$replace" desc="$REPLACE([$текст],[$искомый текст],[$текст для замены]) - заменяет в тексте заданную строку"/>
    <Keyword name="str" desc="STR([#выражение]) - переводит число в строку"/>
    <Keyword name="$str" desc="$STR([#выражение]) - переводит число в строку"/>
    <Keyword name="val" desc="VAL([$выражение]) - переводит строку в число"/>
    <Keyword name="arrcomp" desc="ARRCOMP([#начальный индекс],[$имя массива],[$шаблон]) - поиск в массиве элемента, соответствующего регулярному выражению"/>
    <Keyword name="strcomp" desc="STRCOMP([$выражение],[$шаблон]) - проверяет заданный текст на соответствие регулярному выражению"/>
    <Keyword name="strfind" desc="STRFIND([$выражение],[$шаблон],[#номер]) - возвращает подстроку, соответствующую группе с номером [#номер] регулярного выражения"/>
    <Keyword name="$strfind" desc="$STRFIND([$выражение],[$шаблон],[#номер]) - возвращает подстроку, соответствующую группе с номером [#номер] регулярного выражения"/>
    <Keyword name="strpos" desc="STRPOS([$выражение],[$шаблон],[#номер]) - возвращает позицию подстроки, соответствующей группе с номером [#номер] регулярного выражения"/>
    <Keyword name="countobj" desc="COUNTOBJ - возвращает текущее число предметов"/>
    <Keyword name="msecscount" desc="MSECSCOUNT - возвращает количество миллисекунд, прошедших с момента начала игры"/>
    <Keyword name="rnd" desc="RND - возвращает случайное значение от 1 до 1000"/>
    <Keyword name="curloc" desc="CURLOC - возвращает название текущей локации"/>
    <Keyword name="$curloc" desc="$CURLOC - возвращает название текущей локации"/>
    <Keyword name="qspver" desc="QSPVER - возвращает версию интерпретатора"/>
    <Keyword name="$qspver" desc="$QSPVER - возвращает версию интерпретатора"/>
    <Keyword name="selobj" desc="SELOBJ - возвращает название выделенного предмета"/>
    <Keyword name="$selobj" desc="$SELOBJ - возвращает название выделенного предмета"/>
    <Keyword name="selact" desc="SELACT - возвращает название выделенного действия"/>
    <Keyword name="$selact" desc="$SELACT - возвращает название выделенного действия"/>
    <Keyword name="curacts" desc="CURACTS - возвращает в виде кода все текущие действия"/>
    <Keyword name="$curacts" desc="$CURACTS - возвращает в виде кода все текущие действия"/>
    <Keyword name="user_text" desc="USER_TEXT - возвращает текст в строке ввода"/>
    <Keyword name="$user_text" desc="$USER_TEXT - возвращает текст в строке ввода"/>
    <Keyword name="usrtxt" desc="USRTXT - возвращает текст в строке ввода"/>
    <Keyword name="$usrtxt" desc="$USRTXT - возвращает текст в строке ввода"/>
    <Keyword name="maintxt" desc="MAINTXT - возвращает текст в основном окне описания"/>
    <Keyword name="$maintxt" desc="$MAINTXT - возвращает текст в основном окне описания"/>
    <Keyword name="stattxt" desc="STATTXT - возвращает текст в дополнительном окне описания"/>
    <Keyword name="$stattxt" desc="$STATTXT - возвращает текст в дополнительном окне описания"/>
  </Expressions>
  <Variables>
    <Keyword name="args" desc="ARGS - массив с параметрами процедуры / функции"/>
    <Keyword name="$args" desc="$ARGS - массив с параметрами процедуры / функции"/>
    <Keyword name="result" desc="RESULT - переменная содержит результат, возвращаемый текущей функцией"/>
    <Keyword name="$result" desc="$RESULT - переменная содержит результат, возвращаемый текущей функцией"/>
    <Keyword name="disablescroll" desc="DISABLESCROLL - если переменная не равна 0, то запрещает автопрокрутку текста при выводе"/>
    <Keyword name="disablesubex" desc="DISABLESUBEX - если переменная не равна 0, то запрещает использование "подвыражений" в тексте"/>
    <Keyword name="nosave" desc="NOSAVE - если переменная не равна 0, то сохранение состояния игры пользователем невозможно"/>
    <Keyword name="debug" desc="DEBUG - если переменная не равна 0, то отключается проверка идентификатора игры при загрузке состояния"/>
    <Keyword name="$counter" desc="$COUNTER - переменная содержит название локации-счётчика"/>
    <Keyword name="$ongload" desc="$ONGLOAD - переменная содержит название локации-обработчика загрузки состояния"/>
    <Keyword name="$ongsave" desc="$ONGSAVE - переменная содержит название локации-обработчика сохранения состояния"/>
    <Keyword name="$onnewloc" desc="$ONNEWLOC - переменная содержит название локации-обработчика перехода на новую локацию"/>
    <Keyword name="$onactsel" desc="$ONACTSEL - переменная содержит название локации-обработчика выбора действия"/>
    <Keyword name="$onobjsel" desc="$ONOBJSEL - переменная содержит название локации-обработчика выбора предмета"/>
    <Keyword name="$onobjadd" desc="$ONOBJADD - переменная содержит название локации-обработчика добавления предмета"/>
    <Keyword name="$onobjdel" desc="$ONOBJDEL - переменная содержит название локации-обработчика удаления предмета"/>
    <Keyword name="$usercom" desc="$USERCOM - переменная содержит название локации-обработчика строки ввода"/>
    <Keyword name="usehtml" desc="USEHTML - если переменная не равна 0, то включает возможность использования HTML"/>
    <Keyword name="bcolor" desc="BCOLOR - переменная содержит цвет фона"/>
    <Keyword name="fcolor" desc="FCOLOR - переменная содержит основной цвет шрифта"/>
    <Keyword name="lcolor" desc="LCOLOR - переменная содержит основной цвет ссылок"/>
    <Keyword name="fsize" desc="FSIZE - переменная содержит основной размер шрифта"/>
    <Keyword name="$fname" desc="$FNAME - переменная содержит название основного шрифта"/>
    <Keyword name="$backimage" desc="$BACKIMAGE - переменная содержит путь к фоновому изображению"/>
  </Variables>
</QGen-keywords>


code:
#!/usr/bin/env python
# usage: txtmerge.py <input_dir> <output_file_name>
# does the exact opposite of txtsplit.py

import os
#import sys
#import re
import io
import xml.etree.ElementTree as ET

#assert len(sys.argv) == 3, "usage:\ntxtmerge.py <input_dir> <output_file_name>"
#idir = str(sys.argv[1])
#oname = str(sys.argv[2])
idir = '../game/locations'
oname = 'jack.txt'

# read the project xml file first
# let's do this later in order to implement directory structure
tree = ET.parse('../game/jack.qproj')
root = tree.getroot()

ofile = io.open(oname, 'w', encoding='utf-16', newline='\r\n')

for location in root.iter('Location'):
    iname = location.attrib['name']
    #iname = iname.replace("$","_")

    try:
        ifile = io.open(os.path.join(idir,iname + '.qsrc'), 'rt', encoding='utf-8')
        text = ifile.read()

        # make sure there's a line at the end of file
        # (why wouldn't there be one? WINDOWS!
        if text[-1] != u'\n':
            text += u'\n\n'

        ofile.write(text)
        ifile.close()
    except IOError:
        print("WARNING: missing location %s" % iname)
        pass

ofile.close()


code:
#!/usr/bin/env python3
# usage: txtsplit.py <input_file_name> <output_dir>
# ammended usage: txtsplit.py, no longer accepts arguments for JoNT
# splits a txt2gam file into individual location files
# encoded in utf-8, for git to better handle

import os
#import sys
import re
import io
#import xml.etree.ElementTree as ET

#assert len(sys.argv) == 3, "usage:\ntxtsplit.py <input_file_name> <output_dir>"
#iname = str(sys.argv[1])
#odir = str(sys.argv[2])
iname = 'jack.txt'
odir = '../game/locations'

# read the project xml file first
# let's do this later in order to implement directory structure
"""
tree = ET.parse('../game/jack.qproj')
root = tree.getroot()
"""

ifile = io.open(iname, 'rt', encoding='utf-16')

counter = 1

oname = None
firstline = ifile.readline().replace(u'\ufeff','')
# use \S (non-whitespace) instead of [_.\w] to match Russian characters in location names - ImperatorAugustus
match = re.search('^#\s([\$|\#]?\S+)$', firstline)
if match:
    oname = os.path.join(odir, match.group(1) + '.qsrc' )
    counter += 1
assert oname, "file is in the wrong format, must start with a location name"

ofile = io.open(oname, 'w', encoding='utf-8')
ofile.write(firstline)

for line in ifile:
 # use \S (non-whitespace) instead of [_.\w] to match Russian characters in location names (solves trinity_engine files being appended to #quest_base) - ImperatorAugustus
    match = re.search('^#\s([\$|\#]?[\S]+)$', line)
    if match:
        ofile.close()
        oname = os.path.join(odir, match.group(1) + '.qsrc' )
        counter += 1
        ofile = io.open(oname, 'w', encoding='utf-8')
    ofile.write(line)