commit d673543dd5db4bf86d103a2eed4d78a9e2efb879 Author: iisaev Date: Thu Sep 10 10:59:37 2026 +0300 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c301ca8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +# Godot 4.x +.godot/ +.idea/ +sdk/ +bin/ +obj/ + +#ai +.omo/ +.opencode/ + +gen/ +obj/ +bin/ + +*.tres~ +*.tscn~ + +# GDScript LSP +.godot/ + +# Export +*.exe +*.dmg +*.apk +*.aab +*.pck +*.zip +*.log + +# OS +.DS_Store +Thumbs.db + +# Editor +*.import +*.godot.uid diff --git a/locale/ui_en.properties b/locale/ui_en.properties new file mode 100644 index 0000000..fef41d3 --- /dev/null +++ b/locale/ui_en.properties @@ -0,0 +1,136 @@ +# --- scenes/battle/winground.tscn --- +mod_interface_name = Interface +mod_interface_desc = Game interface +ui/battle/victory = Victory +ui/battle/victory/return = Continue +ui/battle/victory/loot_title = Loot: + +# --- scenes/battle/deadground.tscn --- +ui/battle/defeat = Defeat +ui/battle/endgame/to_main_menu = Main menu + +# --- scenes/battle/battle.tscn --- +ui/battle/next = End turn + +# --- scenes/menu/main_menu.tscn --- +menu/newgame = New Game +ui/menu/load = Load +menu/settings = Settings +menu/exit = Exit +menu/tools = Tools + +# --- Mods Menu --- +menu/mods = Mods +mods/title = Mods +mods/enable = Enable +mods/disable = Disable +mods/enabled = Enabled +mods/disabled = Disabled +mods/disabled_reason = Disabled +mods/dep_disabled_reason = Dependency "{0}" is disabled +mods/dependency_disabled = Dependency disabled +mods/invalid_dep_format = Invalid dependency format: "{0}" +mods/required_mod_not_loaded = Required mod "{0}" is not loaded +mods/version_mismatch = Version mismatch: requires {0}, found {1} +mods/restart_required = Restart required for changes to take effect +mods/back = Back +mods/author = Author +mods/version = Version +mods/depends = Dependencies +mods/used_by = Used by +mods/overrides_title = Overrides +mods/reset_order = Reset Order +mods/reset_order_title = Reset Order +mods/reset_order_text = Are you sure you want to reset the mod order? It will be recalculated automatically +mods/reset_order_confirm = Yes +mods/reset_order_cancel = Cancel +mods/tab_device = Device +mods/tab_network = Network +mods/network_refresh = Refresh +mods/network_loading = Loading catalog... +mods/network_ready = Catalog loaded +mods/network_empty = No mods in catalog +mods/network_error = Failed to load catalog +mods/network_no_urls = No catalog URLs configured +mods/status_installed = Installed +mods/status_update_available = Update available +mods/status_not_installed = Not installed +mods/status_modified = Modified locally +mods/catalog_export = Export to Catalog +mods/catalog_title = Export Catalog Entry +mods/catalog_download_url = Download URL +mods/catalog_category = Category +mods/category_story = Story +mods/category_characters = Characters +mods/category_gameplay = Gameplay +mods/category_visual = Visual +mods/category_audio = Audio +mods/category_ui = UI +mods/category_locale = Locale +mods/category_library = Library +mods/category_overhaul = Overhaul +mods/category_other = Other +mods/catalog_tags = Tags (comma-separated) +mods/catalog_changelog = Changelog +mods/catalog_status = Status +mods/catalog_min_game_version = Min Game Version +mods/catalog_icon_url = Icon URL +mods/catalog_copy = Copy JSON +mods/catalog_export_file = Export to File +mods/catalog_close = Close +mods/install_button = Install +mods/update_button = Update +mods/overwrite_button = Overwrite +mods/downgrade_button = Downgrade +mods/restart_button = Restart required +mods/installing = Installing... +mods/install_complete = Install complete. Restart required. +mods/install_failed = Install failed. Check log for details. + +# --- Save/Load --- +ui/load/title = Load +ui/save/title = Save +ui/save/empty = Empty +ui/save/overwrite_title = Overwrite save +ui/save/overwrite_text = A save already exists in this slot. Overwrite? +ui/save/save_button = Overwrite +ui/save/cancel_button = Cancel +ui/save/game_day = Day {day}, {time} +ui/save/party_size = Party: {count} + +# --- GameMenu --- +menu/resume = Resume +menu/save = Save +menu/load = Load +menu/main_menu = Main menu + +# --- Character Panel --- +ui/character_panel/title = Character Actions +ui/character_panel/reset = Reset +ui/character_panel/close = Close +ui/character_panel/reset_title = Reset Action Assignments +ui/character_panel/reset_text = Are you sure you want to reset all action assignments? Character actions will return to defaults, collected actions will stay in the pool. +ui/character_panel/reset_ok = Reset +ui/character_panel/reset_cancel = Cancel + +# --- Inventory --- +ui/inventory/title = Inventory +ui/inventory/use = Use +ui/inventory/drop = Drop +ui/inventory/drop_all = All +ui/inventory/drop_confirm = Drop +ui/inventory/drop_quantity = Drop +ui/inventory/close = Close +ui/inventory/no_ap = Not enough AP +ui/inventory/select_target = Select target +ui/inventory/cancel = Cancel + +# --- Map --- +ui/map/close = Close + +# --- Quest Journal --- +ui/journal/title = Journal +ui/journal/active = Active +ui/journal/completed = Completed +ui/journal/close = Close +ui/journal/empty = No quests diff --git a/locale/ui_ru.properties b/locale/ui_ru.properties new file mode 100644 index 0000000..c5fa2fa --- /dev/null +++ b/locale/ui_ru.properties @@ -0,0 +1,136 @@ +# --- scenes/battle/winground.tscn --- +ui/battle/victory = Победа +ui/battle/victory/return = Продолжить +ui/battle/victory/loot_title = Добыча: + +# --- scenes/battle/deadground.tscn --- +ui/battle/defeat = Поражение +ui/battle/endgame/to_main_menu = Главное меню + +# --- scenes/battle/battle.tscn --- +ui/battle/next = Конец хода + +# --- scenes/menu/main_menu.tscn --- +menu/newgame = Новая игра +ui/menu/load = Загрузить +menu/settings = Настройки +menu/exit = Выход +menu/tools = Инструменты + +# --- Mods Menu --- +menu/mods = Моды +mods/title = Моды +mods/enable = Включить +mods/disable = Выключить +mods/enabled = Включён +mods/disabled = Выключен +mods/disabled_reason = Выключен +mods/dep_disabled_reason = Зависимость "{0}" выключена +mods/dependency_disabled = Зависимость отключена +mods/invalid_dep_format = Неверный формат зависимости: "{0}" +mods/required_mod_not_loaded = Требуемый мод "{0}" не загружен +mods/version_mismatch = Несовпадение версий: требуется {0}, найдена {1} +mods/restart_required = Перезапустите игру для применения изменений +mods/back = Назад +mods/author = Автор +mods/version = Версия +mods/depends = Зависимости +mods/used_by = Используется +mods/overrides_title = Переопределения +mods/reset_order = Сбросить порядок +mods/reset_order_title = Сброс порядка +mods/reset_order_text = Вы действительно хотите сбросить порядок модов? Он будет рассчитан автоматически заново +mods/reset_order_confirm = Да +mods/reset_order_cancel = Отмена +mods/tab_device = Устройство +mods/tab_network = Сеть +mods/network_refresh = Обновить +mods/network_loading = Загрузка каталога... +mods/network_ready = Каталог загружен +mods/network_empty = В каталоге нет модов +mods/network_error = Ошибка загрузки каталога +mods/network_no_urls = Не настроены URL каталогов +mods/status_installed = Установлен +mods/status_update_available = Доступно обновление +mods/status_not_installed = Не установлен +mods/status_modified = Изменён локально +mods/catalog_export = Экспорт в каталог +mods/catalog_title = Экспорт записи каталога +mods/catalog_download_url = URL скачивания +mods/catalog_category = Категория +mods/category_story = Сюжет +mods/category_characters = Персонажи +mods/category_gameplay = Геймплей +mods/category_visual = Визуал +mods/category_audio = Аудио +mods/category_ui = Интерфейс +mods/category_locale = Перевод +mods/category_library = Библиотека +mods/category_overhaul = Тотальная конверсия +mods/category_other = Прочее +mods/catalog_tags = Теги (через запятую) +mods/catalog_changelog = Список изменений +mods/catalog_status = Статус +mods/catalog_min_game_version = Мин. версия игры +mods/catalog_icon_url = URL иконки +mods/catalog_copy = Копировать JSON +mods/catalog_export_file = Экспорт в файл +mods/catalog_close = Закрыть +mods/install_button = Установить +mods/update_button = Обновить +mods/overwrite_button = Перезаписать +mods/downgrade_button = Даунгрейд +mods/restart_button = Перезапуск +mods/installing = Установка... +mods/install_complete = Установка завершена. Требуется перезапуск. +mods/install_failed = Ошибка установки. Подробности в логе. + +# --- Save/Load --- +ui/load/title = Загрузка +ui/save/title = Сохранение +ui/save/empty = Пусто +ui/save/overwrite_title = Перезаписать сохранение +ui/save/overwrite_text = Сохранение в этом слоте уже существует. Перезаписать? +ui/save/save_button = Перезаписать +ui/save/cancel_button = Отмена +ui/save/game_day = День {day}, {time} +ui/save/party_size = Отряд: {count} + +# --- GameMenu --- +menu/resume = Вернуться +menu/save = Сохранить +menu/load = Загрузить +menu/main_menu = Главное меню + +# --- Character Panel --- +ui/character_panel/title = Действия персонажей +ui/character_panel/reset = Сброс +ui/character_panel/close = Закрыть +ui/character_panel/reset_title = Сбросить распределение действий +ui/character_panel/reset_text = Вы уверены, что хотите сбросить распределение всех действий? Действия персонажей вернутся к исходным, собранные действия останутся в пуле. +ui/character_panel/reset_ok = Сбросить +ui/character_panel/reset_cancel = Отмена + +# --- Inventory --- +ui/inventory/title = Инвентарь +ui/inventory/use = Использовать +ui/inventory/drop = Выбросить +ui/inventory/drop_all = Все +ui/inventory/drop_confirm = Выбросить +ui/inventory/drop_quantity = Выбросить +ui/inventory/close = Закрыть +ui/inventory/no_ap = Недостаточно ОД +ui/inventory/select_target = Выберите цель +ui/inventory/cancel = Отмена + +# --- Map --- +ui/map/close = Закрыть + +# --- Quest Journal --- +ui/journal/title = Журнал +ui/journal/active = В процессе +ui/journal/completed = Завершённые +ui/journal/close = Закрыть +ui/journal/empty = Нет квестов +mod_interface_name = Интерфейс +mod_interface_desc = Игровой интерфейс diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..735ae61 --- /dev/null +++ b/manifest.json @@ -0,0 +1,8 @@ +{ + "id": "interface", + "name": "Interface", + "version": "1.0.0", + "author": "ct", + "description": "Game interface", + "depends": ["core>=1"] +} diff --git a/mod.png b/mod.png new file mode 100644 index 0000000..2edfb90 Binary files /dev/null and b/mod.png differ diff --git a/shaders/avatar.gdshader b/shaders/avatar.gdshader new file mode 100644 index 0000000..15c4f9b --- /dev/null +++ b/shaders/avatar.gdshader @@ -0,0 +1,48 @@ +shader_type canvas_item; +render_mode blend_premul_alpha; + +uniform int hide_mode : hint_range(0, 1) = 0; +uniform vec4 outline_color : source_color = vec4(0.0, 0.0, 0.0, 1.0); +uniform vec4 invert_outline_color : source_color = vec4(1.0, 1.0, 1.0, 1.0); +uniform vec2 pixel_size = vec2(0.001953125, 0.001953125); + +void fragment() { + vec4 color = texture(TEXTURE, UV) * COLOR; + +#ifdef ALPHA_CLIP + if (color.a < 0.001) + discard; +#endif + + if (hide_mode > 0) { + color.r = 0.0; + color.g = 0.0; + color.b = 0.0; + } + + if (color.a > 0.99) { + COLOR = color; + } else { + float max_alpha = 0.0; + + for (int x = -2; x <= 2; x++) { + for (int y = -2; y <= 2; y++) { + if (x == 0 && y == 0) + continue; + + vec2 offset = vec2(float(x), float(y)) * pixel_size; + float neighbor_alpha = texture(TEXTURE, UV + offset).a; + max_alpha = max(max_alpha, neighbor_alpha); + } + } + + if (max_alpha > 0.99) { + if (hide_mode > 0) + COLOR = invert_outline_color; + else + COLOR = outline_color; + } else { + COLOR = color; + } + } +} diff --git a/shaders/default.gdshader b/shaders/default.gdshader new file mode 100644 index 0000000..5a6fe27 --- /dev/null +++ b/shaders/default.gdshader @@ -0,0 +1,15 @@ +shader_type canvas_item; +render_mode blend_premul_alpha; + +uniform vec4 tint : source_color = vec4(1.0, 1.0, 1.0, 1.0); + +void fragment() { + vec4 color = texture(TEXTURE, UV) * COLOR * tint; + +#ifdef ALPHA_CLIP + if (color.a < 0.001) + discard; +#endif + + COLOR = color; +} diff --git a/shaders/effect_anim.gdshader b/shaders/effect_anim.gdshader new file mode 100644 index 0000000..6d17549 --- /dev/null +++ b/shaders/effect_anim.gdshader @@ -0,0 +1,24 @@ +shader_type canvas_item; +render_mode blend_premul_alpha; + +uniform float frame_index : hint_range(0.0, 1024.0) = 0.0; +uniform float frame_count : hint_range(1.0, 1024.0) = 5.0; + +void fragment() { + float frame_width = 1.0 / frame_count; + float frame_u = frame_index * frame_width; + vec2 uv = UV; + uv.x = uv.x * frame_width + frame_u; + + vec4 color = texture(TEXTURE, uv) * COLOR; + + float luma = dot(color.rgb, vec3(0.299, 0.587, 0.114)); + color.a *= luma; + +#ifdef ALPHA_CLIP + if (color.a < 0.001) + discard; +#endif + + COLOR = color; +} diff --git a/shaders/interactive_highlight.gdshader b/shaders/interactive_highlight.gdshader new file mode 100644 index 0000000..d3b5f80 --- /dev/null +++ b/shaders/interactive_highlight.gdshader @@ -0,0 +1,9 @@ +shader_type canvas_item; + +uniform vec4 modulate_color : source_color = vec4(0.0); + +void fragment() { + vec4 tex = texture(TEXTURE, UV); + COLOR = tex; + COLOR.rgb = mix(COLOR.rgb, modulate_color.rgb, modulate_color.a); +} diff --git a/shaders/noise_simplex.gdshaderinclude b/shaders/noise_simplex.gdshaderinclude new file mode 100644 index 0000000..b33d635 --- /dev/null +++ b/shaders/noise_simplex.gdshaderinclude @@ -0,0 +1,79 @@ +// Array and textureless GLSL 2D/3D/4D simplex noise functions. +// Ported from Ashima Arts webgl-noise (MIT License). +// https://github.com/ashima/webgl-noise + +vec3 mod289_vec3(vec3 x) { + return x - floor(x * (1.0 / 289.0)) * 289.0; +} + +vec4 mod289_vec4(vec4 x) { + return x - floor(x * (1.0 / 289.0)) * 289.0; +} + +vec4 permute(vec4 x) { + return mod289_vec4(((x * 34.0) + 1.0) * x); +} + +vec4 taylor_inv_sqrt(vec4 r) { + return 1.79284291400159 - 0.85373472095314 * r; +} + +float snoise(vec3 v) { + const vec2 C = vec2(1.0 / 6.0, 1.0 / 3.0); + const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); + + vec3 i = floor(v + dot(v, C.yyy)); + vec3 x0 = v - i + dot(i, C.xxx); + + vec3 g = step(x0.yzx, x0.xyz); + vec3 l = 1.0 - g; + vec3 i1 = min(g.xyz, l.zxy); + vec3 i2 = max(g.xyz, l.zxy); + + vec3 x1 = x0 - i1 + C.xxx; + vec3 x2 = x0 - i2 + C.yyy; + vec3 x3 = x0 - D.yyy; + + i = mod289_vec3(i); + vec4 p = permute(permute(permute( + i.z + vec4(0.0, i1.z, i2.z, 1.0)) + + i.y + vec4(0.0, i1.y, i2.y, 1.0)) + + i.x + vec4(0.0, i1.x, i2.x, 1.0)); + + float n_ = 0.142857142857; + vec3 ns = n_ * D.wyz - D.xzx; + + vec4 j = p - 49.0 * floor(p * ns.z * ns.z); + + vec4 x_ = floor(j * ns.z); + vec4 y_ = floor(j - 7.0 * x_); + + vec4 x = x_ * ns.x + ns.yyyy; + vec4 y = y_ * ns.x + ns.yyyy; + vec4 h = 1.0 - abs(x) - abs(y); + + vec4 b0 = vec4(x.xy, y.xy); + vec4 b1 = vec4(x.zw, y.zw); + + vec4 s0 = floor(b0) * 2.0 + 1.0; + vec4 s1 = floor(b1) * 2.0 + 1.0; + vec4 sh = -step(h, vec4(0.0, 0.0, 0.0, 0.0)); + + vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy; + vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww; + + vec3 p0 = vec3(a0.xy, h.x); + vec3 p1 = vec3(a0.zw, h.y); + vec3 p2 = vec3(a1.xy, h.z); + vec3 p3 = vec3(a1.zw, h.w); + + vec4 norm = taylor_inv_sqrt(vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); + p0 *= norm.x; + p1 *= norm.y; + p2 *= norm.z; + p3 *= norm.w; + + vec4 m = max(0.6 - vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0); + m = m * m; + return 42.0 * dot(m * m, vec4(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3))); +} diff --git a/shaders/pixel_art.gdshader b/shaders/pixel_art.gdshader new file mode 100644 index 0000000..5a6a1e2 --- /dev/null +++ b/shaders/pixel_art.gdshader @@ -0,0 +1,18 @@ +shader_type canvas_item; +render_mode blend_premul_alpha; + +uniform float pixel_size : hint_range(0.1, 1000.0) = 1.0; + +void fragment() { + vec2 pixel_scale = SCREEN_PIXEL_SIZE * pixel_size; + vec2 pixel_uv = floor(SCREEN_UV / pixel_scale) * pixel_scale; + + vec4 color = texture(TEXTURE, pixel_uv) * COLOR; + +#ifdef ALPHA_CLIP + if (color.a < 0.001) + discard; +#endif + + COLOR = color; +} diff --git a/shaders/pixel_art_post_process.gdshader b/shaders/pixel_art_post_process.gdshader new file mode 100644 index 0000000..ab277f5 --- /dev/null +++ b/shaders/pixel_art_post_process.gdshader @@ -0,0 +1,11 @@ +shader_type canvas_item; +render_mode blend_disabled; + +uniform sampler2D screen_texture : hint_screen_texture, filter_nearest; +uniform float pixel_size : hint_range(0.1, 1000.0) = 1.0; + +void fragment() { + vec2 pixel_scale = SCREEN_PIXEL_SIZE * pixel_size; + vec2 pixel_uv = floor(SCREEN_UV / pixel_scale) * pixel_scale; + COLOR = texture(screen_texture, pixel_uv); +} diff --git a/shaders/scene_transition.gdshader b/shaders/scene_transition.gdshader new file mode 100644 index 0000000..0715529 --- /dev/null +++ b/shaders/scene_transition.gdshader @@ -0,0 +1,80 @@ +shader_type canvas_item; +render_mode blend_premul_alpha; + +uniform vec4 tint : source_color = vec4(1.0, 1.0, 1.0, 1.0); +uniform float noise_scale : hint_range(1.0, 100.0) = 20.0; +uniform float smoothness : hint_range(0.0, 0.5) = 0.1; +uniform float progress : hint_range(0.0, 1.0) = 0.0; +uniform bool invert_direction = false; +uniform float distortion : hint_range(0.0, 0.5) = 0.05; +uniform float hue_shift : hint_range(0.0, 1.0) = 0.2; +uniform float glow_intensity : hint_range(0.0, 1.0) = 0.3; + +float random(vec2 uv) { + return fract(sin(dot(uv, vec2(12.9898, 78.233))) * 43758.5453); +} + +float perlin_noise(vec2 uv) { + vec2 i = floor(uv); + vec2 f = fract(uv); + vec2 u = f * f * (3.0 - 2.0 * f); + + float a = random(i); + float b = random(i + vec2(1.0, 0.0)); + float c = random(i + vec2(0.0, 1.0)); + float d = random(i + vec2(1.0, 1.0)); + + return mix(mix(a, b, u.x), mix(c, d, u.x), u.y); +} + +float fractal_noise(vec2 uv, int octaves) { + float value = 0.0; + float amplitude = 0.5; + float frequency = 1.0; + + for (int i = 0; i < 8; i++) { + if (i >= octaves) + break; + value += perlin_noise(uv * frequency) * amplitude; + amplitude *= 0.5; + frequency *= 2.0; + } + + return value; +} + +vec3 hue_shift_func(vec3 color, float hue) { + const vec3 k = vec3(0.57735, 0.57735, 0.57735); + float cos_angle = cos(hue); + return color * cos_angle + cross(k, color) * sin(hue) + k * dot(k, color) * (1.0 - cos_angle); +} + +void fragment() { + vec2 noise_uv = UV * noise_scale; + float noise = fractal_noise(noise_uv, 3); + + float distorted_progress = progress + noise * distortion; + + float transition_mask; + if (invert_direction) + transition_mask = step(distorted_progress, noise); + else + transition_mask = step(noise, distorted_progress); + + float edge = smoothstep(0.0, smoothness, abs(noise - progress)); + float alpha = mix(transition_mask, 1.0 - transition_mask, edge); + if (invert_direction) + alpha = 1.0 - alpha; + + vec4 col = texture(TEXTURE, UV) * COLOR * tint; + + float glow = clamp(abs(noise - progress) / smoothness, 0.0, 1.0) * glow_intensity; + col.rgb += glow * vec3(1.0, 0.8, 0.5) * col.a; + + if (abs(noise - progress) < smoothness * 2.0) { + col.rgb = hue_shift_func(col.rgb, hue_shift); + } + + col.a *= alpha; + COLOR = col; +} diff --git a/shaders/timed_sprite.gdshader b/shaders/timed_sprite.gdshader new file mode 100644 index 0000000..4f47602 --- /dev/null +++ b/shaders/timed_sprite.gdshader @@ -0,0 +1,127 @@ +shader_type canvas_item; +render_mode blend_premul_alpha; + +uniform sampler2D depth_mask : source_color, filter_linear; +uniform sampler2D albedo_map : source_color, filter_linear; + +uniform float flicker_speed : hint_range(0.0, 100.0) = 5.0; +uniform float flicker_strength : hint_range(0.0, 1.0) = 0.3; +uniform float flicker_scale : hint_range(0.0, 10.0) = 1.0; + +uniform bool use_time = true; + +uniform vec4 day_color : source_color = vec4(1.0, 1.0, 1.0, 1.0); +uniform vec4 morning_color : source_color = vec4(0.8207547, 0.6465379, 0.8050903, 1.0); +uniform vec4 night_color : source_color = vec4(0.0, 0.13673696, 0.20754719, 1.0); +uniform vec4 evening_color : source_color = vec4(0.81671757, 0.7075472, 0.9433962, 1.0); +uniform vec4 time_weights = vec4(0.0, 1.0, 0.0, 0.0); + +uniform float light_intensity : hint_range(0.0, 10.0) = 2.0; +uniform float light_falloff : hint_range(0.0, 10.0) = 3.0; +uniform float light_radius_scale : hint_range(0.0, 10.0) = 1.0; + +uniform vec2 light_positions[11]; +uniform vec4 light_colors[11]; +uniform float light_radii[11]; +uniform float light_influence[11]; +uniform int light_count; + +varying vec2 world_pos; + +float rand(vec2 co) { + return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453); +} + +vec3 calculate_light_color(vec2 wp, out float total_influence) { + vec3 combined_color = vec3(0.0, 0.0, 0.0); + total_influence = 0.0; + + for (int i = 0; i < 11; i++) { + if (i >= light_count) + break; + + vec2 light_pos = light_positions[i]; + float light_radius = light_radii[i] * light_radius_scale; + vec3 light_col = light_colors[i].rgb; + + float dist = distance(wp, light_pos); + float influence = clamp(1.0 - dist / light_radius, 0.0, 1.0); + // Avoid pow with negative base + if (influence <= 0.0) + continue; + influence = pow(influence, light_falloff); + + float flicker_seed = light_pos.x * 1.357 + light_pos.y * 2.468 + float(i) * 3.579; + + float discrete_time = floor(TIME * flicker_speed * 3.0 + flicker_seed) / 3.0; + + float t1 = discrete_time * 2.0; + float t2 = discrete_time * 3.0 + 1.2; + float t3 = discrete_time * 4.0 + 2.4; + + float flicker1 = floor((sin(t1) * 0.5 + 0.5) * 4.0) / 3.0; + float flicker2 = floor((sin(t2) * 0.3 + 0.5) * 3.0) / 2.0; + float flicker3 = floor((sin(t3) * 0.2 + 0.5) * 3.0) / 2.0; + + float flicker = flicker1 * 0.5 + flicker2 * 0.3 + flicker3 * 0.2; + + float noise_seed = floor(TIME * flicker_speed * 2.0 + flicker_seed); + float noise_val = rand(vec2(noise_seed, flicker_seed)) * 0.15; + + flicker = floor((flicker + noise_val) * 5.0) / 4.0; + flicker = clamp(flicker, 0.0, 1.0); + + float flicker_factor = 0.7 + flicker * 0.6 * flicker_strength; + flicker_factor = floor(flicker_factor * 8.0) / 7.0; + + influence *= flicker_factor; + + combined_color += light_col * influence * light_intensity * light_influence[i]; + total_influence += influence * light_intensity * light_influence[i]; + } + + return combined_color; +} + +void vertex() { + world_pos = (MODEL_MATRIX * vec4(VERTEX, 0.0, 1.0)).xy; +} + +void fragment() { + vec4 color = texture(TEXTURE, UV) * COLOR; + float a = color.a; + + float depth = texture(depth_mask, UV).r; + float albedo = texture(albedo_map, UV).r; + +#ifdef ALPHA_CLIP + if (color.a < 0.001) + discard; +#endif + + if (!use_time) { + COLOR = color; + } else { + vec4 weights = time_weights; + + vec4 time_color = morning_color * weights.x + + day_color * weights.y + + evening_color * weights.z + + night_color * weights.w; + + float total_influence; + vec3 light_col = calculate_light_color(world_pos, total_influence); + total_influence = clamp(total_influence, 0.0, 1.0); + + float light_infl = clamp(mix(light_col.r, 0.0, weights.y + weights.x + weights.z) * depth, 0.0, 1.0); + + float pixel_luma = max(dot(color.rgb, vec3(0.299, 0.587, 0.114)), 0.01); + float target_luma = max(albedo, pixel_luma); + float lift = mix(1.0, target_luma / pixel_luma, light_infl); + + vec3 lit_result = min(color.rgb * lift * light_col, 1.0); + + COLOR.rgb = mix(color.rgb * time_color.rgb, lit_result, light_infl); + COLOR.a = a; + } +} diff --git a/ui/InventoryCells.png b/ui/InventoryCells.png new file mode 100644 index 0000000..82fbe91 Binary files /dev/null and b/ui/InventoryCells.png differ diff --git a/ui/base/black.png b/ui/base/black.png new file mode 100644 index 0000000..3cf27f4 Binary files /dev/null and b/ui/base/black.png differ diff --git a/ui/base/dark.png b/ui/base/dark.png new file mode 100644 index 0000000..a7b9301 Binary files /dev/null and b/ui/base/dark.png differ diff --git a/ui/base/empty.png b/ui/base/empty.png new file mode 100644 index 0000000..fdf950d Binary files /dev/null and b/ui/base/empty.png differ diff --git a/ui/base/white.png b/ui/base/white.png new file mode 100644 index 0000000..818c71d Binary files /dev/null and b/ui/base/white.png differ diff --git a/ui/battle/deadground.png b/ui/battle/deadground.png new file mode 100644 index 0000000..b2fd8ab Binary files /dev/null and b/ui/battle/deadground.png differ diff --git a/ui/battle/winground.png b/ui/battle/winground.png new file mode 100644 index 0000000..4201ba3 Binary files /dev/null and b/ui/battle/winground.png differ diff --git a/ui/gui.png b/ui/gui.png new file mode 100644 index 0000000..e04f7c8 Binary files /dev/null and b/ui/gui.png differ diff --git a/ui/icon.png b/ui/icon.png new file mode 100644 index 0000000..dc11f27 Binary files /dev/null and b/ui/icon.png differ diff --git a/ui/icons/bag.png b/ui/icons/bag.png new file mode 100644 index 0000000..1f515c5 Binary files /dev/null and b/ui/icons/bag.png differ diff --git a/ui/icons/cards.png b/ui/icons/cards.png new file mode 100644 index 0000000..4df191b Binary files /dev/null and b/ui/icons/cards.png differ diff --git a/ui/icons/coin.png b/ui/icons/coin.png new file mode 100644 index 0000000..6e396a0 Binary files /dev/null and b/ui/icons/coin.png differ diff --git a/ui/icons/health.png b/ui/icons/health.png new file mode 100644 index 0000000..f1c693d Binary files /dev/null and b/ui/icons/health.png differ diff --git a/ui/icons/journal.png b/ui/icons/journal.png new file mode 100644 index 0000000..42bff7f Binary files /dev/null and b/ui/icons/journal.png differ diff --git a/ui/icons/lamp.png b/ui/icons/lamp.png new file mode 100644 index 0000000..b6ab086 Binary files /dev/null and b/ui/icons/lamp.png differ diff --git a/ui/icons/map.png b/ui/icons/map.png new file mode 100644 index 0000000..5731c3e Binary files /dev/null and b/ui/icons/map.png differ diff --git a/ui/icons/save.png b/ui/icons/save.png new file mode 100644 index 0000000..72e1d5b Binary files /dev/null and b/ui/icons/save.png differ diff --git a/ui/icons/settings.png b/ui/icons/settings.png new file mode 100644 index 0000000..c82de78 Binary files /dev/null and b/ui/icons/settings.png differ diff --git a/ui/icons/skills.png b/ui/icons/skills.png new file mode 100644 index 0000000..234b3df Binary files /dev/null and b/ui/icons/skills.png differ diff --git a/ui/plate_day.png b/ui/plate_day.png new file mode 100644 index 0000000..093bd9f Binary files /dev/null and b/ui/plate_day.png differ diff --git a/ui/plate_night.png b/ui/plate_night.png new file mode 100644 index 0000000..eba68cb Binary files /dev/null and b/ui/plate_night.png differ diff --git a/ui/skills/skill_frame.png b/ui/skills/skill_frame.png new file mode 100644 index 0000000..6e6705e Binary files /dev/null and b/ui/skills/skill_frame.png differ diff --git a/ui/skills/skill_frame_full.png b/ui/skills/skill_frame_full.png new file mode 100644 index 0000000..29a8019 Binary files /dev/null and b/ui/skills/skill_frame_full.png differ diff --git a/ui/tg.png b/ui/tg.png new file mode 100644 index 0000000..96496e9 Binary files /dev/null and b/ui/tg.png differ