Compare commits
36 Commits
witcher001
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a11c4614ea | ||
|
|
5cbe7a345e | ||
|
|
2add42c1cb | ||
|
|
4039c24372 | ||
|
|
7df68febca | ||
|
|
5ecf5fb9d7 | ||
|
|
c3f449b999 | ||
|
|
8a0a8390b2 | ||
|
|
d39f5ca68b | ||
|
|
1c20333f30 | ||
|
|
1d8e103690 | ||
|
|
4c9ecb31d8 | ||
|
|
2e749ed26e | ||
|
|
fc93eb6680 | ||
|
|
5b21ba615e | ||
|
|
02ba86331b | ||
|
|
6a79e8e41e | ||
|
|
6406c4f258 | ||
|
|
9f812f0318 | ||
|
|
adf9871861 | ||
|
|
825a56a4a4 | ||
|
|
e5e3d7bb28 | ||
|
|
e773b51985 | ||
|
|
0975f3b9cd | ||
|
|
e9c888e2bf | ||
|
|
a743f653dd | ||
|
|
3d3522b905 | ||
|
|
b6cd17449f | ||
|
|
159fac02f0 | ||
|
|
9f17d51fc8 | ||
|
|
ca73148f4b | ||
|
|
0c24d52e6d | ||
|
|
beb4fee0d8 | ||
|
|
a7d17d9afd | ||
|
|
76287dda46 | ||
|
|
9da0ae1016 |
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -5,3 +5,6 @@
|
||||
*.wav filter=lfs diff=lfs merge=lfs -text
|
||||
*.ogg filter=lfs diff=lfs merge=lfs -text
|
||||
*.mp3 filter=lfs diff=lfs merge=lfs -text
|
||||
*.bin filter=lfs diff=lfs merge=lfs -text
|
||||
*.dll filter=lfs diff=lfs merge=lfs -text
|
||||
*.so filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@ -409,3 +409,8 @@ web_resources/
|
||||
pc_resources/
|
||||
resources_hd/
|
||||
web_resources_x2/
|
||||
android_resources/
|
||||
|
||||
.artifacts/
|
||||
|
||||
*.zip
|
||||
|
||||
41
Readme.md
41
Readme.md
@ -185,3 +185,44 @@ make -j$(nproc) -C build #Компилируем
|
||||
Для постройки без звука
|
||||
rm -rf build #Очищаем build папку
|
||||
cmake -B build -DAUDIO=1 #Пересоздаём конфигурацию CMake
|
||||
|
||||
|
||||
# Cmake Build NSIS and Portable for Windows:
|
||||
|
||||
```
|
||||
cmake --build . --config Release
|
||||
cpack -C Release
|
||||
```
|
||||
|
||||
Если есть такая ошибка:
|
||||
|
||||
CPack Error: Cannot find NSIS compiler makensis: likely it is not installed, or not in your PATH
|
||||
CPack Error: Could not read NSIS registry value. This is usually caused by NSIS not being installed. Please install NSIS from http://nsis.sourceforge.net
|
||||
CPack Error: Cannot initialize the generator NSIS
|
||||
|
||||
|
||||
То нужно установить nsis отсюда: https://nsis.sourceforge.io/Download
|
||||
|
||||
|
||||
# Steam windows
|
||||
|
||||
```
|
||||
cmake -DSTEAMSDK=ON ..
|
||||
cmake --build . --config Release
|
||||
```
|
||||
|
||||
|
||||
# Steam Linux
|
||||
|
||||
```
|
||||
docker run -it --rm -v "${PWD}:/work2" -w /work2 registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest bash
|
||||
|
||||
|
||||
apt-get update
|
||||
apt-get install libboost-dev libeigen3-dev liblua5.4-dev libzip-dev libglu1-mesa-dev
|
||||
|
||||
|
||||
cmake -DSTEAMSDK=ON -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build . -j 4
|
||||
|
||||
```
|
||||
|
||||
128
optimize_android_resources.py
Normal file
128
optimize_android_resources.py
Normal file
@ -0,0 +1,128 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
optimize_web_resources.py - Resize PNG images for the web build.
|
||||
|
||||
Copies <src> to <dst>/resources/, then downscales all PNG files:
|
||||
- resources/w/ui/img/** -> 1/8 original size
|
||||
- all other PNGs -> 1/4 original size
|
||||
|
||||
Files listed in EXCEPTIONS are copied unchanged.
|
||||
|
||||
Usage (manual):
|
||||
python optimize_web_resources.py [--src resources] [--dst web_resources]
|
||||
|
||||
Usage (CMake):
|
||||
${Python3_EXECUTABLE} optimize_web_resources.py --src <abs_src> --dst <abs_dst>
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import shutil
|
||||
|
||||
try:
|
||||
from PIL import Image
|
||||
except ImportError:
|
||||
raise SystemExit("Pillow is required: pip install Pillow")
|
||||
|
||||
# Paths relative to the resources directory — these files are never resized.
|
||||
EXCEPTIONS = {
|
||||
"loading.png",
|
||||
"loading_land003_en.png",
|
||||
"loading_land003_ru.png",
|
||||
"black.png",
|
||||
"transparent.png",
|
||||
"w/blue.png",
|
||||
"w/red.png",
|
||||
"w/spark.png",
|
||||
"w/star.png",
|
||||
"w/star_red.png",
|
||||
"w/white.png",
|
||||
"w/ui/img/main/aboutPage003android.png",
|
||||
"w/ui_en/img/main/aboutPage003android.png",
|
||||
"w/exterior/texAtlas002.png",
|
||||
}
|
||||
|
||||
# Path prefixes (relative to resources root, forward-slash) that get 8x reduction.
|
||||
HIGH_REDUCTION_PREFIXES = (
|
||||
"w/ui/img",
|
||||
)
|
||||
|
||||
LOW_REDUCTION_POSTFIXES = (
|
||||
"texAtlas002.png",
|
||||
"Building_work014.png",
|
||||
"Building_Floors_tex004.png",
|
||||
"Building_Walls_tex006.png",
|
||||
"asphalt003small.png",
|
||||
"Ext_Building004.png",
|
||||
"Plane3_tex002.png",
|
||||
"darklands_building002.png",
|
||||
"Staircase001.png",
|
||||
"Staircase_Obj002.png"
|
||||
)
|
||||
|
||||
def _resize_factor(rel: str) -> int:
|
||||
norm = rel.replace("\\", "/")
|
||||
for prefix in HIGH_REDUCTION_PREFIXES:
|
||||
if norm.startswith(prefix):
|
||||
return 8
|
||||
for prefix in LOW_REDUCTION_POSTFIXES:
|
||||
if norm.endswith(prefix):
|
||||
return 2
|
||||
return 4
|
||||
|
||||
|
||||
def _next_pot(n: int) -> int:
|
||||
if n < 1:
|
||||
return 1
|
||||
p = 1
|
||||
while p < n:
|
||||
p <<= 1
|
||||
return p
|
||||
|
||||
|
||||
def optimize(src_dir: str, dst_parent: str) -> None:
|
||||
src_dir = os.path.abspath(src_dir)
|
||||
dst_resources = os.path.join(os.path.abspath(dst_parent), "resources")
|
||||
|
||||
print(f"Copying {src_dir} -> {dst_resources}")
|
||||
if os.path.exists(dst_resources):
|
||||
shutil.rmtree(dst_resources)
|
||||
shutil.copytree(src_dir, dst_resources)
|
||||
|
||||
total = 0
|
||||
for root, _dirs, files in os.walk(dst_resources):
|
||||
for filename in files:
|
||||
if not filename.lower().endswith(".png"):
|
||||
continue
|
||||
|
||||
full_path = os.path.join(root, filename)
|
||||
rel = os.path.relpath(full_path, dst_resources).replace("\\", "/")
|
||||
|
||||
if rel in EXCEPTIONS:
|
||||
print(f" skip (exception): {rel}")
|
||||
continue
|
||||
|
||||
factor = _resize_factor(rel)
|
||||
|
||||
with Image.open(full_path) as img:
|
||||
orig_w, orig_h = img.size
|
||||
new_w = _next_pot(max(1, orig_w // factor))
|
||||
new_h = _next_pot(max(1, orig_h // factor))
|
||||
resized = img.resize((new_w, new_h), Image.LANCZOS)
|
||||
resized.save(full_path)
|
||||
|
||||
print(f" {rel}: {orig_w}x{orig_h} -> {new_w}x{new_h} (/{factor} + POT)")
|
||||
total += 1
|
||||
|
||||
print(f"Done. Resized {total} PNG file(s).")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Optimize PNG images for web build")
|
||||
parser.add_argument("--src", default="resources",
|
||||
help="Source resources directory (default: resources)")
|
||||
parser.add_argument("--dst", default="android_resources",
|
||||
help="Destination parent directory; will contain a 'resources' subdir "
|
||||
"(default: android_resources)")
|
||||
args = parser.parse_args()
|
||||
optimize(args.src, args.dst)
|
||||
@ -27,7 +27,18 @@ except ImportError:
|
||||
# Paths relative to the resources directory — these files are never resized.
|
||||
EXCEPTIONS = {
|
||||
"loading.png",
|
||||
"loading_land003_en.png",
|
||||
"loading_land003_ru.png",
|
||||
"black.png",
|
||||
"transparent.png",
|
||||
"w/blue.png",
|
||||
"w/red.png",
|
||||
"w/spark.png",
|
||||
"w/star.png",
|
||||
"w/star_red.png",
|
||||
"w/white.png",
|
||||
"w/ui/img/main/aboutPage003android.png",
|
||||
"w/ui_en/img/main/aboutPage003android.png"
|
||||
}
|
||||
|
||||
# Path prefixes (relative to resources root, forward-slash) that get 8x reduction.
|
||||
@ -35,13 +46,28 @@ HIGH_REDUCTION_PREFIXES = (
|
||||
"w/ui/img",
|
||||
)
|
||||
|
||||
LOW_REDUCTION_POSTFIXES = (
|
||||
"texAtlas002.png",
|
||||
"Building_work014.png",
|
||||
"Building_Floors_tex004.png",
|
||||
"Building_Walls_tex006.png",
|
||||
"asphalt003small.png",
|
||||
"Ext_Building004.png",
|
||||
"Plane3_tex002.png",
|
||||
"darklands_building002.png",
|
||||
"Staircase001.png",
|
||||
"Staircase_Obj002.png"
|
||||
)
|
||||
|
||||
def _resize_factor(rel: str) -> int:
|
||||
norm = rel.replace("\\", "/")
|
||||
for prefix in HIGH_REDUCTION_PREFIXES:
|
||||
if norm.startswith(prefix):
|
||||
return 8
|
||||
return 4
|
||||
for prefix in LOW_REDUCTION_POSTFIXES:
|
||||
if norm.endswith(prefix):
|
||||
return 2
|
||||
return 8
|
||||
|
||||
|
||||
def _next_pot(n: int) -> int:
|
||||
|
||||
2
proj-android/.gitignore
vendored
2
proj-android/.gitignore
vendored
@ -61,5 +61,5 @@ app/jni/libpng
|
||||
app/jni/SDL
|
||||
app/jni/zlib
|
||||
|
||||
app/src/main/assets/resources
|
||||
app/src/main/assets
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
### Перед запуском в папке ```app/jni/```(рядом с src) нужно создать три папки с исходниками библиотек ```libpng```, ```SDL```, ```zlib```
|
||||
### Android version
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
def buildAsLibrary = project.hasProperty('BUILD_AS_LIBRARY');
|
||||
def buildAsLibrary = project.hasProperty('BUILD_AS_LIBRARY')
|
||||
def buildAsApplication = !buildAsLibrary
|
||||
if (buildAsApplication) {
|
||||
apply plugin: 'com.android.application'
|
||||
@ -9,30 +9,33 @@ else {
|
||||
|
||||
android {
|
||||
if (buildAsApplication) {
|
||||
namespace "org.libsdl.app"
|
||||
namespace "fishrungames.shadowoverbishkek"
|
||||
}
|
||||
compileSdkVersion 34
|
||||
compileSdkVersion 37
|
||||
defaultConfig {
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 34
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 37
|
||||
versionCode 4
|
||||
versionName "1.0.7"
|
||||
externalNativeBuild {
|
||||
/*ndkBuild {
|
||||
arguments "APP_PLATFORM=android-19"
|
||||
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
|
||||
}*/
|
||||
cmake {
|
||||
arguments "-DANDROID_APP_PLATFORM=android-19", "-DANDROID_STL=c++_static"
|
||||
cppFlags "-std=c++11 -frtti -fexceptions"
|
||||
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
|
||||
arguments /*"-DANDROID_APP_PLATFORM=android-19",*/ "-DANDROID_STL=c++_static"
|
||||
cppFlags "-std=c++17 -frtti -fexceptions"
|
||||
abiFilters 'arm64-v8a', 'x86_64'
|
||||
}
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
// Enables code optimizations.
|
||||
minifyEnabled = true
|
||||
// Enables resource shrinking.
|
||||
shrinkResources = true
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
applicationVariants.all { variant ->
|
||||
@ -62,7 +65,7 @@ android {
|
||||
libraryVariants.all { variant ->
|
||||
variant.outputs.all { output ->
|
||||
if (output.outputFileName != null && output.outputFileName.endsWith(".aar")) {
|
||||
output.outputFileName = "org.libsdl.app.aar"
|
||||
output.outputFileName = "fishrungames.shadowoverbishkek.aar"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -70,5 +73,6 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'androidx.core:core-splashscreen:1.0.1'
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ set(TP_ROOT "${THIRDPARTY_DIR}")
|
||||
# ==============================================================================
|
||||
|
||||
# --- ZLIB ---
|
||||
add_subdirectory("${TP_ROOT}/zlib-1.3.1" zlib-build)
|
||||
#add_subdirectory("${TP_ROOT}/zlib-1.3.2" zlib-build)
|
||||
|
||||
# --- LIBPNG ---
|
||||
set(PNG_STATIC ON CACHE BOOL "Build static library" FORCE)
|
||||
@ -39,6 +39,10 @@ add_subdirectory("${TP_ROOT}/libpng-1.6.51" libpng-build)
|
||||
# --- SDL2 ---
|
||||
# Android-версия SDL требует специфичных настроек, но add_subdirectory обычно подхватывает их сама
|
||||
add_subdirectory("${TP_ROOT}/SDL-release-2.32.10" sdl-build)
|
||||
add_subdirectory("${TP_ROOT}/SDL_mixer-release-2.8.0" sdl-mixer-build)
|
||||
|
||||
|
||||
add_subdirectory("${TP_ROOT}/SDL_ttf-release-2.24.0" sdl-ttf-build)
|
||||
|
||||
# --- LIBZIP ---
|
||||
# Отключаем поиск системных крипто-библиотек, так как в NDK их может не быть в стандартных путях
|
||||
|
||||
@ -33,62 +33,145 @@ endforeach()
|
||||
# Создаем кастомную цель, которая будет запускать процесс копирования
|
||||
add_custom_target(sync_resources ALL DEPENDS ${RES_OUTPUTS})
|
||||
|
||||
set(LUA_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../thirdparty/lua-5.4.8")
|
||||
file(GLOB LUA_SOURCES "${LUA_SRC_DIR}/*.c")
|
||||
list(REMOVE_ITEM LUA_SOURCES
|
||||
"${LUA_SRC_DIR}/lua.c"
|
||||
"${LUA_SRC_DIR}/luac.c"
|
||||
"${LUA_SRC_DIR}/onelua.c"
|
||||
)
|
||||
add_library(lua_static STATIC ${LUA_SOURCES})
|
||||
target_include_directories(lua_static PUBLIC "${LUA_SRC_DIR}")
|
||||
|
||||
|
||||
|
||||
add_library(main SHARED
|
||||
SDL_android_main.c
|
||||
../../../../src/BoneAnimatedModel.cpp
|
||||
../../../../src/Environment.cpp
|
||||
../../../../src/Game.cpp
|
||||
../../../../src/main.cpp
|
||||
../../../../src/Projectile.cpp
|
||||
../../../../src/SparkEmitter.cpp
|
||||
../../../../src/TextModel.cpp
|
||||
../../../../src/UiManager.cpp
|
||||
../../../../src/utils/Perlin.cpp
|
||||
../../../../src/utils/TaskManager.cpp
|
||||
../../../../src/utils/Utils.cpp
|
||||
../../../../src/navigation/PathFinder.cpp
|
||||
../../../../src/planet/PlanetData.cpp
|
||||
../../../../src/planet/PlanetObject.cpp
|
||||
../../../../src/planet/StoneObject.cpp
|
||||
../../../../src/render/FrameBuffer.cpp
|
||||
../../../../src/render/ShadowMap.cpp
|
||||
../../../../src/Game.cpp
|
||||
../../../../src/Game.h
|
||||
../../../../src/Character.cpp
|
||||
../../../../src/Character.h
|
||||
../../../../src/CharacterState.cpp
|
||||
../../../../src/CharacterState.h
|
||||
../../../../src/Environment.cpp
|
||||
../../../../src/Environment.h
|
||||
../../../../src/Localization.cpp
|
||||
../../../../src/Localization.h
|
||||
../../../../src/render/Renderer.cpp
|
||||
../../../../src/render/Renderer.h
|
||||
../../../../src/render/ShaderManager.cpp
|
||||
../../../../src/render/ShaderManager.h
|
||||
../../../../src/render/TextureManager.cpp
|
||||
../../../../src/render/TextureManager.h
|
||||
../../../../src/TextModel.cpp
|
||||
../../../../src/TextModel.h
|
||||
../../../../src/AudioPlayerAsync.cpp
|
||||
../../../../src/AudioPlayerAsync.h
|
||||
../../../../src/BoneAnimatedModelNew.cpp
|
||||
../../../../src/BoneAnimatedModelNew.h
|
||||
../../../../src/render/OpenGlExtensions.cpp
|
||||
../../../../src/render/OpenGlExtensions.h
|
||||
../../../../src/utils/Utils.cpp
|
||||
../../../../src/utils/Utils.h
|
||||
../../../../src/SparkEmitter.cpp
|
||||
../../../../src/SparkEmitter.h
|
||||
../../../../src/TeleportZone.h
|
||||
../../../../src/TeleportZone.cpp
|
||||
../../../../src/utils/TaskManager.cpp
|
||||
../../../../src/utils/TaskManager.h
|
||||
../../../../src/render/FrameBuffer.cpp
|
||||
../../../../src/render/FrameBuffer.h
|
||||
../../../../src/render/ShadowMap.cpp
|
||||
../../../../src/render/ShadowMap.h
|
||||
../../../../src/UiManager.cpp
|
||||
../../../../src/UiManager.h
|
||||
../../../../src/render/TextRenderer.h
|
||||
../../../../src/render/TextRenderer.cpp
|
||||
../../../../src/MenuManager.h
|
||||
../../../../src/MenuManager.cpp
|
||||
../../../../src/Location.h
|
||||
../../../../src/Location.cpp
|
||||
../../../../src/LocationState.h
|
||||
../../../../src/LocationState.cpp
|
||||
../../../../src/LocationEditor.h
|
||||
../../../../src/LocationEditor.cpp
|
||||
../../../../src/NpcCar.h
|
||||
../../../../src/NpcCar.cpp
|
||||
../../../../src/GameConstants.h
|
||||
../../../../src/GameConstants.cpp
|
||||
../../../../src/GameState.h
|
||||
../../../../src/GameState.cpp
|
||||
../../../../src/ScriptEngine.h
|
||||
../../../../src/ScriptEngine.cpp
|
||||
../../../../src/navigation/PathFinder.h
|
||||
../../../../src/navigation/PathFinder.cpp
|
||||
../../../../src/items/GameObjectLoader.h
|
||||
../../../../src/items/GameObjectLoader.cpp
|
||||
../../../../src/items/Item.h
|
||||
../../../../src/items/Item.cpp
|
||||
../../../../src/items/ItemRegistry.h
|
||||
../../../../src/items/ItemRegistry.cpp
|
||||
../../../../src/items/InteractiveObject.h
|
||||
../../../../src/items/InteractiveObject.cpp
|
||||
../../../../src/items/InteractiveObjectState.h
|
||||
../../../../src/dialogue/DialogueTypes.h
|
||||
../../../../src/dialogue/DialogueDatabase.h
|
||||
../../../../src/dialogue/DialogueDatabase.cpp
|
||||
../../../../src/dialogue/DialogueRuntime.h
|
||||
../../../../src/dialogue/DialogueRuntime.cpp
|
||||
../../../../src/dialogue/DialogueOverlay.h
|
||||
../../../../src/dialogue/DialogueOverlay.cpp
|
||||
../../../../src/dialogue/DialogueSystem.h
|
||||
../../../../src/dialogue/DialogueSystem.cpp
|
||||
../../../../src/dialogue/TranslationDatabase.h
|
||||
../../../../src/dialogue/TranslationDatabase.cpp
|
||||
../../../../src/quest/QuestTypes.h
|
||||
../../../../src/quest/QuestJournal.h
|
||||
../../../../src/quest/QuestJournal.cpp
|
||||
../../../../src/cutscene/CutsceneTypes.h
|
||||
../../../../src/cutscene/CutsceneDatabase.h
|
||||
../../../../src/cutscene/CutsceneDatabase.cpp
|
||||
../../../../src/cutscene/CutsceneRuntime.h
|
||||
../../../../src/cutscene/CutsceneRuntime.cpp
|
||||
../../../../src/cutscene/CutsceneOverlay.h
|
||||
../../../../src/cutscene/CutsceneOverlay.cpp
|
||||
../../../../src/render/UiQuad.h
|
||||
)
|
||||
|
||||
# Подключаем заголовки
|
||||
target_include_directories(main PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../SDL/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../zlib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../libpng
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../../thirdparty/eigen-5.0.0
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../../thirdparty/boost_1_90_0
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../../src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../libzip
|
||||
)
|
||||
|
||||
# ВАЖНО: Линкуемся с png_static (статика) или png_shared (динамика)
|
||||
# Так как мы установили PNG_STATIC=ON и PNG_SHARED=OFF,
|
||||
# должна создаться цель png_static
|
||||
|
||||
|
||||
find_library(OPENGLES3_LIB GLESv3)
|
||||
|
||||
target_link_libraries(main
|
||||
png_static # ← ЭТО ПРАВИЛЬНОЕ ИМЯ ЦЕЛИ!
|
||||
${OPENGLES3_LIB}
|
||||
png_static
|
||||
z
|
||||
SDL2
|
||||
)
|
||||
|
||||
|
||||
find_library(OPENGLES2_LIB GLESv2)
|
||||
|
||||
target_link_libraries(main
|
||||
${OPENGLES2_LIB} # OpenGL ES 2.0/3.0
|
||||
SDL2_ttf
|
||||
SDL2_mixer
|
||||
log
|
||||
android
|
||||
OpenSLES
|
||||
dl
|
||||
zip
|
||||
lua_static
|
||||
#freetype
|
||||
)
|
||||
|
||||
# Подключаем заголовки
|
||||
target_include_directories(main PRIVATE
|
||||
#${CMAKE_CURRENT_SOURCE_DIR}/../SDL/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../../thirdparty/SDL_ttf-release-2.24.0/external/freetype/include
|
||||
|
||||
#${CMAKE_CURRENT_SOURCE_DIR}/../zlib
|
||||
#${CMAKE_CURRENT_SOURCE_DIR}/../libpng
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../../thirdparty/eigen-5.0.0
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../../thirdparty/boost_1_90_0
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../../src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../../thirdparty/sol2-3.3.0/include
|
||||
#${CMAKE_CURRENT_SOURCE_DIR}/../libzip
|
||||
)
|
||||
|
||||
add_dependencies(main sync_resources)
|
||||
|
||||
6
proj-android/app/proguard-rules.pro
vendored
6
proj-android/app/proguard-rules.pro
vendored
@ -16,6 +16,9 @@
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# SDL2 specific rules
|
||||
-keep class org.libsdl.app.** { *; }
|
||||
|
||||
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLInputConnection {
|
||||
void nativeCommitText(java.lang.String, int);
|
||||
void nativeGenerateScancodeForUnichar(char);
|
||||
@ -96,3 +99,6 @@
|
||||
void hapticRun(int, float, int);
|
||||
void hapticStop(int);
|
||||
}
|
||||
|
||||
# Keep our main activity
|
||||
-keep class fishrungames.shadowoverbishkek.ShadowOverBishkekActivity { *; }
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
android:installLocation="auto">
|
||||
|
||||
<!-- OpenGL ES 2.0 -->
|
||||
<uses-feature android:glEsVersion="0x00020000" />
|
||||
<uses-feature android:glEsVersion="0x00030000" />
|
||||
|
||||
<!-- Touchscreen support -->
|
||||
<uses-feature
|
||||
@ -52,7 +52,7 @@
|
||||
<!-- <uses-permission android:name="android.permission.RECORD_AUDIO" /> -->
|
||||
|
||||
<!-- Create a Java class extending SDLActivity and place it in a
|
||||
directory under app/src/main/java matching the package, e.g. app/src/main/java/com/gamemaker/game/MyGame.java
|
||||
directory under shadowoverbishkek/main/java matching the package, e.g. shadowoverbishkek/main/java/com/gamemaker/game/MyGame.java
|
||||
|
||||
then replace "SDLActivity" with the name of your class (e.g. "MyGame")
|
||||
in the XML below.
|
||||
@ -62,14 +62,14 @@
|
||||
<application android:label="@string/app_name"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:allowBackup="true"
|
||||
android:theme="@style/AppTheme"
|
||||
android:theme="@style/Theme.App.Starting"
|
||||
android:hardwareAccelerated="true" >
|
||||
|
||||
<!-- Example of setting SDL hints from AndroidManifest.xml:
|
||||
<meta-data android:name="SDL_ENV.SDL_ACCELEROMETER_AS_JOYSTICK" android:value="0"/>
|
||||
-->
|
||||
|
||||
<activity android:name="SDLActivity"
|
||||
<activity android:name=".ShadowOverBishkekActivity"
|
||||
android:label="@string/app_name"
|
||||
android:alwaysRetainTaskState="true"
|
||||
android:launchMode="singleInstance"
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
package fishrungames.shadowoverbishkek;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.core.splashscreen.SplashScreen;
|
||||
import org.libsdl.app.SDLActivity;
|
||||
|
||||
public class ShadowOverBishkekActivity extends SDLActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
SplashScreen.installSplashScreen(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
}
|
||||
BIN
proj-android/app/src/main/res/drawable/splash_icon.png
(Stored with Git LFS)
Normal file
BIN
proj-android/app/src/main/res/drawable/splash_icon.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
proj-android/app/src/main/res/mipmap-hdpi/ic_launcher.png
(Stored with Git LFS)
BIN
proj-android/app/src/main/res/mipmap-hdpi/ic_launcher.png
(Stored with Git LFS)
Binary file not shown.
BIN
proj-android/app/src/main/res/mipmap-mdpi/ic_launcher.png
(Stored with Git LFS)
BIN
proj-android/app/src/main/res/mipmap-mdpi/ic_launcher.png
(Stored with Git LFS)
Binary file not shown.
BIN
proj-android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
(Stored with Git LFS)
BIN
proj-android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
(Stored with Git LFS)
Binary file not shown.
BIN
proj-android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
(Stored with Git LFS)
BIN
proj-android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
(Stored with Git LFS)
Binary file not shown.
BIN
proj-android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
(Stored with Git LFS)
BIN
proj-android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
(Stored with Git LFS)
Binary file not shown.
3
proj-android/app/src/main/res/values-ru/strings.xml
Normal file
3
proj-android/app/src/main/res/values-ru/strings.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">Тень над Бишкеком</string>
|
||||
</resources>
|
||||
@ -1,3 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">Game</string>
|
||||
<string name="app_name">Shadow Over Bishkek</string>
|
||||
</resources>
|
||||
|
||||
@ -4,4 +4,13 @@
|
||||
<style name="AppTheme" parent="android:Theme.NoTitleBar.Fullscreen">
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
<!-- Тема для Splash Screen -->
|
||||
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
|
||||
<!-- Черный фон -->
|
||||
<item name="windowSplashScreenBackground">#000000</item>
|
||||
<!-- Ваша картинка 512x512 -->
|
||||
<item name="windowSplashScreenAnimatedIcon">@drawable/splash_icon</item>
|
||||
<!-- Ссылка на основную тему, которая применится после загрузки -->
|
||||
<item name="postSplashScreenTheme">@style/AppTheme</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
||||
@ -6,7 +6,7 @@ buildscript {
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.1.1'
|
||||
classpath 'com.android.tools.build:gradle:9.3.0'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
||||
@ -9,7 +9,18 @@
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
android.builtInKotlin=false
|
||||
android.defaults.buildfeatures.resvalues=true
|
||||
android.dependency.useConstraints=true
|
||||
android.enableAppCompileTimeRClass=false
|
||||
android.newDsl=false
|
||||
android.r8.optimizedResourceShrinking=false
|
||||
android.r8.strictFullModeForKeepRules=false
|
||||
android.sdk.defaultTargetSdkToCompileSdkIfUnset=false
|
||||
android.uniquePackageNames=false
|
||||
android.usesSdkInManifest.disallowed=false
|
||||
org.gradle.jvmargs=-Xmx4096m
|
||||
android.useAndroidX=true
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
|
||||
12
proj-android/gradle/gradle-daemon-jvm.properties
Normal file
12
proj-android/gradle/gradle-daemon-jvm.properties
Normal file
@ -0,0 +1,12 @@
|
||||
#This file is generated by updateDaemonJvm
|
||||
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/ec7520a1e057cd116f9544c42142a16b/redirect
|
||||
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/4c4f879899012ff0a8b2e2117df03b0e/redirect
|
||||
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/ec7520a1e057cd116f9544c42142a16b/redirect
|
||||
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/4c4f879899012ff0a8b2e2117df03b0e/redirect
|
||||
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/73bcfb608d1fde9fb62e462f834a3299/redirect
|
||||
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/846ee0d876d26a26f37aa1ce8de73224/redirect
|
||||
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/ec7520a1e057cd116f9544c42142a16b/redirect
|
||||
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/4c4f879899012ff0a8b2e2117df03b0e/redirect
|
||||
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/9482ddec596298c84656d31d16652665/redirect
|
||||
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/39701d92e1756bb2f141eb67cd4c660e/redirect
|
||||
toolchainVersion=21
|
||||
@ -1,6 +1,6 @@
|
||||
#Sat Jan 10 10:31:05 MSK 2026
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@ -1,10 +1,17 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(witcher001 LANGUAGES C CXX)
|
||||
project(ShadowOverBishkekDemo LANGUAGES C CXX)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "Setting build type to 'Release' as none was specified.")
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
option(STEAMSDK "Enable Steamworks SDK integration" OFF)
|
||||
|
||||
# ===========================================
|
||||
# Поиск системных зависимостей Linux
|
||||
# ===========================================
|
||||
@ -62,9 +69,9 @@ endif()
|
||||
|
||||
|
||||
# ===========================================
|
||||
# Основной проект witcher001
|
||||
# Основной проект ShadowOverBishkekDemo
|
||||
# ===========================================
|
||||
add_executable(witcher001
|
||||
add_executable(ShadowOverBishkekDemo
|
||||
../src/main.cpp
|
||||
../src/Game.cpp
|
||||
../src/Game.h
|
||||
@ -158,7 +165,7 @@ add_executable(witcher001
|
||||
)
|
||||
|
||||
# include-пути проекта
|
||||
target_include_directories(witcher001 PRIVATE
|
||||
target_include_directories(ShadowOverBishkekDemo PRIVATE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../src"
|
||||
${SDL2_INCLUDE_DIRS}
|
||||
${SDL2_TTF_INCLUDE_DIRS}
|
||||
@ -166,19 +173,18 @@ target_include_directories(witcher001 PRIVATE
|
||||
${LIBZIP_INCLUDE_DIRS}
|
||||
${LUA_INCLUDE_DIRS}
|
||||
${EIGEN3_INCLUDE_DIRS}
|
||||
# sol2 - header-only, берем напрямую из thirdparty (если он там есть)
|
||||
# или можно установить системный libsol-dev и убрать этот путь
|
||||
# sol2 - header-only, берем напрямую из thirdparty
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/sol2-3.3.0/include"
|
||||
)
|
||||
|
||||
# Убираем WIN32_LEAN_AND_MEAN
|
||||
target_compile_definitions(witcher001 PRIVATE
|
||||
target_compile_definitions(ShadowOverBishkekDemo PRIVATE
|
||||
PNG_ENABLED
|
||||
SDL_MAIN_HANDLED
|
||||
)
|
||||
|
||||
# Линковка директорий для pkg-config (если пакеты не в /usr/lib)
|
||||
target_link_directories(witcher001 PRIVATE
|
||||
target_link_directories(ShadowOverBishkekDemo PRIVATE
|
||||
${SDL2_LIBRARY_DIRS}
|
||||
${SDL2_TTF_LIBRARY_DIRS}
|
||||
${SDL2_MIXER_LIBRARY_DIRS}
|
||||
@ -187,7 +193,7 @@ target_link_directories(witcher001 PRIVATE
|
||||
)
|
||||
|
||||
# Линковка библиотек
|
||||
target_link_libraries(witcher001 PRIVATE
|
||||
target_link_libraries(ShadowOverBishkekDemo PRIVATE
|
||||
OpenGL::GL
|
||||
OpenGL::GLU
|
||||
ZLIB::ZLIB
|
||||
@ -202,18 +208,93 @@ target_link_libraries(witcher001 PRIVATE
|
||||
pthread
|
||||
)
|
||||
|
||||
# ===========================================
|
||||
# Интеграция Steamworks SDK (если STEAMSDK=ON)
|
||||
# ===========================================
|
||||
if(STEAMSDK)
|
||||
message(STATUS "Steamworks SDK integration is ENABLED.")
|
||||
|
||||
target_compile_definitions(ShadowOverBishkekDemo PRIVATE STEAMSDK)
|
||||
|
||||
set(STEAM_SDK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/steamworks_sdk_164/sdk")
|
||||
|
||||
target_include_directories(ShadowOverBishkekDemo PRIVATE
|
||||
"${STEAM_SDK_DIR}/public"
|
||||
"${STEAM_SDK_DIR}/public/steam"
|
||||
)
|
||||
|
||||
set(STEAM_LIB_DIR "${STEAM_SDK_DIR}/redistributable_bin/linux64")
|
||||
set(STEAM_LIB_NAME "steam_api")
|
||||
set(STEAM_SO_NAME "libsteam_api.so")
|
||||
|
||||
find_library(STEAM_LIBRARY
|
||||
NAMES ${STEAM_LIB_NAME}
|
||||
PATHS ${STEAM_LIB_DIR}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
if(STEAM_LIBRARY)
|
||||
target_link_libraries(ShadowOverBishkekDemo PRIVATE ${STEAM_LIBRARY})
|
||||
message(STATUS "Found Steam API library: ${STEAM_LIBRARY}")
|
||||
else()
|
||||
message(FATAL_ERROR "Steam API library (${STEAM_LIB_NAME}) NOT found in ${STEAM_LIB_DIR}!")
|
||||
endif()
|
||||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/steam_appid.txt" "4945840")
|
||||
else()
|
||||
message(STATUS "Steamworks SDK integration is DISABLED.")
|
||||
endif()
|
||||
|
||||
# ===========================================
|
||||
# Настройка RPATH и копирование динамических библиотек
|
||||
# ===========================================
|
||||
|
||||
# Указываем линкеру искать .so файлы в той же папке, где лежит бинарник ($ORIGIN)
|
||||
set_target_properties(ShadowOverBishkekDemo PROPERTIES
|
||||
INSTALL_RPATH "$ORIGIN"
|
||||
BUILD_WITH_INSTALL_RPATH TRUE
|
||||
)
|
||||
|
||||
#FIXING BUILD BUG
|
||||
set(LUA_SO_DIR "/usr/lib/x86_64-linux-gnu/")
|
||||
set (LIBZIP_SO_DIR "/usr/lib/x86_64-linux-gnu/")
|
||||
# Поиск директорий, где лежат библиотеки
|
||||
#get_filename_component(LUA_SO_DIR ${LUA_SO_PATH} DIRECTORY)
|
||||
#get_filename_component(LIBZIP_SO_DIR ${LIBZIP_SO_PATH} DIRECTORY)
|
||||
|
||||
add_custom_command(TARGET ShadowOverBishkekDemo POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Copying shared libraries with sonames..."
|
||||
# Копируем библиотеки и все их симлинки (cp -P сохраняет структуру симлинков)
|
||||
COMMAND sh -c "cp -P ${LUA_SO_DIR}/liblua5.4.so* '$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/'"
|
||||
COMMAND sh -c "cp -P ${LIBZIP_SO_DIR}/libzip.so* '$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/'"
|
||||
)
|
||||
|
||||
# Если включен Steam, копируем libsteam_api.so и steam_appid.txt
|
||||
if(STEAMSDK)
|
||||
add_custom_command(TARGET ShadowOverBishkekDemo POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Copying Steam SDK components..."
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${STEAM_LIB_DIR}/${STEAM_SO_NAME}"
|
||||
"$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/${STEAM_SO_NAME}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/steam_appid.txt"
|
||||
"$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/steam_appid.txt"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/steam_appid.txt"
|
||||
"${CMAKE_BINARY_DIR}/steam_appid.txt"
|
||||
)
|
||||
endif()
|
||||
|
||||
# ===========================================
|
||||
# Копирование ресурсов после сборки
|
||||
# ===========================================
|
||||
set(RUNTIME_RESOURCE_DIRS
|
||||
"resources"
|
||||
"audio"
|
||||
"music"
|
||||
)
|
||||
|
||||
# В Linux (при использовании Make/Ninja) бинарник обычно создается в CMAKE_BINARY_DIR.
|
||||
# Копируем ресурсы рядом с исполняемым файлом.
|
||||
foreach(resdir IN LISTS RUNTIME_RESOURCE_DIRS)
|
||||
add_custom_command(TARGET witcher001 POST_BUILD
|
||||
add_custom_command(TARGET ShadowOverBishkekDemo POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Copying ${resdir} to binary dir..."
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
"${CMAKE_SOURCE_DIR}/../${resdir}"
|
||||
|
||||
@ -8,13 +8,19 @@ if(NOT CMAKE_MAKE_PROGRAM AND WIN32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
project(bishkek-witcher LANGUAGES C CXX)
|
||||
project(ShadowOverBishkekDemo LANGUAGES C CXX)
|
||||
|
||||
option(OPTIMIZE_WEB_RESOURCES "Resize PNG images for web build (requires Python3 + Pillow)" ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
# Максимальная оптимизация кода и LTO (Link-Time Optimization)
|
||||
add_compile_options(-O3 -flto)
|
||||
add_link_options(-O3 -flto)
|
||||
endif()
|
||||
|
||||
# --- АВТО-ЗАГРУЗКА ЗАВИСИМОСТЕЙ ---
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/../cmake/FetchDependencies.cmake")
|
||||
# Теперь гарантированно есть папка ../thirdparty со всеми исходниками
|
||||
@ -109,6 +115,8 @@ set(SOURCES
|
||||
../src/LocationState.cpp
|
||||
../src/LocationEditor.h
|
||||
../src/LocationEditor.cpp
|
||||
../src/NpcCar.h
|
||||
../src/NpcCar.cpp
|
||||
../src/GameConstants.h
|
||||
../src/GameConstants.cpp
|
||||
../src/GameState.h
|
||||
@ -150,10 +158,10 @@ set(SOURCES
|
||||
../src/render/UiQuad.h
|
||||
)
|
||||
|
||||
add_executable(bishkek-witcher ${SOURCES})
|
||||
add_executable(ShadowOverBishkekDemo ${SOURCES})
|
||||
|
||||
# Настройка путей к инклудам (используем скачанные исходники)
|
||||
target_include_directories(bishkek-witcher PRIVATE
|
||||
target_include_directories(ShadowOverBishkekDemo PRIVATE
|
||||
../src
|
||||
../thirdparty/eigen-5.0.0
|
||||
../thirdparty/boost_1_90_0
|
||||
@ -168,7 +176,7 @@ set(ENABLE_COMMONCRYPTO OFF CACHE BOOL "" FORCE)
|
||||
|
||||
add_subdirectory("../thirdparty/libzip-1.11.4" libzip-build)
|
||||
|
||||
target_link_libraries(bishkek-witcher PRIVATE zip z lua_static websocket.js)
|
||||
target_link_libraries(ShadowOverBishkekDemo PRIVATE zip z lua_static websocket.js)
|
||||
|
||||
# Эмскриптен-флаги
|
||||
set(EMSCRIPTEN_FLAGS
|
||||
@ -185,7 +193,7 @@ set(EMSCRIPTEN_FLAGS
|
||||
"-DNETWORK"
|
||||
)
|
||||
|
||||
target_compile_options(bishkek-witcher PRIVATE ${EMSCRIPTEN_FLAGS} "-O2")
|
||||
target_compile_options(ShadowOverBishkekDemo PRIVATE ${EMSCRIPTEN_FLAGS} "-O2")
|
||||
|
||||
# Only loading.png and the shaders used before resources.zip is ready are preloaded.
|
||||
# resources.zip is downloaded asynchronously at runtime and served as a separate file.
|
||||
@ -195,6 +203,7 @@ set(EMSCRIPTEN_LINK_FLAGS
|
||||
#"-sPTHREAD_POOL_SIZE=4"
|
||||
"-sALLOW_MEMORY_GROWTH=1"
|
||||
"-sFULL_ES3=1"
|
||||
"-lidbfs.js"
|
||||
"--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/../resources/loading.png@resources/loading.png"
|
||||
"--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/../resources/loadingProgressBar.png@resources/loadingProgressBar.png"
|
||||
"--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/../resources/loadingProgressBarFrame.png@resources/loadingProgressBarFrame.png"
|
||||
@ -202,15 +211,14 @@ set(EMSCRIPTEN_LINK_FLAGS
|
||||
"--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/../resources/start_uni_interior.lua@resources/start_uni_interior.lua"
|
||||
"--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/../resources/start_uni_exterior.lua@resources/start_uni_exterior.lua"
|
||||
"--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/../resources/start_dorm.lua@resources/start_dorm.lua"
|
||||
"--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/../audio@audio"
|
||||
)
|
||||
|
||||
# Применяем настройки линковки
|
||||
target_link_options(bishkek-witcher PRIVATE ${EMSCRIPTEN_LINK_FLAGS})
|
||||
target_link_options(ShadowOverBishkekDemo PRIVATE ${EMSCRIPTEN_LINK_FLAGS})
|
||||
|
||||
# Для совместимости со старыми версиями CMake, если target_link_options недостаточно
|
||||
string(REPLACE ";" " " EMSCRIPTEN_LINK_FLAGS_STR "${EMSCRIPTEN_LINK_FLAGS}")
|
||||
set_target_properties(bishkek-witcher PROPERTIES
|
||||
set_target_properties(ShadowOverBishkekDemo PROPERTIES
|
||||
LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS_STR}"
|
||||
SUFFIX ".html"
|
||||
)
|
||||
@ -254,23 +262,40 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
# music resources
|
||||
set(MUSIC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../music")
|
||||
set(MUSIC_ZIP "${CMAKE_CURRENT_BINARY_DIR}/music.zip")
|
||||
get_filename_component(MUSIC_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.." ABSOLUTE)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${MUSIC_ZIP}"
|
||||
COMMAND ${CMAKE_COMMAND} -E tar "cf" "${MUSIC_ZIP}" --format=zip "music"
|
||||
WORKING_DIRECTORY "${MUSIC_PARENT_DIR}"
|
||||
DEPENDS "${MUSIC_PARENT_DIR}/music"
|
||||
)
|
||||
|
||||
|
||||
add_custom_target(pack_resources DEPENDS "${RESOURCES_ZIP}")
|
||||
add_dependencies(bishkek-witcher pack_resources)
|
||||
add_dependencies(ShadowOverBishkekDemo pack_resources)
|
||||
|
||||
add_custom_target(pack_music DEPENDS "${MUSIC_ZIP}")
|
||||
add_dependencies(ShadowOverBishkekDemo pack_music)
|
||||
|
||||
|
||||
# Определяем путь к директории установки (относительно папки билда)
|
||||
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/public")
|
||||
|
||||
# 1. Устанавливаем основной HTML файл
|
||||
install(TARGETS bishkek-witcher
|
||||
install(TARGETS ShadowOverBishkekDemo
|
||||
RUNTIME DESTINATION .
|
||||
)
|
||||
|
||||
# 2. Устанавливаем сопутствующие файлы (JS, WASM и сгенерированный архив данных)
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/bishkek-witcher.js"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/bishkek-witcher.wasm"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/bishkek-witcher.data"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/ShadowOverBishkekDemo.js"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/ShadowOverBishkekDemo.wasm"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/ShadowOverBishkekDemo.data"
|
||||
DESTINATION .
|
||||
)
|
||||
|
||||
@ -278,10 +303,15 @@ install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/index.html"
|
||||
DESTINATION .
|
||||
)
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/favicon.ico"
|
||||
DESTINATION .
|
||||
)
|
||||
|
||||
# resources.zip is served separately and downloaded asynchronously at runtime
|
||||
install(FILES "${RESOURCES_ZIP}" DESTINATION .)
|
||||
install(FILES "${MUSIC_ZIP}" DESTINATION .)
|
||||
|
||||
add_custom_command(TARGET bishkek-witcher POST_BUILD
|
||||
add_custom_command(TARGET ShadowOverBishkekDemo POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} --install .
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||
COMMENT "Automatically deploying to public directory..."
|
||||
|
||||
@ -37,3 +37,14 @@ Run:
|
||||
```
|
||||
emrun --no_browser --port 8080 public
|
||||
```
|
||||
|
||||
# Release build
|
||||
|
||||
|
||||
```
|
||||
mkdir build_release
|
||||
cd build_release
|
||||
emcmake cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build . --config Release
|
||||
cmake --install . --prefix ../dist
|
||||
```
|
||||
|
||||
File diff suppressed because one or more lines are too long
BIN
proj-web/favicon.ico
Normal file
BIN
proj-web/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
@ -39,7 +39,7 @@
|
||||
|
||||
function loadGameScript() {
|
||||
var s = document.createElement('script');
|
||||
s.src = 'bishkek-witcher.js';
|
||||
s.src = 'ShadowOverBishkekDemo.js';
|
||||
s.async = true;
|
||||
document.body.appendChild(s);
|
||||
}
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
<!doctypehtml><html lang=en-us><head><meta charset=utf-8><meta content="text/html; charset=utf-8"http-equiv=Content-Type><title>Emscripten-Generated Code</title><style>body{font-family:arial;margin:0;padding:none}.emscripten{padding-right:0;margin-left:auto;margin-right:auto;display:block}div.emscripten{text-align:center}div.emscripten_border{border:1px solid #000}canvas.emscripten{border:0 none;background-color:#000}#emscripten_logo{display:inline-block;margin:0;padding:6px;width:265px}.spinner{height:30px;width:30px;margin:0;margin-top:20px;margin-left:20px;display:inline-block;vertical-align:top;-webkit-animation:rotation .8s linear infinite;-moz-animation:rotation .8s linear infinite;-o-animation:rotation .8s linear infinite;animation:rotation .8s linear infinite;border-left:5px solid #ebebeb;border-right:5px solid #ebebeb;border-bottom:5px solid #ebebeb;border-top:5px solid #787878;border-radius:100%;background-color:#bdd72e}@-webkit-keyframes rotation{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(360deg)}}@-moz-keyframes rotation{from{-moz-transform:rotate(0)}to{-moz-transform:rotate(360deg)}}@-o-keyframes rotation{from{-o-transform:rotate(0)}to{-o-transform:rotate(360deg)}}@keyframes rotation{from{transform:rotate(0)}to{transform:rotate(360deg)}}#status{display:inline-block;vertical-align:top;margin-top:30px;margin-left:20px;font-weight:700;color:#787878}#progress{height:20px;width:300px}#controls{display:inline-block;float:right;vertical-align:top;margin-top:30px;margin-right:20px}#output{width:100%;height:200px;margin:0 auto;margin-top:10px;border-left:0;border-right:0px;padding-left:0;padding-right:0;display:block;background-color:#000;color:#fff;font-family:'Lucida Console',Monaco,monospace;outline:0}</style></head><body><script src="https://cdn.jsdelivr.net/npm/eruda"></script>
|
||||
<script>eruda.init();</script><a href=http://emscripten.org><img id=emscripten_logo src=""></a><div class=spinner id=spinner></div><div class=emscripten id=status>Downloading...</div><span id=controls><span><input type=checkbox id=resize>Resize canvas</span> <span><input type=checkbox id=pointerLock checked>Lock/hide mouse pointer </span><span><input type=button onclick='Module.requestFullscreen(document.getElementById("pointerLock").checked,document.getElementById("resize").checked)'value=Fullscreen></span></span><div class=emscripten><progress hidden id=progress max=100 value=0></progress></div><div class=emscripten_border><canvas class=emscripten id=canvas oncontextmenu=event.preventDefault() tabindex=-1></canvas></div><textarea id=output rows=8></textarea><script>var statusElement=document.getElementById("status"),progressElement=document.getElementById("progress"),spinnerElement=document.getElementById("spinner"),canvasElement=document.getElementById("canvas"),outputElement=document.getElementById("output");outputElement&&(outputElement.value=""),canvasElement.addEventListener("webglcontextlost",(e=>{alert("WebGL context lost. You will need to reload the page."),e.preventDefault()}),!1);var Module={print(...e){if(console.log(...e),outputElement){var t=e.join(" ");outputElement.value+=t+"\n",outputElement.scrollTop=outputElement.scrollHeight}},canvas:canvasElement,setStatus(e){if(Module.setStatus.last||(Module.setStatus.last={time:Date.now(),text:""}),e!==Module.setStatus.last.text){var t=e.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/),n=Date.now();t&&n-Module.setStatus.last.time<30||(Module.setStatus.last.time=n,Module.setStatus.last.text=e,t?(e=t[1],progressElement.value=100*parseInt(t[2]),progressElement.max=100*parseInt(t[4]),progressElement.hidden=!1,spinnerElement.hidden=!1):(progressElement.value=null,progressElement.max=null,progressElement.hidden=!0,e||(spinnerElement.style.display="none")),statusElement.innerHTML=e)}},totalDependencies:0,monitorRunDependencies(e){this.totalDependencies=Math.max(this.totalDependencies,e),Module.setStatus(e?"Preparing... ("+(this.totalDependencies-e)+"/"+this.totalDependencies+")":"All downloads complete.")}};Module.setStatus("Downloading..."),window.onerror=e=>{Module.setStatus("Exception thrown, see JavaScript console"),spinnerElement.style.display="none",Module.setStatus=e=>{e&&console.error("[post-exception status] "+e)}}</script><script async src="space-game001.js" crossorigin="anonymous"></script></body></html>
|
||||
@ -1,200 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
||||
<title>Sky Trek Tales</title>
|
||||
<style>
|
||||
body, html {
|
||||
margin: 0; padding: 0; width: 100%; height: 100%;
|
||||
overflow: hidden; background-color: #000;
|
||||
position: fixed;
|
||||
}
|
||||
#canvas {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0; left: 0;
|
||||
width: 100vw; height: 100vh;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#fs-button {
|
||||
position: absolute;
|
||||
top: 10px; right: 10px;
|
||||
padding: 10px;
|
||||
z-index: 10;
|
||||
background: rgba(255,255,255,0.3);
|
||||
color: white; border: 1px solid white;
|
||||
cursor: pointer;
|
||||
font-family: sans-serif;
|
||||
border-radius: 5px;
|
||||
}
|
||||
#status { color: white; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
|
||||
|
||||
/* Nick modal */
|
||||
#nickOverlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(0,0,0,0.85);
|
||||
z-index: 9999;
|
||||
}
|
||||
#nickBox {
|
||||
background: #111;
|
||||
border: 1px solid #444;
|
||||
padding: 24px;
|
||||
width: 320px;
|
||||
box-shadow: 0 8px 24px rgba(0,0,0,0.6);
|
||||
text-align: center;
|
||||
}
|
||||
#nickBox h2 { margin: 0 0 12px 0; font-size: 18px; color: #eee; }
|
||||
#nickBox input[type="text"] {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 12px;
|
||||
border: 1px solid #333;
|
||||
background: #000;
|
||||
color: #fff;
|
||||
}
|
||||
#nickBox button {
|
||||
padding: 10px 16px;
|
||||
font-size: 16px;
|
||||
background: #2a9fd6;
|
||||
border: none;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<button id="fs-button">Fullscreen</button>
|
||||
<div id="status">Downloading...</div>
|
||||
<canvas id="canvas" oncontextmenu="event.preventDefault()" tabindex="-1"></canvas>
|
||||
<div id="nickOverlay" style="display:none;">
|
||||
<div id="nickBox">
|
||||
<h2>Enter your nickname</h2>
|
||||
<input id="nickInput" type="text" maxlength="32" placeholder="Player" />
|
||||
<div>
|
||||
<button id="nickSubmit">Start</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Utility: подготовить глобальный Module до загрузки Emscripten-скрипта
|
||||
function prepareModuleEnvironment() {
|
||||
window.Module = window.Module || {};
|
||||
var canvasEl = document.getElementById('canvas');
|
||||
// Устанавливаем canvas для Emscripten, чтобы createContext не падал
|
||||
window.Module.canvas = canvasEl;
|
||||
// Подготовим заглушку setStatus, если ещё нет
|
||||
window.Module.setStatus = window.Module.setStatus || function (text) {
|
||||
var statusElement = document.getElementById("status");
|
||||
statusElement.innerHTML = text;
|
||||
statusElement.style.display = text ? 'block' : 'none';
|
||||
};
|
||||
}
|
||||
|
||||
// Show overlay only if no nickname saved.
|
||||
function loadGameScript() {
|
||||
var s = document.createElement('script');
|
||||
s.src = 'space-game001.js';
|
||||
s.async = true;
|
||||
document.body.appendChild(s);
|
||||
}
|
||||
|
||||
function showNickOverlay() {
|
||||
var overlay = document.getElementById('nickOverlay');
|
||||
overlay.style.display = 'flex';
|
||||
var input = document.getElementById('nickInput');
|
||||
input.focus();
|
||||
}
|
||||
|
||||
function hideNickOverlay() {
|
||||
var overlay = document.getElementById('nickOverlay');
|
||||
overlay.style.display = 'none';
|
||||
}
|
||||
|
||||
function saveNickAndStart(nick) {
|
||||
try {
|
||||
if (!nick || nick.trim() === '') nick = 'Player';
|
||||
localStorage.setItem('spacegame_nick', nick);
|
||||
} catch (e) {
|
||||
console.warn('localStorage not available', e);
|
||||
}
|
||||
hideNickOverlay();
|
||||
// перед загрузкой скрипта гарантируем, что Module.canvas задан
|
||||
prepareModuleEnvironment();
|
||||
loadGameScript();
|
||||
}
|
||||
|
||||
document.getElementById('fs-button').addEventListener('click', function() {
|
||||
if (!document.fullscreenElement) {
|
||||
document.documentElement.requestFullscreen().catch(function(e) {
|
||||
console.error('Fullscreen error: ' + e.message);
|
||||
});
|
||||
} else {
|
||||
document.exitFullscreen();
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Готовим Module сразу — даже если откроется модалка, поле canvas будет доступно для скрипта (если он загружается позже)
|
||||
prepareModuleEnvironment();
|
||||
|
||||
var stored = null;
|
||||
try {
|
||||
stored = localStorage.getItem('spacegame_nick');
|
||||
} catch (e) {
|
||||
console.warn('localStorage not available', e);
|
||||
}
|
||||
|
||||
if (stored && stored.trim() !== '') {
|
||||
// Nick is present — start immediately
|
||||
loadGameScript();
|
||||
} else {
|
||||
// Show modal to request nickname before loading WASM
|
||||
showNickOverlay();
|
||||
var submit = document.getElementById('nickSubmit');
|
||||
var input = document.getElementById('nickInput');
|
||||
|
||||
submit.addEventListener('click', function() {
|
||||
saveNickAndStart(input.value);
|
||||
});
|
||||
|
||||
input.addEventListener('input', function() {
|
||||
// Strip any character that is not a-z, A-Z, 0-9 or space
|
||||
var pos = this.selectionStart;
|
||||
var cleaned = this.value.replace(/[^a-zA-Z0-9 ]/g, '');
|
||||
if (cleaned !== this.value) {
|
||||
this.value = cleaned;
|
||||
this.setSelectionRange(pos - 1, pos - 1);
|
||||
}
|
||||
});
|
||||
|
||||
input.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Enter') {
|
||||
saveNickAndStart(input.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener("orientationchange", function() {
|
||||
// Chrome на Android обновляет innerWidth/Height не мгновенно.
|
||||
// Ждем завершения анимации поворота.
|
||||
setTimeout(() => {
|
||||
// В Emscripten это вызовет ваш onWindowResized в C++
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
}, 200);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@ -1,16 +1,19 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(witcher001 LANGUAGES C CXX)
|
||||
project(ShadowOverBishkekDemo LANGUAGES C CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Опция для интеграции Steamworks SDK (по умолчанию выключена)
|
||||
option(STEAMSDK "Enable Steamworks SDK integration" OFF)
|
||||
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ThirdParty.cmake)
|
||||
|
||||
# ===========================================
|
||||
# Основной проект witcher001
|
||||
# Основной проект ShadowOverBishkekDemo
|
||||
# ===========================================
|
||||
add_executable(witcher001
|
||||
add_executable(ShadowOverBishkekDemo WIN32
|
||||
../src/main.cpp
|
||||
../src/Game.cpp
|
||||
../src/Game.h
|
||||
@ -101,36 +104,32 @@ add_executable(witcher001
|
||||
../src/cutscene/CutsceneOverlay.h
|
||||
../src/cutscene/CutsceneOverlay.cpp
|
||||
../src/render/UiQuad.h
|
||||
app.rc
|
||||
)
|
||||
|
||||
# Установка проекта по умолчанию для Visual Studio
|
||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT witcher001)
|
||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ShadowOverBishkekDemo)
|
||||
|
||||
# include-пути проекта
|
||||
target_include_directories(witcher001 PRIVATE
|
||||
target_include_directories(ShadowOverBishkekDemo PRIVATE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../src"
|
||||
)
|
||||
|
||||
set_target_properties(witcher001 PROPERTIES
|
||||
OUTPUT_NAME "witcher001"
|
||||
set_target_properties(ShadowOverBishkekDemo PROPERTIES
|
||||
OUTPUT_NAME "ShadowOverBishkekDemo"
|
||||
)
|
||||
|
||||
# Определения препроцессора:
|
||||
# PNG_ENABLED – включает код PNG в TextureManager
|
||||
# SDL_MAIN_HANDLED – отключает переопределение main -> SDL_main
|
||||
target_compile_definitions(witcher001 PRIVATE
|
||||
# Определения препроцессора
|
||||
target_compile_definitions(ShadowOverBishkekDemo PRIVATE
|
||||
WIN32_LEAN_AND_MEAN
|
||||
PNG_ENABLED
|
||||
SDL_MAIN_HANDLED
|
||||
# DEBUG_LIGHT
|
||||
# SHOW_PATH
|
||||
)
|
||||
|
||||
# Линкуем с SDL2main, если он вообще установлен
|
||||
target_link_libraries(witcher001 PRIVATE SDL2main_external_lib)
|
||||
target_link_libraries(ShadowOverBishkekDemo PRIVATE SDL2main_external_lib)
|
||||
|
||||
# Линкуем сторонние библиотеки
|
||||
target_link_libraries(witcher001 PRIVATE
|
||||
target_link_libraries(ShadowOverBishkekDemo PRIVATE
|
||||
SDL2_external_lib
|
||||
libpng_external_lib
|
||||
zlib_external_lib
|
||||
@ -145,79 +144,186 @@ target_link_libraries(witcher001 PRIVATE
|
||||
|
||||
# Линкуем OpenGL (Windows)
|
||||
if(WIN32)
|
||||
target_link_libraries(witcher001 PRIVATE opengl32)
|
||||
target_link_libraries(ShadowOverBishkekDemo PRIVATE opengl32)
|
||||
endif()
|
||||
|
||||
# ===========================================
|
||||
# Копирование SDL2d.dll и zlibd.dll рядом с exe
|
||||
# Интеграция Steamworks SDK (если STEAMSDK=ON)
|
||||
# ===========================================
|
||||
if(STEAMSDK)
|
||||
message(STATUS "Steamworks SDK integration is ENABLED.")
|
||||
|
||||
target_compile_definitions(ShadowOverBishkekDemo PRIVATE STEAMSDK)
|
||||
|
||||
set(STEAM_SDK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/steamworks_sdk_164/sdk")
|
||||
|
||||
target_include_directories(ShadowOverBishkekDemo PRIVATE
|
||||
"${STEAM_SDK_DIR}/public"
|
||||
"${STEAM_SDK_DIR}/public/steam"
|
||||
)
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(STEAM_LIB_DIR "${STEAM_SDK_DIR}/redistributable_bin/win64")
|
||||
set(STEAM_LIB_NAME "steam_api64")
|
||||
set(STEAM_DLL_NAME "steam_api64.dll")
|
||||
else()
|
||||
set(STEAM_LIB_DIR "${STEAM_SDK_DIR}/redistributable_bin")
|
||||
set(STEAM_LIB_NAME "steam_api")
|
||||
set(STEAM_DLL_NAME "steam_api.dll")
|
||||
endif()
|
||||
|
||||
find_library(STEAM_LIBRARY
|
||||
NAMES ${STEAM_LIB_NAME}
|
||||
PATHS ${STEAM_LIB_DIR}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
if(STEAM_LIBRARY)
|
||||
target_link_libraries(ShadowOverBishkekDemo PRIVATE ${STEAM_LIBRARY})
|
||||
message(STATUS "Found Steam API library: ${STEAM_LIBRARY}")
|
||||
else()
|
||||
message(FATAL_ERROR "Steam API library (${STEAM_LIB_NAME}) NOT found in ${STEAM_LIB_DIR}!")
|
||||
endif()
|
||||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/steam_appid.txt" "4945840")
|
||||
else()
|
||||
message(STATUS "Steamworks SDK integration is DISABLED.")
|
||||
endif()
|
||||
|
||||
# ===========================================
|
||||
# Копирование DLL и ресурсов для локального запуска в Visual Studio
|
||||
# ===========================================
|
||||
if (WIN32)
|
||||
|
||||
# SDL2: в Debug - SDL2d.dll, в Release - SDL2.dll
|
||||
set(SDL2_DLL_SRC "$<IF:$<CONFIG:Debug>,${SDL2_INSTALL_DIR}/bin/SDL2d.dll,${SDL2_INSTALL_DIR}/bin/SDL2.dll>")
|
||||
set(SDL2_DLL_DST "$<IF:$<CONFIG:Debug>,$<TARGET_FILE_DIR:witcher001>/SDL2d.dll,$<TARGET_FILE_DIR:witcher001>/SDL2.dll>")
|
||||
|
||||
set(SDL2_DLL_DST "$<IF:$<CONFIG:Debug>,$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/SDL2d.dll,$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/SDL2.dll>")
|
||||
|
||||
set(LIBZIP_DLL_SRC "$<IF:$<CONFIG:Debug>,${LIBZIP_BASE_DIR}-Debug/bin/zip.dll,${LIBZIP_BASE_DIR}-Release/bin/zip.dll>")
|
||||
|
||||
set(ZLIB_DLL_SRC "$<IF:$<CONFIG:Debug>,${ZLIB_INSTALL_DIR}/bin/zd.dll,${ZLIB_INSTALL_DIR}/bin/z.dll>")
|
||||
set(ZLIB_DLL_DST "$<IF:$<CONFIG:Debug>,$<TARGET_FILE_DIR:witcher001>/zd.dll,$<TARGET_FILE_DIR:witcher001>/z.dll>")
|
||||
set(ZLIB_DLL_DST "$<IF:$<CONFIG:Debug>,$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/zd.dll,$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/z.dll>")
|
||||
|
||||
set(SDL2TTF_DLL_SRC "$<IF:$<CONFIG:Debug>,${SDL2TTF_BASE_DIR}-Debug/bin/SDL2_ttfd.dll,${SDL2TTF_BASE_DIR}-Release/bin/SDL2_ttf.dll>")
|
||||
|
||||
set(SDL2MIXER_DLL_SRC "$<IF:$<CONFIG:Debug>,${SDL2MIXER_BASE_DIR}-Debug/bin/SDL2_mixerd.dll,${SDL2MIXER_BASE_DIR}-Release/bin/SDL2_mixer.dll>")
|
||||
|
||||
add_custom_command(TARGET witcher001 POST_BUILD
|
||||
add_custom_command(TARGET ShadowOverBishkekDemo POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Copying DLLs to output folder..."
|
||||
|
||||
# Копируем SDL2 (целевое имя всегда SDL2.dll)
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${SDL2_DLL_SRC}"
|
||||
"${SDL2_DLL_DST}"
|
||||
|
||||
# Копируем LIBZIP (целевое имя всегда zip.dll)
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${LIBZIP_DLL_SRC}"
|
||||
"$<TARGET_FILE_DIR:witcher001>/zip.dll"
|
||||
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${ZLIB_DLL_SRC}"
|
||||
"${ZLIB_DLL_DST}"
|
||||
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${SDL2TTF_DLL_SRC}"
|
||||
"$<TARGET_FILE_DIR:witcher001>"
|
||||
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SDL2_DLL_SRC}" "${SDL2_DLL_DST}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${LIBZIP_DLL_SRC}" "$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/zip.dll"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ZLIB_DLL_SRC}" "${ZLIB_DLL_DST}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SDL2TTF_DLL_SRC}" "$<TARGET_FILE_DIR:ShadowOverBishkekDemo>"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/SDL_mixer-release-2.8.0/install-$<CONFIG>/bin/SDL2_mixer$<$<CONFIG:Debug>:d>.dll"
|
||||
|
||||
# This is only for profiling:
|
||||
#"${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/SDL_mixer-release-2.8.0/install-Release/bin/SDL2_mixer$<$<CONFIG:Debug>:d>.dll"
|
||||
"$<TARGET_FILE_DIR:witcher001>/SDL2_mixer$<$<CONFIG:Debug>:d>.dll"
|
||||
"$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/SDL2_mixer$<$<CONFIG:Debug>:d>.dll"
|
||||
)
|
||||
|
||||
if(STEAMSDK)
|
||||
add_custom_command(TARGET ShadowOverBishkekDemo POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Copying Steam SDK components..."
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${STEAM_LIB_DIR}/${STEAM_DLL_NAME}"
|
||||
"$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/${STEAM_DLL_NAME}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/steam_appid.txt"
|
||||
"$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/steam_appid.txt"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/steam_appid.txt"
|
||||
"${CMAKE_BINARY_DIR}/steam_appid.txt"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# ===========================================
|
||||
# Копирование ресурсов после сборки
|
||||
# ===========================================
|
||||
|
||||
# Какие папки с ресурсами нужно копировать
|
||||
set(RUNTIME_RESOURCE_DIRS
|
||||
"resources"
|
||||
"audio"
|
||||
)
|
||||
|
||||
# Копируем ресурсы и шейдеры в папку exe и в корень build/
|
||||
# Копирование ресурсов локально
|
||||
set(RUNTIME_RESOURCE_DIRS "resources" "music")
|
||||
foreach(resdir IN LISTS RUNTIME_RESOURCE_DIRS)
|
||||
add_custom_command(TARGET witcher001 POST_BUILD
|
||||
add_custom_command(TARGET ShadowOverBishkekDemo POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Copying ${resdir} to runtime folders..."
|
||||
# 1) туда, где лежит exe (build/Debug, build/Release и т.п.)
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
"${CMAKE_SOURCE_DIR}/../${resdir}"
|
||||
"$<TARGET_FILE_DIR:witcher001>/${resdir}"
|
||||
# 2) в корень build, если захочешь запускать из этой папки
|
||||
"$<TARGET_FILE_DIR:ShadowOverBishkekDemo>/${resdir}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
"${CMAKE_SOURCE_DIR}/../${resdir}"
|
||||
"${CMAKE_BINARY_DIR}/${resdir}"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# ===========================================
|
||||
# ПРАВИЛА ИНСТАЛЛЯЦИИ (Для CPack и создания пакетов)
|
||||
# ===========================================
|
||||
|
||||
# 1. Основной исполняемый файл
|
||||
install(TARGETS ShadowOverBishkekDemo DESTINATION .)
|
||||
|
||||
# 2. Необходимые DLL
|
||||
if(WIN32)
|
||||
install(FILES
|
||||
"${SDL2_INSTALL_DIR}/bin/SDL2.dll"
|
||||
"${LIBZIP_BASE_DIR}-Release/bin/zip.dll"
|
||||
"${ZLIB_INSTALL_DIR}/bin/z.dll"
|
||||
"${SDL2TTF_BASE_DIR}-Release/bin/SDL2_ttf.dll"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/SDL_mixer-release-2.8.0/install-Release/bin/SDL2_mixer.dll"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dist_dlls/concrt140.dll"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dist_dlls/msvcp140.dll"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dist_dlls/msvcp140_1.dll"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dist_dlls/msvcp140_2.dll"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dist_dlls/msvcp140_atomic_wait.dll"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dist_dlls/msvcp140_clr0400.dll"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dist_dlls/msvcp140_codecvt_ids.dll"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dist_dlls/msvcp140d.dll"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dist_dlls/OpenAL32.dll"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dist_dlls/vcamp140.dll"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dist_dlls/vccorlib140.dll"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dist_dlls/vcomp140.dll"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dist_dlls/vcruntime140.dll"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dist_dlls/vcruntime140_1.dll"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dist_dlls/vcruntime140_1_clr0400.dll"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dist_dlls/vcruntime140_threads.dll"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dist_dlls/wrap_oal.dll"
|
||||
DESTINATION .
|
||||
)
|
||||
|
||||
if(STEAMSDK)
|
||||
install(FILES
|
||||
"${STEAM_LIB_DIR}/${STEAM_DLL_NAME}"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/steam_appid.txt"
|
||||
DESTINATION .
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# 3. Директории с ресурсами
|
||||
foreach(resdir IN LISTS RUNTIME_RESOURCE_DIRS)
|
||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/../${resdir}" DESTINATION .)
|
||||
endforeach()
|
||||
|
||||
# ===========================================
|
||||
# НАСТРОЙКА CPACK (Создание ZIP Portable и NSIS Installer)
|
||||
# ===========================================
|
||||
set(CPACK_PACKAGE_NAME "ShadowOverBishkekDemo")
|
||||
set(CPACK_PACKAGE_VENDOR "Fish Run Games")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Shadow Over Bishkek Demo Version")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "1")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "0")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "5")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "Fish Run Games/Shadow Over Bishkek Demo")
|
||||
|
||||
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt")
|
||||
|
||||
# Настройки NSIS инсталлятора
|
||||
set(CPACK_NSIS_DISPLAY_NAME "Shadow Over Bishkek Demo")
|
||||
set(CPACK_NSIS_PACKAGE_NAME "Shadow Over Bishkek Demo")
|
||||
set(CPACK_NSIS_HELP_LINK "https://fishrungames.com/contact.html")
|
||||
set(CPACK_NSIS_URL_INFO_ABOUT "https://shadowoverbishkek.com/")
|
||||
set(CPACK_NSIS_MODIFY_PATH OFF)
|
||||
set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
|
||||
|
||||
# Иконки и ярлыки в меню Пуск и на Рабочем столе
|
||||
set(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}/icon.ico")
|
||||
set(CPACK_NSIS_MUI_UNIICON "${CMAKE_CURRENT_SOURCE_DIR}/icon.ico")
|
||||
set(CPACK_NSIS_CREATE_ICONS_EXTRA
|
||||
"CreateShortCut '$DESKTOP\\\\Shadow Over Bishkek Demo.lnk' '$INSTDIR\\\\ShadowOverBishkekDemo.exe'"
|
||||
)
|
||||
|
||||
# Форматы генераторов: ZIP (Portable) и NSIS (Установщик)
|
||||
set(CPACK_GENERATOR "ZIP;NSIS")
|
||||
|
||||
include(CPack)
|
||||
|
||||
21
proj-windows/LICENSE.txt
Normal file
21
proj-windows/LICENSE.txt
Normal file
@ -0,0 +1,21 @@
|
||||
END USER LICENSE AGREEMENT (EULA)
|
||||
|
||||
Game: Shadow Over Bishkek (Demo Version)
|
||||
Developer: Fish Run Games
|
||||
|
||||
1. GRANT OF LICENSE
|
||||
Fish Run Games grants you a non-exclusive, non-transferable, limited license to download, install, and play the Shadow Over Bishkek Demo for personal, non-commercial entertainment purposes.
|
||||
|
||||
2. OWNERSHIP & INTELLECTUAL PROPERTY
|
||||
The game, including all code, graphics, audio, characters, storyline, and assets, is the intellectual property of Fish Run Games and is protected by copyright and other intellectual property laws. You may not reverse engineer, decompile, modify, or redistribute the software without express written permission.
|
||||
|
||||
3. DISCLAIMER OF WARRANTY
|
||||
THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
4. USER DATA AND SAVES
|
||||
Save files and local configuration options are stored locally on your device. Fish Run Games is not responsible for any loss of save data resulting from software updates, system crashes, or uninstallation.
|
||||
|
||||
5. TERMINATION
|
||||
This license is effective until terminated. Your rights under this license will terminate automatically without notice from Fish Run Games if you fail to comply with any term(s) of this agreement.
|
||||
|
||||
Copyright (c) 2026 Fish Run Games. All rights reserved.
|
||||
1
proj-windows/app.rc
Normal file
1
proj-windows/app.rc
Normal file
@ -0,0 +1 @@
|
||||
IDI_ICON1 ICON "icon.ico"
|
||||
BIN
proj-windows/dist_dlls/OpenAL32.dll
(Stored with Git LFS)
Normal file
BIN
proj-windows/dist_dlls/OpenAL32.dll
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
proj-windows/dist_dlls/concrt140.dll
(Stored with Git LFS)
Normal file
BIN
proj-windows/dist_dlls/concrt140.dll
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
proj-windows/dist_dlls/msvcp140.dll
(Stored with Git LFS)
Normal file
BIN
proj-windows/dist_dlls/msvcp140.dll
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
proj-windows/dist_dlls/msvcp140_1.dll
(Stored with Git LFS)
Normal file
BIN
proj-windows/dist_dlls/msvcp140_1.dll
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
proj-windows/dist_dlls/msvcp140_2.dll
(Stored with Git LFS)
Normal file
BIN
proj-windows/dist_dlls/msvcp140_2.dll
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
proj-windows/dist_dlls/msvcp140_atomic_wait.dll
(Stored with Git LFS)
Normal file
BIN
proj-windows/dist_dlls/msvcp140_atomic_wait.dll
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
proj-windows/dist_dlls/msvcp140_clr0400.dll
(Stored with Git LFS)
Normal file
BIN
proj-windows/dist_dlls/msvcp140_clr0400.dll
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
proj-windows/dist_dlls/msvcp140_codecvt_ids.dll
(Stored with Git LFS)
Normal file
BIN
proj-windows/dist_dlls/msvcp140_codecvt_ids.dll
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
proj-windows/dist_dlls/msvcp140d.dll
(Stored with Git LFS)
Normal file
BIN
proj-windows/dist_dlls/msvcp140d.dll
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
proj-windows/dist_dlls/vcamp140.dll
(Stored with Git LFS)
Normal file
BIN
proj-windows/dist_dlls/vcamp140.dll
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
proj-windows/dist_dlls/vccorlib140.dll
(Stored with Git LFS)
Normal file
BIN
proj-windows/dist_dlls/vccorlib140.dll
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
proj-windows/dist_dlls/vcomp140.dll
(Stored with Git LFS)
Normal file
BIN
proj-windows/dist_dlls/vcomp140.dll
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
proj-windows/dist_dlls/vcruntime140.dll
(Stored with Git LFS)
Normal file
BIN
proj-windows/dist_dlls/vcruntime140.dll
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
proj-windows/dist_dlls/vcruntime140_1.dll
(Stored with Git LFS)
Normal file
BIN
proj-windows/dist_dlls/vcruntime140_1.dll
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
proj-windows/dist_dlls/vcruntime140_1_clr0400.dll
(Stored with Git LFS)
Normal file
BIN
proj-windows/dist_dlls/vcruntime140_1_clr0400.dll
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
proj-windows/dist_dlls/vcruntime140_threads.dll
(Stored with Git LFS)
Normal file
BIN
proj-windows/dist_dlls/vcruntime140_threads.dll
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
proj-windows/dist_dlls/wrap_oal.dll
(Stored with Git LFS)
Normal file
BIN
proj-windows/dist_dlls/wrap_oal.dll
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
proj-windows/icon.ico
Normal file
BIN
proj-windows/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 361 KiB |
@ -3,7 +3,7 @@
|
||||
{
|
||||
"id": "main_hall",
|
||||
"positionX": -3.1,
|
||||
"positionY": 6.0,
|
||||
"positionY": 4.8,
|
||||
"positionZ": 0.0,
|
||||
"directionX": 0.0,
|
||||
"directionY": -1.0,
|
||||
@ -20,7 +20,7 @@
|
||||
"limitX": 3.75,
|
||||
"limitY": 2.75,
|
||||
"positionX": 4.95,
|
||||
"positionY": 3.0,
|
||||
"positionY": 3.6,
|
||||
"positionZ": -14.25,
|
||||
"directionX": 0.0,
|
||||
"directionY": -1.0,
|
||||
@ -55,7 +55,7 @@
|
||||
"limitX": 3.75,
|
||||
"limitY": 2.75,
|
||||
"positionX": -4.95,
|
||||
"positionY": 4.0,
|
||||
"positionY": 4.2,
|
||||
"positionZ": -19.95,
|
||||
"directionX": 0.0,
|
||||
"directionY": -1.0,
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
"animationIdlePath": "resources/w/girlfriend/girlfriend_idle003_small.anim",
|
||||
"animationWalkPath": "resources/w/girlfriend/girlfriend_walk003_small.anim",
|
||||
"meshTextures": {
|
||||
"Girl_Low": "resources/w/girlfriend/Girl_Base_color.png"
|
||||
"Girl_Low": "resources/w/girlfriend/Girl_Base_color006.png"
|
||||
},
|
||||
"positionX": 0.799619,
|
||||
"positionY": 0.0,
|
||||
|
||||
@ -1122,9 +1122,9 @@
|
||||
"waypointReachRadius": 3.0,
|
||||
"waypoints": []
|
||||
},
|
||||
"taxiCarTriggerPositionX": -1.7014118346046923e+38,
|
||||
"taxiCarTriggerPositionY": -1.7014118346046923e+38,
|
||||
"taxiCarTriggerPositionZ": -1.7014118346046923e+38,
|
||||
"taxiCarTriggerPositionX": 0.0,
|
||||
"taxiCarTriggerPositionY": 0.0,
|
||||
"taxiCarTriggerPositionZ": 0.0,
|
||||
"taxiDefaultWaypoints": []
|
||||
},
|
||||
"tutorialInteractiveObjectsLocked": false
|
||||
@ -1476,7 +1476,6 @@
|
||||
"morning_can_open_door_index": 0,
|
||||
"morning_did_open_door_index": 0,
|
||||
"player_hold_book": false,
|
||||
"player_hold_knife": false,
|
||||
"teacher_arrived_to_library": false,
|
||||
"teacher_door_opened": false,
|
||||
"teacher_told_about_book": false,
|
||||
@ -1652,7 +1651,7 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"savedAt": "2026-07-14 14:00",
|
||||
"savedAt": "2026-07-24 23:40",
|
||||
"taxiIsCalled": false,
|
||||
"tutorialJournalPickedUp": false,
|
||||
"tutorialJournalScreenOpened": false,
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
{
|
||||
"key": "Аида Дженибековна",
|
||||
"ru": "Аида Дженибековна",
|
||||
"en": "Aida Dzhanybekovna"
|
||||
"en": "Aida Dzhenibekovna"
|
||||
},
|
||||
{
|
||||
"key": "Алтынай",
|
||||
|
||||
@ -44,8 +44,8 @@
|
||||
},
|
||||
{
|
||||
"id": "report_card",
|
||||
"name": "Begimai's grade book",
|
||||
"description": "This is Begimai's grade book. This is where a teacher should write grades for each subject or coursework.",
|
||||
"name": "Begimai's record book",
|
||||
"description": "This is Begimai's record book. This is where a teacher should write grades for each subject or coursework.",
|
||||
"icon": "resources/w/ui/img/inv/ItemReportCard002.png",
|
||||
"selectedIcon": "resources/w/ui/img/inv/ItemSelReportCard002.png"
|
||||
},
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
"objectives": [
|
||||
{ "id": "ghost_lore_aiperi", "text": "Talk to Aiperi", "completed": false },
|
||||
{ "id": "ghost_lore_alik", "text": "Talk to Alik", "completed": false, "visible": false },
|
||||
{ "id": "ghost_lore_teacher", "text": "Talk to Aida Dzhanybekovna", "completed": false }
|
||||
{ "id": "ghost_lore_teacher", "text": "Talk to Aida Dzhenibekovna", "completed": false }
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -31,7 +31,7 @@
|
||||
"description": "Begimai's story is even more mysterious. While her coursework was due, the university was undergoing a general cleaning. By chance, her coursework ended up in the trash bin. As a result, her coursework was thrown away, the professor was not able to find it, and gave her a zero grade. According to Alik, the coursework still lies in a pile of trash in the university courtyard.",
|
||||
"objectives": [
|
||||
{ "id": "ghost_coursework_find", "text": "Find Begimai's coursework", "completed": false },
|
||||
{ "id": "ghost_coursework_mark", "text": "Show coursework to Aida Dzhanybekovna", "completed": false }
|
||||
{ "id": "ghost_coursework_mark", "text": "Show coursework to Aida Dzhenibekovna", "completed": false }
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -41,9 +41,9 @@
|
||||
"autoComplete": true,
|
||||
"description": "A student named Begimai actually attended university last year. She tried to submit a coursework, but due to a series of circumstances, she failed and received a zero grade. This coursework shattered all her plans and hopes, and Begimai jumped out the window. Now she's returned as a ghost, and to be liberated, she must ensure she receives a grade for the coursework.",
|
||||
"objectives": [
|
||||
{ "id": "ghost_release_reportcard", "text": "Find Begimai's grade book", "completed": false },
|
||||
{ "id": "ghost_release_mark", "text": "Put a grade for the coursework in the grade book", "completed": false },
|
||||
{ "id": "ghost_release_show", "text": "Show the grade book to the ghost", "completed": false }
|
||||
{ "id": "ghost_release_reportcard", "text": "Find Begimai's record book", "completed": false },
|
||||
{ "id": "ghost_release_mark", "text": "Put a grade for the coursework in the record book", "completed": false },
|
||||
{ "id": "ghost_release_show", "text": "Show the record book to the ghost", "completed": false }
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -51,7 +51,7 @@
|
||||
"title": "Manas studies",
|
||||
"status": "Available",
|
||||
"autoComplete": true,
|
||||
"description": "There's a Manas Studies module coming up soon, and I've never attended a lecture before. We have a Manas Studies lecture today, so I need to attend it and get the module assignment from my teacher, Aida Dzhanybekovna.",
|
||||
"description": "There's a Manas Studies module coming up soon, and I've never attended a lecture before. We have a Manas Studies lecture today, so I need to attend it and get the module assignment from my teacher, Aida Dzhenibekovna.",
|
||||
"objectives": [
|
||||
{ "id": "study_beginning_lecture", "text": "Attend the lecture", "completed": false },
|
||||
{ "id": "study_beginning_task", "text": "Get an assignment for the module", "completed": false }
|
||||
@ -61,7 +61,7 @@
|
||||
"id": "study_project",
|
||||
"title": "Essay on Manaschi",
|
||||
"status": "Hidden",
|
||||
"description": "My Manas studies teacher, Aida Dzhanybekovna, gave me an assignment: find a book about Zhusup Mamai's Manaschi in the library and write an essay about it. The book isn't allowed out of the library, but I can use the library's computer to write the essay. The essay must be completed before tomorrow.",
|
||||
"description": "My Manas studies teacher, Aida Dzhenibekovna, gave me an assignment: find a book about Zhusup Mamai's Manaschi in the library and write an essay about it. The book isn't allowed out of the library, but I can use the library's computer to write the essay. The essay must be completed before tomorrow.",
|
||||
"objectives": [
|
||||
{ "id": "study_project_book", "text": "Find the book", "completed": false },
|
||||
{ "id": "study_project_write", "text": "Write the essay", "completed": false },
|
||||
|
||||
@ -1,290 +0,0 @@
|
||||
{
|
||||
"dialogues": [
|
||||
{
|
||||
"id": "test_cutscene_skip_hold_dialogue",
|
||||
"start": "cutscene_start",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "cutscene_start",
|
||||
"type": "CutsceneStart",
|
||||
"cutsceneId": "test_cutscene_skip_hold_01",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
"id": "end_1",
|
||||
"type": "End"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "test_cutscene_images_hardcut_dialogue",
|
||||
"start": "cutscene_start",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "cutscene_start",
|
||||
"type": "CutsceneStart",
|
||||
"cutsceneId": "test_cutscene_images_hardcut_01",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
"id": "end_1",
|
||||
"type": "End"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "test_cutscene_images_crossfade_dialogue",
|
||||
"start": "cutscene_start",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "cutscene_start",
|
||||
"type": "CutsceneStart",
|
||||
"cutsceneId": "test_cutscene_images_crossfade_01",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
"id": "end_1",
|
||||
"type": "End"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "test_cutscene_images_silent_dialogue",
|
||||
"start": "cutscene_start",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "cutscene_start",
|
||||
"type": "CutsceneStart",
|
||||
"cutsceneId": "test_cutscene_images_silent_01",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
"id": "end_1",
|
||||
"type": "End"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"cutscenes": [
|
||||
{
|
||||
"id": "test_cutscene_skip_hold_01",
|
||||
"background": "resources/first_cutscene.png",
|
||||
"skippable": true,
|
||||
"durationMs": 12000,
|
||||
"cameraTrack": [
|
||||
{
|
||||
"durationMs": 3000,
|
||||
"from": { "anchor": "Center", "zoom": 1.0, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "TopLeft", "zoom": 1.45, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInOutSine"
|
||||
},
|
||||
{
|
||||
"durationMs": 3000,
|
||||
"from": { "anchor": "TopLeft", "zoom": 1.45, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "TopRight", "zoom": 1.45, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInOutSine"
|
||||
},
|
||||
{
|
||||
"durationMs": 3000,
|
||||
"from": { "anchor": "TopRight", "zoom": 1.45, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "BottomRight", "zoom": 1.65, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInCubic"
|
||||
},
|
||||
{
|
||||
"durationMs": 3000,
|
||||
"from": { "anchor": "BottomRight", "zoom": 1.65, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "BottomLeft", "zoom": 1.45, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInOutSine"
|
||||
}
|
||||
],
|
||||
"lines": [
|
||||
{
|
||||
"speaker": "Narrator",
|
||||
"portrait": "",
|
||||
"text": "This cutscene is long enough to test hold-to-skip.",
|
||||
"durationMs": 2600
|
||||
},
|
||||
{
|
||||
"speaker": "Narrator",
|
||||
"portrait": "",
|
||||
"text": "A normal click must not skip it.",
|
||||
"durationMs": 2600
|
||||
},
|
||||
{
|
||||
"speaker": "Ghost",
|
||||
"portrait": "resources/ghost_avatar.png",
|
||||
"text": "Only the skip button with hold should work.",
|
||||
"durationMs": 2600
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "test_cutscene_images_hardcut_01",
|
||||
"background": "resources/first_cutscene.png",
|
||||
"skippable": true,
|
||||
"durationMs": 9000,
|
||||
"cameraTrack": [
|
||||
{
|
||||
"durationMs": 4500,
|
||||
"from": { "anchor": "Center", "zoom": 1.0, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "TopLeft", "zoom": 1.35, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInOutSine"
|
||||
},
|
||||
{
|
||||
"durationMs": 4500,
|
||||
"from": { "anchor": "TopLeft", "zoom": 1.35, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "BottomRight", "zoom": 1.55, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInOutSine"
|
||||
}
|
||||
],
|
||||
"images": [
|
||||
{
|
||||
"path": "resources/first_cutscene.png",
|
||||
"startMs": 0,
|
||||
"endMs": 4500,
|
||||
"fadeInMs": 0,
|
||||
"fadeOutMs": 0
|
||||
},
|
||||
{
|
||||
"path": "resources/second_cutscene.png",
|
||||
"startMs": 4500,
|
||||
"endMs": 9000,
|
||||
"fadeInMs": 0,
|
||||
"fadeOutMs": 0
|
||||
}
|
||||
],
|
||||
"lines": [
|
||||
{
|
||||
"speaker": "Narrator",
|
||||
"portrait": "",
|
||||
"text": "First image should switch sharply to the second one.",
|
||||
"durationMs": 2800
|
||||
},
|
||||
{
|
||||
"speaker": "Narrator",
|
||||
"portrait": "",
|
||||
"text": "No fade should be visible here.",
|
||||
"durationMs": 2800
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "test_cutscene_images_crossfade_01",
|
||||
"background": "resources/first_cutscene.png",
|
||||
"skippable": true,
|
||||
"durationMs": 10000,
|
||||
"cameraTrack": [
|
||||
{
|
||||
"durationMs": 2500,
|
||||
"from": { "anchor": "Center", "zoom": 1.0, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "Custom", "centerX": 0.35, "centerY": 0.30, "zoom": 1.45, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInOutQuad"
|
||||
},
|
||||
{
|
||||
"durationMs": 2500,
|
||||
"from": { "anchor": "Custom", "centerX": 0.35, "centerY": 0.30, "zoom": 1.45, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "Custom", "centerX": 0.70, "centerY": 0.32, "zoom": 1.45, "rotationDeg": 0.0 },
|
||||
"easing": "EaseOutCubic"
|
||||
},
|
||||
{
|
||||
"durationMs": 2500,
|
||||
"from": { "anchor": "Custom", "centerX": 0.70, "centerY": 0.32, "zoom": 1.45, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "BottomRight", "zoom": 1.70, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInCubic"
|
||||
},
|
||||
{
|
||||
"durationMs": 2500,
|
||||
"from": { "anchor": "BottomRight", "zoom": 1.70, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "BottomLeft", "zoom": 1.55, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInOutSine"
|
||||
}
|
||||
],
|
||||
"images": [
|
||||
{
|
||||
"path": "resources/first_cutscene.png",
|
||||
"startMs": 0,
|
||||
"endMs": 6000,
|
||||
"fadeInMs": 0,
|
||||
"fadeOutMs": 0
|
||||
},
|
||||
{
|
||||
"path": "resources/second_cutscene.png",
|
||||
"startMs": 4500,
|
||||
"endMs": 10000,
|
||||
"fadeInMs": 1500,
|
||||
"fadeOutMs": 0
|
||||
}
|
||||
],
|
||||
"lines": [
|
||||
{
|
||||
"speaker": "Narrator",
|
||||
"portrait": "",
|
||||
"text": "The second image should fade over the first one.",
|
||||
"durationMs": 2600
|
||||
},
|
||||
{
|
||||
"speaker": "Ghost",
|
||||
"portrait": "resources/ghost_avatar.png",
|
||||
"text": "This test checks overlap and alpha blending.",
|
||||
"durationMs": 2600
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "test_cutscene_images_silent_01",
|
||||
"background": "resources/first_cutscene.png",
|
||||
"skippable": true,
|
||||
"durationMs": 11000,
|
||||
"cameraTrack": [
|
||||
{
|
||||
"durationMs": 2500,
|
||||
"from": { "anchor": "Center", "zoom": 1.0, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "TopLeft", "zoom": 1.35, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInOutSine"
|
||||
},
|
||||
{
|
||||
"durationMs": 3000,
|
||||
"from": { "anchor": "TopLeft", "zoom": 1.35, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "TopRight", "zoom": 1.35, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInOutSine"
|
||||
},
|
||||
{
|
||||
"durationMs": 3000,
|
||||
"from": { "anchor": "TopRight", "zoom": 1.35, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "BottomRight", "zoom": 1.55, "rotationDeg": 0.0 },
|
||||
"easing": "EaseOutCubic"
|
||||
},
|
||||
{
|
||||
"durationMs": 2500,
|
||||
"from": { "anchor": "BottomRight", "zoom": 1.55, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "BottomLeft", "zoom": 1.45, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInOutQuad"
|
||||
}
|
||||
],
|
||||
"images": [
|
||||
{
|
||||
"path": "resources/first_cutscene.png",
|
||||
"startMs": 0,
|
||||
"endMs": 3500,
|
||||
"fadeInMs": 0,
|
||||
"fadeOutMs": 800
|
||||
},
|
||||
{
|
||||
"path": "resources/second_cutscene.png",
|
||||
"startMs": 3000,
|
||||
"endMs": 7500,
|
||||
"fadeInMs": 800,
|
||||
"fadeOutMs": 1000
|
||||
},
|
||||
{
|
||||
"path": "resources/loading.png",
|
||||
"startMs": 7000,
|
||||
"endMs": 11000,
|
||||
"fadeInMs": 1000,
|
||||
"fadeOutMs": 0
|
||||
}
|
||||
],
|
||||
"lines": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -155,7 +155,7 @@
|
||||
"type": "Line",
|
||||
"speaker": "Бекзат",
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Почему ты сама не можешь забрать?",
|
||||
"text": "Почему ты сама не можешь забрать нож у Аиды?",
|
||||
"next": "line_9",
|
||||
"chatBubble": "out"
|
||||
},
|
||||
@ -164,7 +164,16 @@
|
||||
"type": "Line",
|
||||
"speaker": "Айпери",
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Ты же знаешь, если я встречу Аиду, она 100% даст мне какое-нибудь сложное задание.",
|
||||
"text": "Она опять будет скафнить.",
|
||||
"next": "line_12",
|
||||
"chatBubble": "in"
|
||||
},
|
||||
{
|
||||
"id": "line_12",
|
||||
"type": "Line",
|
||||
"speaker": "Айпери",
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "А может быть даже даст мне какое-нибудь сложное задание.",
|
||||
"next": "line_10",
|
||||
"chatBubble": "in"
|
||||
},
|
||||
@ -182,7 +191,7 @@
|
||||
"type": "Line",
|
||||
"speaker": "Айпери",
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Так что жду тебя в универе! Не вздумай прогулять!",
|
||||
"text": "Так что жду тебя в универе! Не вздумай прогулять! Ошо!",
|
||||
"next": "setflag_1",
|
||||
"chatBubble": "in",
|
||||
"questUnlock": "aiperi_knife"
|
||||
@ -359,7 +368,7 @@
|
||||
"type": "Line",
|
||||
"speaker": "Бекзат",
|
||||
"portrait": "resources/dialogue/portrait_hero_neutral.png",
|
||||
"text": "Я заказал такси до универа, машина уже ждет!",
|
||||
"text": "Я заказал такси до универа, машина уже едет!",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
@ -647,7 +656,7 @@
|
||||
"type": "Line",
|
||||
"speaker": "Алик",
|
||||
"portrait": "resources/dialogue/portrait_student_boy.png",
|
||||
"text": "За зданием универа есть контейнер с кучей бумажного мусора и макулатурой.",
|
||||
"text": "Возле здания универа лежит куча строительного мусора и макулатуры.",
|
||||
"next": "line_14"
|
||||
},
|
||||
{
|
||||
@ -1,501 +0,0 @@
|
||||
{
|
||||
"dialogues": [
|
||||
{
|
||||
"id": "dialog_student",
|
||||
"start": "line_1",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "line_1",
|
||||
"type": "Line",
|
||||
"speaker": "Студент",
|
||||
"portrait": "resources/w/avatar_student.png",
|
||||
"text": "В университете завелись призраки, мне страшно ходить на занятия.",
|
||||
"next": "line_2"
|
||||
},
|
||||
{
|
||||
"id": "line_2",
|
||||
"type": "Line",
|
||||
"speaker": "Hero",
|
||||
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
|
||||
"text": "Можешь рассказать подробнее?",
|
||||
"next": "line_3"
|
||||
},
|
||||
{
|
||||
"id": "line_3",
|
||||
"type": "Line",
|
||||
"speaker": "Студент",
|
||||
"portrait": "resources/w/avatar_student.png",
|
||||
"text": "Спроси у Мухтара байке, он все знает.",
|
||||
"next": "line_4"
|
||||
},
|
||||
{
|
||||
"id": "line_4",
|
||||
"type": "Line",
|
||||
"speaker": "Hero",
|
||||
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
|
||||
"text": "Хорошо.",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
"id": "end_1",
|
||||
"type": "End"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "dialog_mukhtar",
|
||||
"start": "line_1",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "line_1",
|
||||
"type": "Line",
|
||||
"speaker": "Мухтар байке",
|
||||
"portrait": "resources/w/avatar_unknown.png",
|
||||
"text": "Здравствуй, мы давно тебя ждем! Ты поможешь нам избавиться от призраков?",
|
||||
"next": "line_2"
|
||||
},
|
||||
{
|
||||
"id": "line_2",
|
||||
"type": "Line",
|
||||
"speaker": "Hero",
|
||||
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
|
||||
"text": "Где их найти?",
|
||||
"next": "line_3"
|
||||
},
|
||||
{
|
||||
"id": "line_3",
|
||||
"type": "Line",
|
||||
"speaker": "Мухтар байке",
|
||||
"portrait": "resources/w/avatar_unknown.png",
|
||||
"text": "Заходи в здание универа и поднимайся на второй этаж.",
|
||||
"next": "line_4"
|
||||
},
|
||||
{
|
||||
"id": "line_4",
|
||||
"type": "Line",
|
||||
"speaker": "Мухтар байке",
|
||||
"portrait": "resources/w/avatar_unknown.png",
|
||||
"text": "Ты их встретишь прямо там.",
|
||||
"next": "line_5"
|
||||
},
|
||||
{
|
||||
"id": "line_4",
|
||||
"type": "Line",
|
||||
"speaker": "Hero",
|
||||
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
|
||||
"text": "Хорошо, я скоро вернусь!",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
"id": "end_1",
|
||||
"type": "End"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "dialog_female_student",
|
||||
"start": "line_1",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "line_1",
|
||||
"type": "Line",
|
||||
"speaker": "Студентка",
|
||||
"portrait": "resources/w/avatar_girl.png",
|
||||
"text": "С этими призраками совсем невозможно ходить на лекции!",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
"id": "end_1",
|
||||
"type": "End"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "test_line_dialogue",
|
||||
"start": "line_1",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "line_1",
|
||||
"type": "Line",
|
||||
"speaker": "Ghost",
|
||||
"portrait": "resources/ghost_avatar.png",
|
||||
"text": "Наконец-то ты пришел.",
|
||||
"next": "line_2"
|
||||
},
|
||||
{
|
||||
"id": "line_2",
|
||||
"type": "Line",
|
||||
"speaker": "Hero",
|
||||
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
|
||||
"text": "Ты сделан из дыма?",
|
||||
"next": "line_3"
|
||||
},
|
||||
{
|
||||
"id": "line_3",
|
||||
"type": "Line",
|
||||
"speaker": "Ghost",
|
||||
"portrait": "resources/ghost_avatar.png",
|
||||
"text": "Ты думаешь, это смешно?",
|
||||
"next": "line_4"
|
||||
},
|
||||
{
|
||||
"id": "line_4",
|
||||
"type": "Line",
|
||||
"speaker": "Hero",
|
||||
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
|
||||
"text": "Я думаю что ты пахнешь как выхлоп от Камаза.",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
"id": "end_1",
|
||||
"type": "End"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ghost_choice_dialogue",
|
||||
"start": "line_1",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "line_1",
|
||||
"type": "Line",
|
||||
"speaker": "Беспокойный Призрак",
|
||||
"portrait": "resources/w/avatar_ghost.png",
|
||||
"text": "Нечасто я вижу смертных, готовых разговаривать со мной.",
|
||||
"next": "choice_1"
|
||||
},
|
||||
{
|
||||
"id": "choice_1",
|
||||
"type": "Choice",
|
||||
"speaker": "Hero",
|
||||
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
|
||||
"text": "",
|
||||
"choices": [
|
||||
{
|
||||
"id": "main_1",
|
||||
"kind": "Main",
|
||||
"text": "Не мешай студентам учиться!",
|
||||
"next": "line_goods"
|
||||
},
|
||||
{
|
||||
"id": "optional_1",
|
||||
"kind": "Optional",
|
||||
"text": "Почему ты появился здесь?",
|
||||
"next": "line_who"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "line_goods",
|
||||
"type": "Line",
|
||||
"speaker": "Беспокойный Призрак",
|
||||
"portrait": "resources/w/avatar_ghost.png",
|
||||
"text": "Это моя месть студентам за то что они призвали меня.",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
"id": "line_who",
|
||||
"type": "Line",
|
||||
"speaker": "Беспокойный Призрак",
|
||||
"portrait": "resources/w/avatar_ghost.png",
|
||||
"text": "Группа студентов совершила ритуал и призвала меня сюда. Пока проклятие не спадет, я всегда буду здесь обитать.",
|
||||
"next": "choice_1"
|
||||
},
|
||||
{
|
||||
"id": "end_1",
|
||||
"type": "End"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "test_condition_dialogue",
|
||||
"start": "set_flag_1",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "set_flag_1",
|
||||
"type": "SetFlag",
|
||||
"effects": [
|
||||
{ "flag": "met_ghost", "value": 1 }
|
||||
],
|
||||
"next": "condition_1"
|
||||
},
|
||||
{
|
||||
"id": "condition_1",
|
||||
"type": "Condition",
|
||||
"conditions": [
|
||||
{ "flag": "met_ghost", "op": "Equals", "value": 1 }
|
||||
],
|
||||
"trueNext": "line_true",
|
||||
"falseNext": "line_false"
|
||||
},
|
||||
{
|
||||
"id": "line_true",
|
||||
"type": "Line",
|
||||
"speaker": "Ghost",
|
||||
"portrait": "resources/ghost_avatar.png",
|
||||
"text": "Now you know who I am.",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
"id": "line_false",
|
||||
"type": "Line",
|
||||
"speaker": "Ghost",
|
||||
"portrait": "resources/ghost_avatar.png",
|
||||
"text": "You should not hear this line.",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
"id": "end_1",
|
||||
"type": "End"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "test_cutscene_dialogue",
|
||||
"start": "cutscene_start",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "cutscene_start",
|
||||
"type": "CutsceneStart",
|
||||
"cutsceneId": "test_cutscene_01",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
"id": "end_1",
|
||||
"type": "End"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "test_silent_cutscene_dialogue",
|
||||
"start": "cutscene_start",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "cutscene_start",
|
||||
"type": "CutsceneStart",
|
||||
"cutsceneId": "test_cutscene_silent_01",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
"id": "end_1",
|
||||
"type": "End"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "test_cutscene_pan_dialogue",
|
||||
"start": "cutscene_start",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "cutscene_start",
|
||||
"type": "CutsceneStart",
|
||||
"cutsceneId": "test_cutscene_pan_01",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
"id": "end_1",
|
||||
"type": "End"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "test_cutscene_pan_dialogue_silent",
|
||||
"start": "cutscene_start",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "cutscene_start",
|
||||
"type": "CutsceneStart",
|
||||
"cutsceneId": "test_cutscene_pan_02",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
"id": "end_1",
|
||||
"type": "End"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "dialog_aida",
|
||||
"start": "line_1",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "line_1",
|
||||
"type": "Line",
|
||||
"speaker": "Асель Дженибековна",
|
||||
"portrait": "resources/w/avatar_teacher.png",
|
||||
"text": "Молодой человек, у меня обед! Я принимаю лабораторные работы только после двух!",
|
||||
"next": "line_2"
|
||||
},
|
||||
{
|
||||
"id": "line_2",
|
||||
"type": "Line",
|
||||
"speaker": "Hero",
|
||||
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
|
||||
"text": "Хорошо, Асель Дженибековна.",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
"id": "end_1",
|
||||
"type": "End"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"cutscenes": [
|
||||
{
|
||||
"id": "test_cutscene_01",
|
||||
"background": "resources/first_cutscene.png",
|
||||
"durationMs": 6800,
|
||||
"cameraTrack": [
|
||||
{
|
||||
"durationMs": 2400,
|
||||
"from": { "focusX": 0.50, "focusY": 0.55, "zoom": 1.00, "rotationDeg": 0.0 },
|
||||
"to": { "focusX": 0.63, "focusY": 0.58, "zoom": 1.16, "rotationDeg": -1.0 },
|
||||
"easing": "EaseInOutSine"
|
||||
},
|
||||
{
|
||||
"durationMs": 2200,
|
||||
"from": { "focusX": 0.63, "focusY": 0.58, "zoom": 1.16, "rotationDeg": -1.0 },
|
||||
"to": { "focusX": 0.74, "focusY": 0.52, "zoom": 1.30, "rotationDeg": -2.4 },
|
||||
"easing": "EaseInOutCubic"
|
||||
},
|
||||
{
|
||||
"durationMs": 2200,
|
||||
"from": { "focusX": 0.74, "focusY": 0.52, "zoom": 1.30, "rotationDeg": -2.4 },
|
||||
"to": { "focusX": 0.58, "focusY": 0.46, "zoom": 1.10, "rotationDeg": -0.6 },
|
||||
"easing": "EaseOutSine"
|
||||
}
|
||||
],
|
||||
"lines": [
|
||||
{
|
||||
"speaker": "Narrator",
|
||||
"portrait": "resources/hero.png",
|
||||
"text": "The air in the room turned cold.",
|
||||
"durationMs": 2200
|
||||
},
|
||||
{
|
||||
"speaker": "Ghost",
|
||||
"portrait": "resources/w/avatar_ghost.png",
|
||||
"text": "Some memories never fade.",
|
||||
"durationMs": 2600,
|
||||
"background": "resources/loading.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "test_cutscene_silent_01",
|
||||
"background": "resources/first_cutscene.png",
|
||||
"durationMs": 5200,
|
||||
"cameraTrack": [
|
||||
{
|
||||
"durationMs": 2600,
|
||||
"from": { "focusX": 0.40, "focusY": 0.54, "zoom": 1.00, "rotationDeg": 0.0 },
|
||||
"to": { "focusX": 0.58, "focusY": 0.54, "zoom": 1.22, "rotationDeg": 0.8 },
|
||||
"easing": "EaseInOutSine"
|
||||
},
|
||||
{
|
||||
"durationMs": 2600,
|
||||
"from": { "focusX": 0.58, "focusY": 0.54, "zoom": 1.22, "rotationDeg": 0.8 },
|
||||
"to": { "focusX": 0.72, "focusY": 0.48, "zoom": 1.34, "rotationDeg": -0.5 },
|
||||
"easing": "EaseOutCubic"
|
||||
}
|
||||
],
|
||||
"lines": []
|
||||
},
|
||||
{
|
||||
"id": "test_cutscene_pan_01",
|
||||
"background": "resources/first_cutscene.png",
|
||||
"durationMs": 12000,
|
||||
"cameraTrack": [
|
||||
{
|
||||
"durationMs": 1200,
|
||||
"from": { "anchor": "Center", "zoom": 1.00, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "Center", "zoom": 1.00, "rotationDeg": 0.0 },
|
||||
"easing": "Linear"
|
||||
},
|
||||
{
|
||||
"durationMs": 2500,
|
||||
"from": { "anchor": "Center", "zoom": 1.00, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "TopLeft", "zoom": 1.55, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInOutSine"
|
||||
},
|
||||
{
|
||||
"durationMs": 2600,
|
||||
"from": { "anchor": "TopLeft", "zoom": 1.55, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "TopRight", "zoom": 1.55, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInOutSine"
|
||||
},
|
||||
{
|
||||
"durationMs": 1800,
|
||||
"from": { "anchor": "TopRight", "zoom": 1.55, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "BottomRight", "zoom": 1.72, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInCubic"
|
||||
},
|
||||
{
|
||||
"durationMs": 3900,
|
||||
"from": { "anchor": "BottomRight", "zoom": 1.72, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "BottomLeft", "zoom": 1.55, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInOutSine"
|
||||
}
|
||||
],
|
||||
"lines": [
|
||||
{
|
||||
"speaker": "Narrator",
|
||||
"portrait": "resources/hero.png",
|
||||
"text": "The memory begins in silence.",
|
||||
"durationMs": 2200
|
||||
},
|
||||
{
|
||||
"speaker": "Narrator",
|
||||
"portrait": "resources/hero.png",
|
||||
"text": "Something is drawing your eyes across the whole scene.",
|
||||
"durationMs": 2800
|
||||
},
|
||||
{
|
||||
"speaker": "Ghost",
|
||||
"portrait": "resources/ghost_avatar.png",
|
||||
"text": "Do not look away.",
|
||||
"durationMs": 2400
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "test_cutscene_pan_02",
|
||||
"background": "resources/first_cutscene.png",
|
||||
"durationMs": 12000,
|
||||
"cameraTrack": [
|
||||
{
|
||||
"durationMs": 1200,
|
||||
"from": { "anchor": "Center", "zoom": 1.00, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "Center", "zoom": 1.00, "rotationDeg": 0.0 },
|
||||
"easing": "Linear"
|
||||
},
|
||||
{
|
||||
"durationMs": 2500,
|
||||
"from": { "anchor": "Center", "zoom": 1.00, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "TopLeft", "zoom": 1.55, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInOutSine"
|
||||
},
|
||||
{
|
||||
"durationMs": 2600,
|
||||
"from": { "anchor": "TopLeft", "zoom": 1.55, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "TopRight", "zoom": 1.55, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInOutSine"
|
||||
},
|
||||
{
|
||||
"durationMs": 1800,
|
||||
"from": { "anchor": "TopRight", "zoom": 1.55, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "BottomRight", "zoom": 1.72, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInCubic"
|
||||
},
|
||||
{
|
||||
"durationMs": 3900,
|
||||
"from": { "anchor": "BottomRight", "zoom": 1.72, "rotationDeg": 0.0 },
|
||||
"to": { "anchor": "BottomLeft", "zoom": 1.55, "rotationDeg": 0.0 },
|
||||
"easing": "EaseInOutSine"
|
||||
}
|
||||
],
|
||||
"lines": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -3,7 +3,7 @@
|
||||
{
|
||||
"key": "Аида Дженибековна",
|
||||
"ru": "Аида Дженибековна",
|
||||
"en": "Aida Dzhanybekovna"
|
||||
"en": "Aida Dzhenibekovna"
|
||||
},
|
||||
{
|
||||
"key": "Опаздывающие, заходите скорее и занимайте свои места! Лекция начинается!",
|
||||
@ -23,7 +23,7 @@
|
||||
{
|
||||
"key": "Этот мир описан в эпосе Манас как Кайып или Аль-Гайб, но некоторые ученые называют его миром теней.",
|
||||
"ru": "Этот мир описан в эпосе Манас как Кайып или Аль-Гайб, но некоторые ученые называют его миром теней.",
|
||||
"en": "This world is described in the Manas epic as Kayip or Al-Ghayb, but some scholars call it the dark lands."
|
||||
"en": "This world is described in the Manas epic as Kayip or Al-Ghayb, but some scholars call it the Darkland."
|
||||
},
|
||||
{
|
||||
"key": "В этом мире обитают феи, духи и джинны. Простым смертным в этот мир дорога закрыта.",
|
||||
@ -33,17 +33,17 @@
|
||||
{
|
||||
"key": "Время там течет по другому - за один день в теневом мире могут пройти годы жизни обычного мира.",
|
||||
"ru": "Время там течет по другому - за один день в теневом мире могут пройти годы жизни обычного мира.",
|
||||
"en": "Time flows differently there - in one day in the dark lands, years of life in the ordinary world can pass."
|
||||
"en": "Time flows differently there - in one day in the Darkland, years of life in the ordinary world can pass."
|
||||
},
|
||||
{
|
||||
"key": "Обычно, мир теней никак не пересекается с нашим миром живых людей.",
|
||||
"ru": "Обычно, мир теней никак не пересекается с нашим миром живых людей.",
|
||||
"en": "Usually, the world of dark lands does not intersect with our world of living people."
|
||||
"en": "Usually, the world of the Darkland does not intersect with our world of living people."
|
||||
},
|
||||
{
|
||||
"key": "Но в критические моменты для народа, обитатели теневого мира могут приходить в наш мир.",
|
||||
"ru": "Но в критические моменты для народа, обитатели теневого мира могут приходить в наш мир.",
|
||||
"en": "But in critical moments for the people, the inhabitants of the dark lands can come to our world."
|
||||
"en": "But in critical moments for the people, the inhabitants of the Darkland can come to our world."
|
||||
},
|
||||
{
|
||||
"key": "Совсем недавно закончилась пандемия, а сегодня мир захлестнули кровавые войны.",
|
||||
|
||||
@ -136,9 +136,9 @@
|
||||
"en": "Before going outside, I have to order a taxi to the university."
|
||||
},
|
||||
{
|
||||
"key": "Я заказал такси до универа, машина уже ждет!",
|
||||
"ru": "Я заказал такси до универа, машина уже ждет!",
|
||||
"en": "I ordered a taxi to the university, the car is already waiting!"
|
||||
"key": "Я заказал такси до универа, машина уже едет!",
|
||||
"ru": "Я заказал такси до универа, машина уже едет!",
|
||||
"en": "I ordered a taxi to the university, the car is already on its way!"
|
||||
},
|
||||
{
|
||||
"key": "Я уже заказал такси, машина уже ждет!",
|
||||
@ -261,9 +261,9 @@
|
||||
"en": "And where is her coursework now?"
|
||||
},
|
||||
{
|
||||
"key": "За зданием универа есть контейнер с кучей бумажного мусора и макулатурой.",
|
||||
"ru": "За зданием универа есть контейнер с кучей бумажного мусора и макулатурой.",
|
||||
"en": "Behind the university building there is a container with a pile of paper trash and waste."
|
||||
"key": "Возле здания универа лежит куча строительного мусора и макулатуры.",
|
||||
"ru": "Возле здания универа лежит куча строительного мусора и макулатуры.",
|
||||
"en": "There is a pile of construction waste and paper near the university building."
|
||||
},
|
||||
{
|
||||
"key": "Скорее всего, курсовая до сих пор лежит где-то там.",
|
||||
@ -303,7 +303,7 @@
|
||||
{
|
||||
"key": "А ведь у нас в этом году новая преподавательница, Аида Дженибековна!",
|
||||
"ru": "А ведь у нас в этом году новая преподавательница, Аида Дженибековна!",
|
||||
"en": "But we have a new teacher this year, Aida Dzhanybekovna!"
|
||||
"en": "But we have a new teacher this year, Aida Dzhenibekovna!"
|
||||
},
|
||||
{
|
||||
"key": "Она конечно не сахар, но если ты ходишь на пары и вовремя сдашь ей задание на модуль, то ты считай сдал экзамен.",
|
||||
@ -318,7 +318,7 @@
|
||||
{
|
||||
"key": "Так что Аида Дженибековна еще норм. Подойди к ней, возьми задание на модуль, и начни ходить на пары. Тогда ты сдашь экзамен успешно.",
|
||||
"ru": "Так что Аида Дженибековна еще норм. Подойди к ней, возьми задание на модуль, и начни ходить на пары. Тогда ты сдашь экзамен успешно.",
|
||||
"en": "So Aida Dzhanybekovna is still okay. Go to her, take the assignment for the module, and start going to class. Then you'll pass the exam successfully."
|
||||
"en": "So Aida Dzhenibekovna is still okay. Go to her, take the assignment for the module, and start going to class. Then you'll pass the exam successfully."
|
||||
},
|
||||
{
|
||||
"key": "Спасибо за информацию!",
|
||||
@ -348,7 +348,7 @@
|
||||
{
|
||||
"key": "Говорят, ей не очень нравится наша новая преподавательница по манасоведению, Аида Дженибековна.",
|
||||
"ru": "Говорят, ей не очень нравится наша новая преподавательница по манасоведению, Аида Дженибековна.",
|
||||
"en": "They say she doesn't really like our new Manas studies teacher, Aida Dzhanybekovna."
|
||||
"en": "They say she doesn't really like our new Manas studies teacher, Aida Dzhenibekovna."
|
||||
},
|
||||
{
|
||||
"key": "Привет Бекзат! Надеюсь ты нашел то что ищешь.",
|
||||
@ -456,9 +456,9 @@
|
||||
"en": "Before I leave the gate, I have to order a taxi to the dorm."
|
||||
},
|
||||
{
|
||||
"key": "Я заказал такси до общаги, машина уже ждет!",
|
||||
"ru": "Я заказал такси до общаги, машина уже ждет!",
|
||||
"en": "I ordered a taxi to the dorm, the car is already waiting!"
|
||||
"key": "Я заказал такси до общаги, машина уже едет!",
|
||||
"ru": "Я заказал такси до общаги, машина уже едет!",
|
||||
"en": "I ordered a taxi to the dorm, the car is already on its way!"
|
||||
},
|
||||
{
|
||||
"key": "Ого, пока я залипал в приложении, уже наступила ночь!",
|
||||
@ -478,7 +478,7 @@
|
||||
{
|
||||
"key": "Кажется, на этой машине в универ приезжает Аида Дженибековна.",
|
||||
"ru": "Кажется, на этой машине в универ приезжает Аида Дженибековна.",
|
||||
"en": "It seems that Aida Dzhanybekovna arrives at the university in this car."
|
||||
"en": "It seems that Aida Dzhenibekovna arrives at the university in this car."
|
||||
},
|
||||
{
|
||||
"key": "Это заклинание не работает днем.",
|
||||
@ -488,7 +488,7 @@
|
||||
{
|
||||
"key": "Чтобы перейти в теневой мир, мне нужно дождаться ночи.",
|
||||
"ru": "Чтобы перейти в теневой мир, мне нужно дождаться ночи.",
|
||||
"en": "To go into the dark lands, I need to wait until night."
|
||||
"en": "To go into the Darkland, I need to wait until night."
|
||||
},
|
||||
{
|
||||
"key": "Чтобы время пролетело быстро, я могу посидеть в телефоне и позалипать в короткие видео.",
|
||||
@ -498,7 +498,7 @@
|
||||
{
|
||||
"key": "У меня силы закончились и мне спать хочется. Достаточно теневого мира на сегодня, поехали в общагу.",
|
||||
"ru": "У меня силы закончились и мне спать хочется. Достаточно теневого мира на сегодня, поехали в общагу.",
|
||||
"en": "I'm exhausted and sleepy. Enough of the dark lands for today, let's go to the dorm."
|
||||
"en": "I'm exhausted and sleepy. Enough of the Darkland for today, let's go to the dorm."
|
||||
},
|
||||
{
|
||||
"key": "Ты куда собрался, Бекзат?",
|
||||
@ -658,7 +658,7 @@
|
||||
{
|
||||
"key": "Аида Дженибековна",
|
||||
"ru": "Аида Дженибековна",
|
||||
"en": "Aida Dzhanybekovna"
|
||||
"en": "Aida Dzhenibekovna"
|
||||
},
|
||||
{
|
||||
"key": "Бекзат, что тебе нужно?",
|
||||
@ -688,7 +688,7 @@
|
||||
{
|
||||
"key": "Аида Дженибековна",
|
||||
"ru": "Аида Дженибековна",
|
||||
"en": "Aida Dzhanybekovna"
|
||||
"en": "Aida Dzhenibekovna"
|
||||
},
|
||||
{
|
||||
"key": "Зачем тебе в учительскую?",
|
||||
@ -828,7 +828,7 @@
|
||||
{
|
||||
"key": "Извините, Аида Дженибековна, я могу пойти уже?",
|
||||
"ru": "Извините, Аида Дженибековна, я могу пойти уже?",
|
||||
"en": "Excuse me, Aida Dzhanybekovna, can I go now?"
|
||||
"en": "Excuse me, Aida Dzhenibekovna, can I go now?"
|
||||
},
|
||||
{
|
||||
"key": "Нет, Бекзат. Ты вломился в учительскую, и теперь хочешь просто так уйти? Не получится.",
|
||||
@ -898,7 +898,7 @@
|
||||
{
|
||||
"key": "Аида Дженибековна, вы помните Бегимай? Она вам курсовую хотела сдать.",
|
||||
"ru": "Аида Дженибековна, вы помните Бегимай? Она вам курсовую хотела сдать.",
|
||||
"en": "Aida Dzhanybekovna, do you remember Begimai? She wanted to submit her term paper to you."
|
||||
"en": "Aida Dzhenibekovna, do you remember Begimai? She wanted to submit her term paper to you."
|
||||
},
|
||||
{
|
||||
"key": "Да, она говорила что приносила курсовую, но у меня ее нигде нет.",
|
||||
@ -913,7 +913,7 @@
|
||||
{
|
||||
"key": "Бекзат, зачетка Бегимай у тебя. Отправляйся в теневой мир и покажи зачетку призраку Бегимай, чтобы она освободилась.",
|
||||
"ru": "Бекзат, зачетка Бегимай у тебя. Отправляйся в теневой мир и покажи зачетку призраку Бегимай, чтобы она освободилась.",
|
||||
"en": "Bekzat, you have Begimai's grade book. Go to the dark lands and show the grade book to Begimai's ghost so she can be released."
|
||||
"en": "Bekzat, you have Begimai's record book. Go to the Darkland and show the record book to Begimai's ghost so she can be released."
|
||||
},
|
||||
{
|
||||
"key": "Хорошо!",
|
||||
@ -923,12 +923,12 @@
|
||||
{
|
||||
"key": "Аида Дженибековна, здравствуйте!",
|
||||
"ru": "Аида Дженибековна, здравствуйте!",
|
||||
"en": "Aida Dzhanybekovna, hello!"
|
||||
"en": "Aida Dzhenibekovna, hello!"
|
||||
},
|
||||
{
|
||||
"key": "Я принес вам зачетку Бегимай и ее курсовую работу, посмотрите пожалуйста.",
|
||||
"ru": "Я принес вам зачетку Бегимай и ее курсовую работу, посмотрите пожалуйста.",
|
||||
"en": "I brought you Begimai's grade book and her coursework, please take a look."
|
||||
"en": "I brought you Begimai's record book and her coursework, please take a look."
|
||||
},
|
||||
{
|
||||
"key": "Хорошо, давай посмотрим.",
|
||||
@ -943,12 +943,12 @@
|
||||
{
|
||||
"key": "Вот держи зачетку с оценкой.",
|
||||
"ru": "Вот держи зачетку с оценкой.",
|
||||
"en": "Here, take the grade book with the grade."
|
||||
"en": "Here, take the record book with the grade."
|
||||
},
|
||||
{
|
||||
"key": "Теперь иди в теневой мир и покажи зачетку Бегимай. Расскажи ей, что она сдала курсовую работу.",
|
||||
"ru": "Теперь иди в теневой мир и покажи зачетку Бегимай. Расскажи ей, что она сдала курсовую работу.",
|
||||
"en": "Now go to the dark lands and show Begimai her grade book. Tell her she passed her coursework."
|
||||
"en": "Now go to the Darkland and show Begimai her record book. Tell her she passed her coursework."
|
||||
},
|
||||
{
|
||||
"key": "Мне стоит вернуть книгу на место, прежде чем уходить из библиотеки.",
|
||||
@ -958,7 +958,7 @@
|
||||
{
|
||||
"key": "Иначе Аида Дженибековна меня убъет.",
|
||||
"ru": "Иначе Аида Дженибековна меня убъет.",
|
||||
"en": "Otherwise Aida Dzhanybekovna will kill me."
|
||||
"en": "Otherwise Aida Dzhenibekovna will kill me."
|
||||
},
|
||||
{
|
||||
"key": "Куда я попал?",
|
||||
@ -1023,7 +1023,7 @@
|
||||
{
|
||||
"key": "Я уйду на покой только когда увиду оценку по курсовой в своей зачетке.",
|
||||
"ru": "Я уйду на покой только когда увиду оценку по курсовой в своей зачетке.",
|
||||
"en": "I will retire only when I see the grade for my coursework in my grade book."
|
||||
"en": "I will retire only when I see the grade for my coursework in my record book."
|
||||
},
|
||||
{
|
||||
"key": "А до тех пор, я буду появлятся здесь каждую ночь.",
|
||||
@ -1048,7 +1048,7 @@
|
||||
{
|
||||
"key": "Это твоя зачетка.",
|
||||
"ru": "Это твоя зачетка.",
|
||||
"en": "This is your grade book."
|
||||
"en": "This is your record book."
|
||||
},
|
||||
{
|
||||
"key": "Тебе поставили за курсовую максимальный балл!",
|
||||
@ -1143,17 +1143,17 @@
|
||||
{
|
||||
"key": "Тут лежат зачетные книжки студентов.",
|
||||
"ru": "Тут лежат зачетные книжки студентов.",
|
||||
"en": "Students' grade books are kept here."
|
||||
"en": "Students' record books are kept here."
|
||||
},
|
||||
{
|
||||
"key": "Здесь лежит зачетка Бегимай. Я пожалуй, возьму ее.",
|
||||
"ru": "Здесь лежит зачетка Бегимай. Я пожалуй, возьму ее.",
|
||||
"en": "Begimai's grade book is here. I think I'll take it."
|
||||
"en": "Begimai's record book is here. I think I'll take it."
|
||||
},
|
||||
{
|
||||
"key": "Мне еще рано возвращать зачетку Бегимай обратно в шкаф.",
|
||||
"ru": "Мне еще рано возвращать зачетку Бегимай обратно в шкаф.",
|
||||
"en": "It's too early for me to return Begimai's grade book back to the shelf."
|
||||
"en": "It's too early for me to return Begimai's record book back to the shelf."
|
||||
},
|
||||
{
|
||||
"key": "Чтобы заказать такси, я сначала должен выйти на улицу.",
|
||||
@ -1358,12 +1358,12 @@
|
||||
{
|
||||
"key": "Ко мне попала странная записка, где было написано заклинание. Я прочитал его, и попал в потусторонний мир.",
|
||||
"ru": "Ко мне попала странная записка, где было написано заклинание. Я прочитал его, и попал в потусторонний мир.",
|
||||
"en": "I received a strange note containing a spell. I read it and found myself in the dark lands."
|
||||
"en": "I received a strange note containing a spell. I read it and found myself in the Darkland."
|
||||
},
|
||||
{
|
||||
"key": "Ты что опять в свои игры переиграл? Какой потусторонний мир?",
|
||||
"ru": "Ты что опять в свои игры переиграл? Какой потусторонний мир?",
|
||||
"en": "Are you playing your video games too much? What dark lands?"
|
||||
"en": "Are you playing your video games too much? What Darkland?"
|
||||
},
|
||||
{
|
||||
"key": "Но это правда! Там все было по-другому, и я видел призраков...",
|
||||
@ -1378,7 +1378,7 @@
|
||||
{
|
||||
"key": "Аида Дженибековна увидела меня в учительской, и заставила писать эссе по этой тупой книге.",
|
||||
"ru": "Аида Дженибековна увидела меня в учительской, и заставила писать эссе по этой тупой книге.",
|
||||
"en": "Aida Dzhanybekovna saw me in the teachers' room and made me write an essay on this stupid book."
|
||||
"en": "Aida Dzhenibekovna saw me in the teachers' room and made me write an essay on this stupid book."
|
||||
},
|
||||
{
|
||||
"key": "Я писал, писал и уснул.",
|
||||
@ -1448,7 +1448,7 @@
|
||||
{
|
||||
"key": "Поэтому, с этого года у нас этот предмет ведет Аида Дженибековна.",
|
||||
"ru": "Поэтому, с этого года у нас этот предмет ведет Аида Дженибековна.",
|
||||
"en": "Therefore, starting this year, Aida Dzhanybekovna has been teaching this subject."
|
||||
"en": "Therefore, starting this year, Aida Dzhenibekovna has been teaching this subject."
|
||||
},
|
||||
{
|
||||
"key": "Ты не знаешь кого-нибудь, кто был знаком с Бегимай?",
|
||||
@ -1473,7 +1473,7 @@
|
||||
{
|
||||
"key": "Я лучше прочитаю заклинание, перейду в теневой мир и так выберусь наружу.",
|
||||
"ru": "Я лучше прочитаю заклинание, перейду в теневой мир и так выберусь наружу.",
|
||||
"en": "I'd rather cast a spell, go into the dark lands, and get out that way."
|
||||
"en": "I'd rather cast a spell, go into the Darkland, and get out that way."
|
||||
},
|
||||
{
|
||||
"key": "Я не буду беспокоить Айпери. Я могу выбраться из универа и без ее помощи.",
|
||||
@ -1588,12 +1588,12 @@
|
||||
{
|
||||
"key": "Я попал в теневой мир, чтобы выбраться из запертого кабинета.",
|
||||
"ru": "Я попал в теневой мир, чтобы выбраться из запертого кабинета.",
|
||||
"en": "I entered the dark lands to escape from the locked room."
|
||||
"en": "I entered the Darkland to escape from the locked room."
|
||||
},
|
||||
{
|
||||
"key": "Но по злой иронии, когда я вернулся из теневого мира, я снова оказался за запертой дверью.",
|
||||
"ru": "Но по злой иронии, когда я вернулся из теневого мира, я снова оказался за запертой дверью.",
|
||||
"en": "But by a cruel irony, when I returned from the dark lands, I found myself behind a locked door again."
|
||||
"en": "But by a cruel irony, when I returned from the Darkland, I found myself behind a locked door again."
|
||||
},
|
||||
{
|
||||
"key": "Хорошо, что уже утро. Надо написать Айпери, может она уже скоро приедет в универ?",
|
||||
@ -1623,7 +1623,7 @@
|
||||
{
|
||||
"key": "Здравствуйте Аида Дженибековна!",
|
||||
"ru": "Здравствуйте Аида Дженибековна!",
|
||||
"en": "Hello Aida Dzhanybekovna!"
|
||||
"en": "Hello Aida Dzhenibekovna!"
|
||||
},
|
||||
{
|
||||
"key": "Ну что Бекзат, эссе про Жусупа Мамая готово к сдаче?",
|
||||
@ -1683,12 +1683,12 @@
|
||||
{
|
||||
"key": "Это заклинание переместило тебя в мир теней. ",
|
||||
"ru": "Это заклинание переместило тебя в мир теней.",
|
||||
"en": "This spell transported you to the dark lands."
|
||||
"en": "This spell transported you to the Darkland."
|
||||
},
|
||||
{
|
||||
"key": "Этот мир предназначен для фей и джиннов. Обычные люди туда попасть не могут. Но у тебя это как-то получилось.",
|
||||
"ru": "Этот мир предназначен для фей и джиннов. Обычные люди туда попасть не могут. Но у тебя это как-то получилось.",
|
||||
"en": "These lands are meant for fairies and genies. Ordinary people can't get there. But somehow you made it."
|
||||
"en": "This land is meant for fairies and genies. Ordinary people can't get there. But somehow you made it."
|
||||
},
|
||||
{
|
||||
"key": "А вы откуда все это знаете?",
|
||||
@ -1723,12 +1723,12 @@
|
||||
{
|
||||
"key": "А на утро бывает так, что все зачетки в шкафу раскиданы как попало.",
|
||||
"ru": "А на утро бывает так, что все зачетки в шкафу раскиданы как попало.",
|
||||
"en": "And in the morning it happens that all the grade books in the closet are scattered all over the place."
|
||||
"en": "And in the morning it happens that all the record books in the closet are scattered all over the place."
|
||||
},
|
||||
{
|
||||
"key": "Призрак обитает где-то в теневом мире. Попади туда и наладь с ним диалог. Узнай, кто он и что ему нужно.",
|
||||
"ru": "Призрак обитает где-то в теневом мире. Попади туда и наладь с ним диалог. Узнай, кто он и что ему нужно.",
|
||||
"en": "The ghost dwells somewhere in the dark lands. Get there and establish a dialogue with him. Find out who he is and what he wants."
|
||||
"en": "The ghost dwells somewhere in the Darkland. Get there and establish a dialogue with him. Find out who he is and what he wants."
|
||||
},
|
||||
{
|
||||
"key": "Если ты успешно избавишься от призрака, я поставлю тебе максимальный балл за модуль.",
|
||||
@ -1753,7 +1753,7 @@
|
||||
{
|
||||
"key": "Обсудить теневой мир",
|
||||
"ru": "Обсудить теневой мир",
|
||||
"en": "Discuss the dark lands"
|
||||
"en": "Discuss the Darkland"
|
||||
},
|
||||
{
|
||||
"key": "Обсудить записку",
|
||||
@ -1763,12 +1763,12 @@
|
||||
{
|
||||
"key": "Что это вообще за теневой мир? Откуда он взялся?",
|
||||
"ru": "Что это вообще за теневой мир? Откуда он взялся?",
|
||||
"en": "What is this dark lands anyway? Where did it come from?"
|
||||
"en": "What is this Darkland anyway? Where did it come from?"
|
||||
},
|
||||
{
|
||||
"key": "Теневой мир это мир, в котором обитают феи, духи и джинны. Он существовал всегда.",
|
||||
"ru": "Теневой мир это мир, в котором обитают феи, духи и джинны. Он существовал всегда.",
|
||||
"en": "The Dark Lands is a world inhabited by fairies, spirits, and genies. It has always existed."
|
||||
"en": "The Darkland is a world inhabited by fairies, spirits, and genies. It has always existed."
|
||||
},
|
||||
{
|
||||
"key": "Обычные люди, не воители, туда не попадают обычно. Кроме тебя, тебе это как-то удалось.",
|
||||
@ -1783,22 +1783,22 @@
|
||||
{
|
||||
"key": "Время в теневом мире",
|
||||
"ru": "Время в теневом мире",
|
||||
"en": "Time in the dark lands"
|
||||
"en": "Time in the Darkland"
|
||||
},
|
||||
{
|
||||
"key": "Призраки в теневом мире",
|
||||
"ru": "Призраки в теневом мире",
|
||||
"en": "Ghosts in the dark lands"
|
||||
"en": "Ghosts in the Darkland"
|
||||
},
|
||||
{
|
||||
"key": "Двери в теневом мире",
|
||||
"ru": "Двери в теневом мире",
|
||||
"en": "Doors in the dark lands"
|
||||
"en": "Doors in the Darkland"
|
||||
},
|
||||
{
|
||||
"key": "Выход из теневого мира",
|
||||
"ru": "Выход из теневого мира",
|
||||
"en": "Exit from the dark lands"
|
||||
"en": "Exit from the Darkland"
|
||||
},
|
||||
{
|
||||
"key": "Достаточно",
|
||||
@ -1808,37 +1808,37 @@
|
||||
{
|
||||
"key": "Почему в теневом мире нет дверей?",
|
||||
"ru": "Почему в теневом мире нет дверей?",
|
||||
"en": "Why are there no doors in the dark lands?"
|
||||
"en": "Why are there no doors in the Darkland?"
|
||||
},
|
||||
{
|
||||
"key": "Я думаю, в мир теней проецируются только фундаментальные объекты, типа зданий, деревьев, рельефа.",
|
||||
"ru": "Я думаю, в мир теней проецируются только фундаментальные объекты, типа зданий, деревьев, рельефа.",
|
||||
"en": "I think that only fundamental objects, such as buildings, trees, and terrain, are projected into the dark lands."
|
||||
"en": "I think that only fundamental objects, such as buildings, trees, and terrain, are projected into the Darkland."
|
||||
},
|
||||
{
|
||||
"key": "Это происходит потому, что в теневом мире время течет сильно медленнее, чем в нашем мире.",
|
||||
"ru": "Это происходит потому, что в теневом мире время течет сильно медленнее, чем в нашем мире.",
|
||||
"en": "This happens because in the dark lands time flows much slower than in our world."
|
||||
"en": "This happens because in the Darkland time flows much slower than in our world."
|
||||
},
|
||||
{
|
||||
"key": "Двери у нас слишком часто открываются и закрываются, поэтому в теневом мире они \"размываются\" или попадают в суперпозицию.",
|
||||
"ru": "Двери у нас слишком часто открываются и закрываются, поэтому в теневом мире они \"размываются\" или попадают в суперпозицию.",
|
||||
"en": "Our doors open and close too often, so in the dark lands they become \"blurred\" or fall into some sort of superposition."
|
||||
"en": "Our doors open and close too often, so in the Darkland they become \"blurred\" or fall into some sort of superposition."
|
||||
},
|
||||
{
|
||||
"key": "Поэтому в мире теней ты можешь спокойно пройти через дверной проем. Но сквозь стены ты пройти не сможешь, они более плотные.",
|
||||
"ru": "Поэтому в мире теней ты можешь спокойно пройти через дверной проем. Но сквозь стены ты пройти не сможешь, они более плотные.",
|
||||
"en": "So, in the dark lands, you can easily pass through a doorway. But you won't be able to pass through walls; they're denser."
|
||||
"en": "So, in the Darkland, you can easily pass through a doorway. But you won't be able to pass through walls; they're denser."
|
||||
},
|
||||
{
|
||||
"key": "Откуда в теневом мире призраки?",
|
||||
"ru": "Откуда в теневом мире призраки?",
|
||||
"en": "Where do ghosts come from in the dark lands?"
|
||||
"en": "Where do ghosts come from in the Darkland?"
|
||||
},
|
||||
{
|
||||
"key": "Это их мир, и они там живут. Я думаю что увидев тебя, обитатели теневого мира тоже были шокированы.",
|
||||
"ru": "Это их мир, и они там живут. Я думаю что увидев тебя, обитатели теневого мира тоже были шокированы.",
|
||||
"en": "This is their world, and they live there. I think the inhabitants of the dark lands were also shocked when they saw you."
|
||||
"en": "This is their world, and they live there. I think the inhabitants of the Darkland were also shocked when they saw you."
|
||||
},
|
||||
{
|
||||
"key": "Но кое в чем ты прав. Здесь в универе, призраков раньше не было. Всякая чертовщина начала происходить совсем недавно.",
|
||||
@ -1863,12 +1863,12 @@
|
||||
{
|
||||
"key": "Каждый раз, когда я выпадаю из теневого мира, наступает утро. Хотя я там был всего несколько минут.",
|
||||
"ru": "Каждый раз, когда я выпадаю из теневого мира, наступает утро. Хотя я там был всего несколько минут.",
|
||||
"en": "Every time I emerge from the dark lands, morning comes, even though I was only there for a few minutes."
|
||||
"en": "Every time I emerge from the Darkland, morning comes, even though I was only there for a few minutes."
|
||||
},
|
||||
{
|
||||
"key": "Время в мире теней течет значительно медленнее, чем в нашем.",
|
||||
"ru": "Время в мире теней течет значительно медленнее, чем в нашем.",
|
||||
"en": "Time in the dark lands flows much slower than in ours."
|
||||
"en": "Time in the Darkland flows much slower than in ours."
|
||||
},
|
||||
{
|
||||
"key": "И похоже, что течение времени там нелинейное.",
|
||||
@ -1878,22 +1878,22 @@
|
||||
{
|
||||
"key": "Это объясняет, почему в теневом мире есть деревья и строения, но отсутствуют двери, автомобили, и прочее.",
|
||||
"ru": "Это объясняет, почему в теневом мире есть деревья и строения, но отсутствуют двери, автомобили, и прочее.",
|
||||
"en": "This explains why the dark lands has trees and buildings, but no doors, cars, etc."
|
||||
"en": "This explains why the Darkland has trees and buildings, but no doors, cars, etc."
|
||||
},
|
||||
{
|
||||
"key": "Объекты в нашем мире должны долго находится на одном месте, прежде чем их проекция появится в мире теней.",
|
||||
"ru": "Объекты в нашем мире должны долго находится на одном месте, прежде чем их проекция появится в мире теней.",
|
||||
"en": "Objects in our world must remain in one place for a long time before their projection appears in the dark lands."
|
||||
"en": "Objects in our world must remain in one place for a long time before their projection appears in the Darkland."
|
||||
},
|
||||
{
|
||||
"key": "Меня постоянно выкидывает из теневого мира. Как я могу там остаться подольше?",
|
||||
"ru": "Меня постоянно выкидывает из теневого мира. Как я могу там остаться подольше?",
|
||||
"en": "I'm constantly being thrown out of the dark lands. How can I stay there any longer?"
|
||||
"en": "I'm constantly being thrown out of the Darkland. How can I stay there any longer?"
|
||||
},
|
||||
{
|
||||
"key": "Если ты потеряешь сознание в теневом мире, то ты принудительно вернешься в наш мир.",
|
||||
"ru": "Если ты потеряешь сознание в теневом мире, то ты принудительно вернешься в наш мир.",
|
||||
"en": "If you lose consciousness in the dark lands, you will be forcibly returned to our world."
|
||||
"en": "If you lose consciousness in the Darkland, you will be forcibly returned to our world."
|
||||
},
|
||||
{
|
||||
"key": "Также избегай света луны, луна тоже может вернуть тебя в мир людей. Лучше вообще не выходи из помещения. ",
|
||||
@ -1903,17 +1903,17 @@
|
||||
{
|
||||
"key": "Если ты задержишься, и в человеческом мире настанет утро, тебя тоже выбросит из теневого мира.",
|
||||
"ru": "Если ты задержишься, и в человеческом мире настанет утро, тебя тоже выбросит из теневого мира.",
|
||||
"en": "If you stay too long and morning comes in the human world, you will be thrown out of the dark lands too."
|
||||
"en": "If you stay too long and morning comes in the human world, you will be thrown out of the Darkland too."
|
||||
},
|
||||
{
|
||||
"key": "Но ты не беспокойся. Даже если тебя выбросит из теневого мира, ты всегда сможешь повторить свою попытку на следующую ночь.",
|
||||
"ru": "Но ты не беспокойся. Даже если тебя выбросит из теневого мира, ты всегда сможешь повторить свою попытку на следующую ночь.",
|
||||
"en": "But don't worry. Even if you're thrown out of the dark lands, you can always try again the next night."
|
||||
"en": "But don't worry. Even if you're thrown out of the Darkland, you can always try again the next night."
|
||||
},
|
||||
{
|
||||
"key": "У тебя есть еще вопросы про теневой мир?",
|
||||
"ru": "У тебя есть еще вопросы про теневой мир?",
|
||||
"en": "Do you have any more questions about the dark lands?"
|
||||
"en": "Do you have any more questions about the Darkland?"
|
||||
},
|
||||
{
|
||||
"key": "Ладно, я узнал достаточно.",
|
||||
@ -1938,7 +1938,7 @@
|
||||
{
|
||||
"key": "Когда я узнала, что в университете начались паранормальные явления, я сразу поняла что это призрак в теневом мире.",
|
||||
"ru": "Когда я узнала, что в университете начались паранормальные явления, я сразу поняла что это призрак в теневом мире.",
|
||||
"en": "When I learned that paranormal phenomena had begun at the university, I immediately realized that it was a ghost in the dark lands."
|
||||
"en": "When I learned that paranormal phenomena had begun at the university, I immediately realized that it was a ghost in the Darkland."
|
||||
},
|
||||
{
|
||||
"key": "Я знаю заклинание, которое тебе дали. У этого заклинания есть еще одно условие - оно сработает только на людей, которые чисты сердцем.",
|
||||
@ -1953,12 +1953,12 @@
|
||||
{
|
||||
"key": "Тогда я предположила, что Айпери уж точно сможет прочитать заклинание и попасть в теневой мир.",
|
||||
"ru": "Тогда я предположила, что Айпери уж точно сможет прочитать заклинание и попасть в теневой мир.",
|
||||
"en": "Then I assumed that Aiperi would definitely be able to cast the spell and enter the dark lands."
|
||||
"en": "Then I assumed that Aiperi would definitely be able to cast the spell and enter the Darkland."
|
||||
},
|
||||
{
|
||||
"key": "Как раз поэтому я хотела вернуть нож ей лично. И заодно отправить ее в теневой мир.",
|
||||
"ru": "Как раз поэтому я хотела вернуть нож ей лично. И заодно отправить ее в теневой мир.",
|
||||
"en": "That's exactly why I wanted to return the knife to her personally. And at the same time, ask her to go to the dark lands."
|
||||
"en": "That's exactly why I wanted to return the knife to her personally. And at the same time, ask her to go to the Darkland."
|
||||
},
|
||||
{
|
||||
"key": "Но ты смешал все мои планы. Сначала ты забрал нож, а потом кто-то подсунул тебе записку.",
|
||||
@ -2068,7 +2068,7 @@
|
||||
{
|
||||
"key": "Переходи в теневой мир, а затем иди в лекционный зал.",
|
||||
"ru": "Переходи в теневой мир, а затем иди в лекционный зал.",
|
||||
"en": "Go to the dark lands and then go to the lecture hall."
|
||||
"en": "Go to the Darkland and then go to the lecture hall."
|
||||
},
|
||||
{
|
||||
"key": "Постарайся поговорить с призраком, и узнать, что ему нужно.",
|
||||
@ -2093,7 +2093,7 @@
|
||||
{
|
||||
"key": "Иди к шкафу в учительской. Среди зачетных книжек найти зачетку Бегимай и принеси мне. Я поставлю ей оценку за курсовую работу.",
|
||||
"ru": "Иди к шкафу в учительской. Среди зачетных книжек найти зачетку Бегимай и принеси мне. Я поставлю ей оценку за курсовую работу.",
|
||||
"en": "Go to the cabinet in the teachers' room. Find Begimai's grade book among the grade books and bring it to me. I'll give her a grade for her coursework."
|
||||
"en": "Go to the cabinet in the teachers' room. Find Begimai's record book among the record books and bring it to me. I'll give her a grade for her coursework."
|
||||
},
|
||||
{
|
||||
"key": "Ты уже нашел курсовую работу Бегимай?",
|
||||
@ -2153,7 +2153,7 @@
|
||||
{
|
||||
"key": "Теперь поищи в шкафу зачетку Бегимай, и принеси мне, я выставлю ей оценку.",
|
||||
"ru": "Теперь поищи в шкафу зачетку Бегимай, и принеси мне, я выставлю ей оценку.",
|
||||
"en": "Now look in the cabinet for Begimai's grade book and bring it to me, I'll give her a grade."
|
||||
"en": "Now look in the cabinet for Begimai's record book and bring it to me, I'll give her a grade."
|
||||
},
|
||||
{
|
||||
"key": "Еще нет.",
|
||||
@ -2173,7 +2173,7 @@
|
||||
{
|
||||
"key": "Но если я возьму кусочек, Аида Дженибековна меня убьет.",
|
||||
"ru": "Но если я возьму кусочек, Аида Дженибековна меня убьет.",
|
||||
"en": "But if I take a piece, Aida Dzhanybekovna will kill me."
|
||||
"en": "But if I take a piece, Aida Dzhenibekovna will kill me."
|
||||
},
|
||||
{
|
||||
"key": "Здесь лежат книги по юриспруденции и праву.",
|
||||
@ -2183,12 +2183,12 @@
|
||||
{
|
||||
"key": "Бекзат, помнишь мы скидывались на торт для Аиды Дженибековной? Я тогда еще приносила скатерть, тарелки и серебряный нож для торта. И я до сих пор не получила назад ничего.",
|
||||
"ru": "Бекзат, помнишь мы скидывались на торт для Аиды Дженибековной? Я тогда еще приносила скатерть, тарелки и серебряный нож для торта. И я до сих пор не получила назад ничего.",
|
||||
"en": "Bekzat, remember how we chipped in for a cake for Aida Dzhanybekovna? I even brought a tablecloth, plates, and a silver cake knife. And I still haven't gotten anything back."
|
||||
"en": "Bekzat, remember how we chipped in for a cake for Aida Dzhenibekovna? I even brought a tablecloth, plates, and a silver cake knife. And I still haven't gotten anything back."
|
||||
},
|
||||
{
|
||||
"key": "Помнишь мы скидывались на торт для Аиды Дженибековной? Я тогда еще приносила скатерть, тарелки и серебряный нож для торта. И я до сих пор не получила назад ничего.",
|
||||
"ru": "Помнишь мы скидывались на торт для Аиды Дженибековной? Я тогда еще приносила скатерть, тарелки и серебряный нож для торта. И я до сих пор не получила назад ничего.",
|
||||
"en": "Remember when we chipped in for a cake for Aida Dzhanybekovna? I even brought a tablecloth, plates, and a silver cake knife. And I still haven't gotten anything back."
|
||||
"en": "Remember when we chipped in for a cake for Aida Dzhenibekovna? I even brought a tablecloth, plates, and a silver cake knife. And I still haven't gotten anything back."
|
||||
},
|
||||
{
|
||||
"key": "А во вторых, мне как-то не хочется попадаться на глаза Аиде.",
|
||||
@ -2198,7 +2198,7 @@
|
||||
{
|
||||
"key": "Да... Только не говори Аиде Дженибековной что я здесь.",
|
||||
"ru": "Да... Только не говори Аиде Дженибековной что я здесь.",
|
||||
"en": "Yes... Just don't tell Aida Dzhanybekovna that I'm here."
|
||||
"en": "Yes... Just don't tell Aida Dzhenibekovna that I'm here."
|
||||
},
|
||||
{
|
||||
"key": "Постарайся только Аиде Дженибековной особо на глаза не попадаться. ",
|
||||
@ -2233,7 +2233,7 @@
|
||||
{
|
||||
"key": "Я уйду на покой только когда увижу оценку по курсовой в своей зачетке.",
|
||||
"ru": "Я уйду на покой только когда увижу оценку по курсовой в своей зачетке.",
|
||||
"en": "I will rest in peace only when I see the grade for my coursework in my grade book."
|
||||
"en": "I will rest in peace only when I see the grade for my coursework in my record book."
|
||||
},
|
||||
{
|
||||
"key": "А до тех пор, я буду появляться здесь каждую ночь.",
|
||||
@ -2248,17 +2248,67 @@
|
||||
{
|
||||
"key": "Аида Дженибековна увидела меня в учительской, и заставила писать эссе по этой тупой книге.",
|
||||
"ru": "Аида Дженибековна увидела меня в учительской, и заставила писать эссе по этой тупой книге.",
|
||||
"en": "Aida Dzhanybekovna saw me in the teachers' room and made me write an essay on this stupid book."
|
||||
"en": "Aida Dzhenibekovna saw me in the teachers' room and made me write an essay on this stupid book."
|
||||
},
|
||||
{
|
||||
"key": "Прошу прощения Аида Дженибековна, я правда старался, но у меня возникли обстоятельства непреодолимой силы.",
|
||||
"ru": "Прошу прощения Аида Дженибековна, я правда старался, но у меня возникли обстоятельства непреодолимой силы.",
|
||||
"en": "I apologize, Aida Dzhanybekovna, I really tried, but I encountered force majeure circumstances."
|
||||
"en": "I apologize, Aida Dzhenibekovna, I really tried, but I encountered force majeure circumstances."
|
||||
},
|
||||
{
|
||||
"key": "Бекзат, я сейчас занята, не мешай мне!",
|
||||
"ru": "Бекзат, я сейчас занята, не мешай мне!",
|
||||
"en": "Bekzat, I'm busy now, don't disturb me!"
|
||||
},
|
||||
{
|
||||
"key": "Почему ты сама не можешь забрать нож у Аиды?",
|
||||
"ru": "Почему ты сама не можешь забрать нож у Аиды?",
|
||||
"en": "Why can't you take the knife from Aida yourself?"
|
||||
},
|
||||
{
|
||||
"key": "Она опять будет скафнить.",
|
||||
"ru": "Она опять будет скафнить.",
|
||||
"en": "She will annoy me again."
|
||||
},
|
||||
{
|
||||
"key": "А может быть даже даст мне какое-нибудь сложное задание.",
|
||||
"ru": "А может быть даже даст мне какое-нибудь сложное задание.",
|
||||
"en": "And maybe she will even give me some difficult assignment."
|
||||
},
|
||||
{
|
||||
"key": "Я уверена, она меня ищет. Она хочет мне какое-то задание дать.",
|
||||
"ru": "Я уверена, она меня ищет. Она хочет мне какое-то задание дать.",
|
||||
"en": "I'm sure she's looking for me. She wants to give me some kind of assignment."
|
||||
},
|
||||
{
|
||||
"key": "Пока ты не принесешь мне нож из учительской, никуда я тебя не выпущу. Ошо!",
|
||||
"ru": "Пока ты не принесешь мне нож из учительской, никуда я тебя не выпущу. Ошо!",
|
||||
"en": "Until you bring me a knife from the teachers' room, I won't let you go anywhere. Osho!"
|
||||
},
|
||||
{
|
||||
"key": "Я слышала она не смогла сдать курсовую по манасоведению.",
|
||||
"ru": "Я слышала она не смогла сдать курсовую по манасоведению.",
|
||||
"en": "I heard she couldn't pass her coursework on Manas studies."
|
||||
},
|
||||
{
|
||||
"key": "Она прыгнула с окна и разбилась насмерть деп.",
|
||||
"ru": "Она прыгнула с окна и разбилась насмерть деп.",
|
||||
"en": "She jumped from the window and fell to her death, dep."
|
||||
},
|
||||
{
|
||||
"key": "Да она надоела, все время скафнит.",
|
||||
"ru": "Да она надоела, все время скафнит.",
|
||||
"en": "Yes, she's annoying, she's always nagging."
|
||||
},
|
||||
{
|
||||
"key": "Если я ее встречу, она на 100% даст мне какое-нибудь сложное задание.",
|
||||
"ru": "Если я ее встречу, она на 100% даст мне какое-нибудь сложное задание.",
|
||||
"en": "If I meet her, she will 100% give me some difficult task."
|
||||
},
|
||||
{
|
||||
"key": "Так что жду тебя в универе! Не вздумай прогулять! Ошо!",
|
||||
"ru": "Так что жду тебя в универе! Не вздумай прогулять! Ошо!",
|
||||
"en": "So I'm waiting for you at the university! Don't even think about skipping! Osho!"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -134,7 +134,7 @@
|
||||
"type": "Line",
|
||||
"speaker": "Бекзат",
|
||||
"portrait": "resources/dialogue/portrait_hero_neutral.png",
|
||||
"text": "Я заказал такси до общаги, машина уже ждет!",
|
||||
"text": "Я заказал такси до общаги, машина уже едет!",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
@ -334,7 +334,7 @@
|
||||
"type": "Line",
|
||||
"speaker": "Бекзат",
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Почему ты сама не можешь забрать?",
|
||||
"text": "Почему ты сама не можешь забрать нож у Аиды?",
|
||||
"next": "line_9",
|
||||
"chatBubble": "out"
|
||||
},
|
||||
@ -343,7 +343,16 @@
|
||||
"type": "Line",
|
||||
"speaker": "Айпери",
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Ты же знаешь, если я встречу Аиду, она 100% даст мне какое-нибудь сложное задание.",
|
||||
"text": "Она опять будет скафнить.",
|
||||
"next": "line_12",
|
||||
"chatBubble": "in"
|
||||
},
|
||||
{
|
||||
"id": "line_12",
|
||||
"type": "Line",
|
||||
"speaker": "Айпери",
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "А может быть даже даст мне какое-нибудь сложное задание.",
|
||||
"next": "line_10",
|
||||
"chatBubble": "in"
|
||||
},
|
||||
@ -361,7 +370,7 @@
|
||||
"type": "Line",
|
||||
"speaker": "Айпери",
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Так что жду тебя в универе! Не вздумай прогулять!",
|
||||
"text": "Так что жду тебя в универе! Не вздумай прогулять! Ошо!",
|
||||
"next": "setflag_1",
|
||||
"chatBubble": "in",
|
||||
"questUnlock": "aiperi_knife"
|
||||
@ -403,6 +412,70 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "dialog_chat_aiperi003",
|
||||
"start": "line_1",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "line_1",
|
||||
"type": "Line",
|
||||
"speaker": "Бекзат",
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Айпери ты куда убежала?",
|
||||
"next": "line_2",
|
||||
"chatBubble": "out"
|
||||
},
|
||||
{
|
||||
"id": "line_2",
|
||||
"type": "Line",
|
||||
"speaker": "Айпери",
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Ты достал уже, я не могу тебя ждать вечно! Возишься как сонная муха.",
|
||||
"next": "line_3",
|
||||
"chatBubble": "in"
|
||||
},
|
||||
{
|
||||
"id": "line_3",
|
||||
"type": "Line",
|
||||
"speaker": "Айпери",
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "У меня нет времени ждать тебя, мне уже пора на курсы ехать.",
|
||||
"next": "line_4",
|
||||
"chatBubble": "in"
|
||||
},
|
||||
{
|
||||
"id": "line_4",
|
||||
"type": "Line",
|
||||
"speaker": "Бекзат",
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Так когда я тебе нож верну?",
|
||||
"next": "line_5",
|
||||
"chatBubble": "out"
|
||||
},
|
||||
{
|
||||
"id": "line_5",
|
||||
"type": "Line",
|
||||
"speaker": "Айпери",
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Приходи завтра в универ! Я каждый день в унике с раннего утра.",
|
||||
"next": "line_6",
|
||||
"chatBubble": "in"
|
||||
},
|
||||
{
|
||||
"id": "line_6",
|
||||
"type": "Line",
|
||||
"speaker": "Бекзат",
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Хорошо, встретимся завтра.",
|
||||
"next": "end_1",
|
||||
"chatBubble": "out"
|
||||
},
|
||||
{
|
||||
"id": "end_1",
|
||||
"type": "End"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "dialog_car001",
|
||||
"start": "line_1",
|
||||
@ -220,7 +220,15 @@
|
||||
"type": "Line",
|
||||
"speaker": "Айпери",
|
||||
"portrait": "resources/dialogue/portrait_aiperi.png",
|
||||
"text": "У меня есть ощущение что если я ее встречу, она даст мне какое-то очень сложное задание.",
|
||||
"text": "Она опять будет скафнить.",
|
||||
"next": "line_29"
|
||||
},
|
||||
{
|
||||
"id": "line_29",
|
||||
"type": "Line",
|
||||
"speaker": "Айпери",
|
||||
"portrait": "resources/dialogue/portrait_aiperi.png",
|
||||
"text": "А может быть даже даст мне какое-нибудь сложное задание.",
|
||||
"next": "line_16"
|
||||
},
|
||||
{
|
||||
@ -292,7 +300,7 @@
|
||||
"type": "Line",
|
||||
"speaker": "Айпери",
|
||||
"portrait": "resources/dialogue/portrait_aiperi.png",
|
||||
"text": "Она меня ищет, я уверена, она хочет мне какое-то задание дать.",
|
||||
"text": "Я уверена, она меня ищет. Она хочет мне какое-то задание дать.",
|
||||
"next": "line_26"
|
||||
},
|
||||
{
|
||||
@ -338,7 +346,7 @@
|
||||
"type": "Line",
|
||||
"speaker": "Айпери",
|
||||
"portrait": "resources/dialogue/portrait_aiperi.png",
|
||||
"text": "Пока ты не принесешь мне нож из учительской, никуда я тебя не выпущу.",
|
||||
"text": "Пока ты не принесешь мне нож из учительской, никуда я тебя не выпущу. Ошо!",
|
||||
"next": "end_1"
|
||||
},
|
||||
{
|
||||
@ -2385,7 +2393,15 @@
|
||||
"type": "Line",
|
||||
"speaker": "Айпери",
|
||||
"portrait": "resources/dialogue/portrait_aiperi.png",
|
||||
"text": "Я слышала она не смогла сдать курсовую по манасоведению, прыгнула с окна и разбилась насмерть.",
|
||||
"text": "Я слышала она не смогла сдать курсовую по манасоведению.",
|
||||
"next": "line_34"
|
||||
},
|
||||
{
|
||||
"id": "line_34",
|
||||
"type": "Line",
|
||||
"speaker": "Айпери",
|
||||
"portrait": "resources/dialogue/portrait_aiperi.png",
|
||||
"text": "Она прыгнула с окна и разбилась насмерть деп.",
|
||||
"next": "line_21"
|
||||
},
|
||||
{
|
||||
@ -2571,7 +2587,7 @@
|
||||
"type": "Line",
|
||||
"speaker": "Бекзат",
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Почему ты сама не можешь забрать?",
|
||||
"text": "Почему ты сама не можешь забрать нож у Аиды?",
|
||||
"next": "line_9",
|
||||
"chatBubble": "out"
|
||||
},
|
||||
@ -2580,7 +2596,16 @@
|
||||
"type": "Line",
|
||||
"speaker": "Айпери",
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Ты же знаешь, если я встречу Аиду, она 100% даст мне какое-нибудь сложное задание.",
|
||||
"text": "Да она надоела, все время скафнит.",
|
||||
"next": "line_12",
|
||||
"chatBubble": "in"
|
||||
},
|
||||
{
|
||||
"id": "line_12",
|
||||
"type": "Line",
|
||||
"speaker": "Айпери",
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Если я ее встречу, она на 100% даст мне какое-нибудь сложное задание.",
|
||||
"next": "line_10",
|
||||
"chatBubble": "in"
|
||||
},
|
||||
@ -2598,7 +2623,7 @@
|
||||
"type": "Line",
|
||||
"speaker": "Айпери",
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Так что жду тебя в универе! Не вздумай прогулять!",
|
||||
"text": "Так что жду тебя в универе! Не вздумай прогулять! Ошо!",
|
||||
"next": "setflag_1",
|
||||
"chatBubble": "in",
|
||||
"questUnlock": "aiperi_knife"
|
||||
Binary file not shown.
Binary file not shown.
20
resources/shaders/default_shadow_web.vertex
Normal file
20
resources/shaders/default_shadow_web.vertex
Normal file
@ -0,0 +1,20 @@
|
||||
precision highp float;
|
||||
attribute vec3 vPosition;
|
||||
attribute vec2 vTexCoord;
|
||||
attribute vec3 vNormal;
|
||||
|
||||
varying vec2 texCoord;
|
||||
varying vec4 fragPosLightSpace;
|
||||
varying vec3 fragNormal;
|
||||
|
||||
uniform mat4 ProjectionModelViewMatrix;
|
||||
uniform mat4 ModelViewMatrix;
|
||||
uniform mat4 uLightFromCamera;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = ProjectionModelViewMatrix * vec4(vPosition, 1.0);
|
||||
texCoord = vTexCoord;
|
||||
fragPosLightSpace = uLightFromCamera * ModelViewMatrix * vec4(vPosition, 1.0);
|
||||
fragNormal = mat3(ModelViewMatrix) * vNormal;
|
||||
}
|
||||
23
resources/shaders/fog_shadow_web.vertex
Normal file
23
resources/shaders/fog_shadow_web.vertex
Normal file
@ -0,0 +1,23 @@
|
||||
attribute vec3 vPosition;
|
||||
attribute vec2 vTexCoord;
|
||||
attribute vec3 vNormal;
|
||||
|
||||
varying vec2 texCoord;
|
||||
varying vec4 fragPosLightSpace;
|
||||
varying vec3 fragNormal;
|
||||
varying float fogDistance;
|
||||
|
||||
uniform mat4 ProjectionModelViewMatrix;
|
||||
uniform mat4 ModelViewMatrix;
|
||||
uniform mat4 uLightFromCamera;
|
||||
uniform vec3 uPlayerEyePos;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 eyePos = ModelViewMatrix * vec4(vPosition, 1.0);
|
||||
fogDistance = length(eyePos.xyz - uPlayerEyePos);
|
||||
gl_Position = ProjectionModelViewMatrix * vec4(vPosition, 1.0);
|
||||
texCoord = vTexCoord;
|
||||
fragPosLightSpace = uLightFromCamera * eyePos;
|
||||
fragNormal = mat3(ModelViewMatrix) * vNormal;
|
||||
}
|
||||
69
resources/shaders/fog_skinning_shadow_web.vertex
Normal file
69
resources/shaders/fog_skinning_shadow_web.vertex
Normal file
@ -0,0 +1,69 @@
|
||||
attribute vec3 vPosition;
|
||||
attribute vec2 vTexCoord;
|
||||
attribute vec3 vNormal;
|
||||
attribute vec4 aBoneIndices0;
|
||||
attribute vec2 aBoneIndices1;
|
||||
attribute vec4 aBoneWeights0;
|
||||
attribute vec2 aBoneWeights1;
|
||||
|
||||
varying vec2 texCoord;
|
||||
varying vec4 fragPosLightSpace;
|
||||
varying vec3 fragNormal;
|
||||
varying float fogDistance;
|
||||
|
||||
uniform mat4 ProjectionModelViewMatrix;
|
||||
uniform mat4 ModelViewMatrix;
|
||||
uniform mat4 uLightFromCamera;
|
||||
uniform mat4 uBoneMatrices[58];
|
||||
uniform vec3 uPlayerEyePos;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 skinnedPos = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec3 skinnedNormal = vec3(0.0, 0.0, 0.0);
|
||||
vec4 originalPos = vec4(vPosition, 1.0);
|
||||
float totalWeight = 0.0;
|
||||
|
||||
if (aBoneWeights0.x > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices0.x)] * originalPos * aBoneWeights0.x;
|
||||
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.x)]) * vNormal * aBoneWeights0.x;
|
||||
totalWeight += aBoneWeights0.x;
|
||||
}
|
||||
if (aBoneWeights0.y > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices0.y)] * originalPos * aBoneWeights0.y;
|
||||
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.y)]) * vNormal * aBoneWeights0.y;
|
||||
totalWeight += aBoneWeights0.y;
|
||||
}
|
||||
if (aBoneWeights0.z > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices0.z)] * originalPos * aBoneWeights0.z;
|
||||
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.z)]) * vNormal * aBoneWeights0.z;
|
||||
totalWeight += aBoneWeights0.z;
|
||||
}
|
||||
if (aBoneWeights0.w > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices0.w)] * originalPos * aBoneWeights0.w;
|
||||
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.w)]) * vNormal * aBoneWeights0.w;
|
||||
totalWeight += aBoneWeights0.w;
|
||||
}
|
||||
if (aBoneWeights1.x > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices1.x)] * originalPos * aBoneWeights1.x;
|
||||
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices1.x)]) * vNormal * aBoneWeights1.x;
|
||||
totalWeight += aBoneWeights1.x;
|
||||
}
|
||||
if (aBoneWeights1.y > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices1.y)] * originalPos * aBoneWeights1.y;
|
||||
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices1.y)]) * vNormal * aBoneWeights1.y;
|
||||
totalWeight += aBoneWeights1.y;
|
||||
}
|
||||
|
||||
if (totalWeight < 0.001) {
|
||||
skinnedPos = originalPos;
|
||||
skinnedNormal = vNormal;
|
||||
}
|
||||
|
||||
vec4 eyePos = ModelViewMatrix * skinnedPos;
|
||||
fogDistance = length(eyePos.xyz - uPlayerEyePos);
|
||||
gl_Position = ProjectionModelViewMatrix * skinnedPos;
|
||||
texCoord = vTexCoord;
|
||||
fragPosLightSpace = uLightFromCamera * eyePos;
|
||||
fragNormal = mat3(ModelViewMatrix) * skinnedNormal;
|
||||
}
|
||||
55
resources/shaders/fog_skinning_web.vertex
Normal file
55
resources/shaders/fog_skinning_web.vertex
Normal file
@ -0,0 +1,55 @@
|
||||
attribute vec3 vPosition;
|
||||
attribute vec2 vTexCoord;
|
||||
attribute vec4 aBoneIndices0;
|
||||
attribute vec2 aBoneIndices1;
|
||||
attribute vec4 aBoneWeights0;
|
||||
attribute vec2 aBoneWeights1;
|
||||
|
||||
varying vec2 texCoord;
|
||||
varying float fogDistance;
|
||||
|
||||
uniform mat4 ProjectionModelViewMatrix;
|
||||
uniform mat4 ModelViewMatrix;
|
||||
uniform mat4 uBoneMatrices[58];
|
||||
uniform vec3 uPlayerEyePos;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 skinnedPos = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec4 originalPos = vec4(vPosition, 1.0);
|
||||
float totalWeight = 0.0;
|
||||
|
||||
if (aBoneWeights0.x > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices0.x)] * originalPos * aBoneWeights0.x;
|
||||
totalWeight += aBoneWeights0.x;
|
||||
}
|
||||
if (aBoneWeights0.y > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices0.y)] * originalPos * aBoneWeights0.y;
|
||||
totalWeight += aBoneWeights0.y;
|
||||
}
|
||||
if (aBoneWeights0.z > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices0.z)] * originalPos * aBoneWeights0.z;
|
||||
totalWeight += aBoneWeights0.z;
|
||||
}
|
||||
if (aBoneWeights0.w > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices0.w)] * originalPos * aBoneWeights0.w;
|
||||
totalWeight += aBoneWeights0.w;
|
||||
}
|
||||
if (aBoneWeights1.x > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices1.x)] * originalPos * aBoneWeights1.x;
|
||||
totalWeight += aBoneWeights1.x;
|
||||
}
|
||||
if (aBoneWeights1.y > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices1.y)] * originalPos * aBoneWeights1.y;
|
||||
totalWeight += aBoneWeights1.y;
|
||||
}
|
||||
|
||||
if (totalWeight < 0.001) {
|
||||
skinnedPos = originalPos;
|
||||
}
|
||||
|
||||
vec4 eyePos = ModelViewMatrix * skinnedPos;
|
||||
fogDistance = length(eyePos.xyz - uPlayerEyePos);
|
||||
gl_Position = ProjectionModelViewMatrix * skinnedPos;
|
||||
texCoord = vTexCoord;
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
precision mediump float;
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D Texture;
|
||||
uniform sampler2D uShadowMap;
|
||||
|
||||
28
resources/shaders/night_fog_shadow_web.vertex
Normal file
28
resources/shaders/night_fog_shadow_web.vertex
Normal file
@ -0,0 +1,28 @@
|
||||
precision highp float;
|
||||
attribute vec3 vPosition;
|
||||
attribute vec2 vTexCoord;
|
||||
attribute vec3 vNormal;
|
||||
|
||||
varying vec2 texCoord;
|
||||
varying vec4 fragPosLightSpace;
|
||||
varying vec3 fragNormal;
|
||||
varying float fogDistance;
|
||||
varying vec3 fragViewPos;
|
||||
varying vec2 fragWorldXZ;
|
||||
|
||||
uniform mat4 ProjectionModelViewMatrix;
|
||||
uniform mat4 ModelViewMatrix;
|
||||
uniform mat4 uLightFromCamera;
|
||||
uniform vec3 uPlayerEyePos;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 eyePos = ModelViewMatrix * vec4(vPosition, 1.0);
|
||||
fogDistance = length(eyePos.xyz - uPlayerEyePos);
|
||||
gl_Position = ProjectionModelViewMatrix * vec4(vPosition, 1.0);
|
||||
texCoord = vTexCoord;
|
||||
fragViewPos = eyePos.xyz;
|
||||
fragNormal = mat3(ModelViewMatrix) * vNormal;
|
||||
fragPosLightSpace = uLightFromCamera * eyePos;
|
||||
fragWorldXZ = vPosition.xz;
|
||||
}
|
||||
74
resources/shaders/night_fog_skinning_shadow_web.vertex
Normal file
74
resources/shaders/night_fog_skinning_shadow_web.vertex
Normal file
@ -0,0 +1,74 @@
|
||||
attribute vec3 vPosition;
|
||||
attribute vec2 vTexCoord;
|
||||
attribute vec3 vNormal;
|
||||
attribute vec4 aBoneIndices0;
|
||||
attribute vec2 aBoneIndices1;
|
||||
attribute vec4 aBoneWeights0;
|
||||
attribute vec2 aBoneWeights1;
|
||||
|
||||
varying vec2 texCoord;
|
||||
varying vec4 fragPosLightSpace;
|
||||
varying vec3 fragNormal;
|
||||
varying float fogDistance;
|
||||
varying vec3 fragViewPos;
|
||||
varying vec2 fragWorldXZ;
|
||||
|
||||
uniform mat4 ProjectionModelViewMatrix;
|
||||
uniform mat4 ModelViewMatrix;
|
||||
uniform mat4 uLightFromCamera;
|
||||
uniform mat4 uViewInverse;
|
||||
uniform mat4 uBoneMatrices[58];
|
||||
uniform vec3 uPlayerEyePos;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 skinnedPos = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec3 skinnedNormal = vec3(0.0, 0.0, 0.0);
|
||||
vec4 originalPos = vec4(vPosition, 1.0);
|
||||
float totalWeight = 0.0;
|
||||
|
||||
if (aBoneWeights0.x > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices0.x)] * originalPos * aBoneWeights0.x;
|
||||
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.x)]) * vNormal * aBoneWeights0.x;
|
||||
totalWeight += aBoneWeights0.x;
|
||||
}
|
||||
if (aBoneWeights0.y > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices0.y)] * originalPos * aBoneWeights0.y;
|
||||
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.y)]) * vNormal * aBoneWeights0.y;
|
||||
totalWeight += aBoneWeights0.y;
|
||||
}
|
||||
if (aBoneWeights0.z > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices0.z)] * originalPos * aBoneWeights0.z;
|
||||
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.z)]) * vNormal * aBoneWeights0.z;
|
||||
totalWeight += aBoneWeights0.z;
|
||||
}
|
||||
if (aBoneWeights0.w > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices0.w)] * originalPos * aBoneWeights0.w;
|
||||
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.w)]) * vNormal * aBoneWeights0.w;
|
||||
totalWeight += aBoneWeights0.w;
|
||||
}
|
||||
if (aBoneWeights1.x > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices1.x)] * originalPos * aBoneWeights1.x;
|
||||
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices1.x)]) * vNormal * aBoneWeights1.x;
|
||||
totalWeight += aBoneWeights1.x;
|
||||
}
|
||||
if (aBoneWeights1.y > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices1.y)] * originalPos * aBoneWeights1.y;
|
||||
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices1.y)]) * vNormal * aBoneWeights1.y;
|
||||
totalWeight += aBoneWeights1.y;
|
||||
}
|
||||
|
||||
if (totalWeight < 0.001) {
|
||||
skinnedPos = originalPos;
|
||||
skinnedNormal = vNormal;
|
||||
}
|
||||
|
||||
vec4 eyePos = ModelViewMatrix * skinnedPos;
|
||||
fogDistance = length(eyePos.xyz - uPlayerEyePos);
|
||||
gl_Position = ProjectionModelViewMatrix * skinnedPos;
|
||||
texCoord = vTexCoord;
|
||||
fragViewPos = eyePos.xyz;
|
||||
fragNormal = mat3(ModelViewMatrix) * skinnedNormal;
|
||||
fragPosLightSpace = uLightFromCamera * eyePos;
|
||||
fragWorldXZ = (uViewInverse * eyePos).xz;
|
||||
}
|
||||
71
resources/shaders/night_fog_skinning_web.vertex
Normal file
71
resources/shaders/night_fog_skinning_web.vertex
Normal file
@ -0,0 +1,71 @@
|
||||
attribute vec3 vPosition;
|
||||
attribute vec2 vTexCoord;
|
||||
attribute vec3 vNormal;
|
||||
attribute vec4 aBoneIndices0;
|
||||
attribute vec2 aBoneIndices1;
|
||||
attribute vec4 aBoneWeights0;
|
||||
attribute vec2 aBoneWeights1;
|
||||
|
||||
varying vec2 texCoord;
|
||||
varying float fogDistance;
|
||||
varying vec3 fragViewPos;
|
||||
varying vec3 fragNormal;
|
||||
varying vec2 fragWorldXZ;
|
||||
|
||||
uniform mat4 ProjectionModelViewMatrix;
|
||||
uniform mat4 ModelViewMatrix;
|
||||
uniform mat4 uViewInverse;
|
||||
uniform mat4 uBoneMatrices[58];
|
||||
uniform vec3 uPlayerEyePos;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 skinnedPos = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec3 skinnedNormal = vec3(0.0, 0.0, 0.0);
|
||||
vec4 originalPos = vec4(vPosition, 1.0);
|
||||
float totalWeight = 0.0;
|
||||
|
||||
if (aBoneWeights0.x > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices0.x)] * originalPos * aBoneWeights0.x;
|
||||
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.x)]) * vNormal * aBoneWeights0.x;
|
||||
totalWeight += aBoneWeights0.x;
|
||||
}
|
||||
if (aBoneWeights0.y > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices0.y)] * originalPos * aBoneWeights0.y;
|
||||
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.y)]) * vNormal * aBoneWeights0.y;
|
||||
totalWeight += aBoneWeights0.y;
|
||||
}
|
||||
if (aBoneWeights0.z > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices0.z)] * originalPos * aBoneWeights0.z;
|
||||
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.z)]) * vNormal * aBoneWeights0.z;
|
||||
totalWeight += aBoneWeights0.z;
|
||||
}
|
||||
if (aBoneWeights0.w > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices0.w)] * originalPos * aBoneWeights0.w;
|
||||
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices0.w)]) * vNormal * aBoneWeights0.w;
|
||||
totalWeight += aBoneWeights0.w;
|
||||
}
|
||||
if (aBoneWeights1.x > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices1.x)] * originalPos * aBoneWeights1.x;
|
||||
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices1.x)]) * vNormal * aBoneWeights1.x;
|
||||
totalWeight += aBoneWeights1.x;
|
||||
}
|
||||
if (aBoneWeights1.y > 0.0) {
|
||||
skinnedPos += uBoneMatrices[int(aBoneIndices1.y)] * originalPos * aBoneWeights1.y;
|
||||
skinnedNormal += mat3(uBoneMatrices[int(aBoneIndices1.y)]) * vNormal * aBoneWeights1.y;
|
||||
totalWeight += aBoneWeights1.y;
|
||||
}
|
||||
|
||||
if (totalWeight < 0.001) {
|
||||
skinnedPos = originalPos;
|
||||
skinnedNormal = vNormal;
|
||||
}
|
||||
|
||||
vec4 eyePos = ModelViewMatrix * skinnedPos;
|
||||
fogDistance = length(eyePos.xyz - uPlayerEyePos);
|
||||
gl_Position = ProjectionModelViewMatrix * skinnedPos;
|
||||
texCoord = vTexCoord;
|
||||
fragViewPos = eyePos.xyz;
|
||||
fragNormal = mat3(ModelViewMatrix) * skinnedNormal;
|
||||
fragWorldXZ = (uViewInverse * eyePos).xz;
|
||||
}
|
||||
24
resources/shaders/night_fog_web.vertex
Normal file
24
resources/shaders/night_fog_web.vertex
Normal file
@ -0,0 +1,24 @@
|
||||
attribute vec3 vPosition;
|
||||
attribute vec2 vTexCoord;
|
||||
attribute vec3 vNormal;
|
||||
|
||||
varying vec2 texCoord;
|
||||
varying float fogDistance;
|
||||
varying vec3 fragViewPos;
|
||||
varying vec3 fragNormal;
|
||||
varying vec2 fragWorldXZ;
|
||||
|
||||
uniform mat4 ProjectionModelViewMatrix;
|
||||
uniform mat4 ModelViewMatrix;
|
||||
uniform vec3 uPlayerEyePos;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 eyePos = ModelViewMatrix * vec4(vPosition.xyz, 1.0);
|
||||
fogDistance = length(eyePos.xyz - uPlayerEyePos);
|
||||
gl_Position = ProjectionModelViewMatrix * vec4(vPosition.xyz, 1.0);
|
||||
texCoord = vTexCoord;
|
||||
fragViewPos = eyePos.xyz;
|
||||
fragNormal = mat3(ModelViewMatrix) * vNormal;
|
||||
fragWorldXZ = vPosition.xz;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user