34 Commits

Author SHA1 Message Date
24ffdaba5e Merge branch 'main' into tooltip 2026-07-02 22:56:34 +02:00
f63c9fa141 update audio player 2026-07-02 22:49:26 +02:00
498115107e update audio player 2026-07-02 22:29:22 +02:00
922c771185 add tooltips and fix stuff 2026-07-02 21:19:56 +02:00
3512145a66 fix new main menu 2026-07-01 22:29:55 +02:00
c22fffdfc1 fix input and delete dead code 2026-07-01 19:40:53 +02:00
238dd4a124 bind new inputs 2026-07-01 19:09:56 +02:00
c296531214 fix day nigh cycle 2026-07-01 16:55:01 +00:00
bdca270dca stop only if station is available on chunk 2026-07-01 17:59:50 +02:00
d47bc26583 fix snow for grass 2026-07-01 17:26:59 +02:00
802a7ef7c1 fix main menu test 2026-06-30 23:57:07 +02:00
3e2739cf02 generate new main menu screen 2026-06-30 23:46:15 +02:00
7be800398d update game_menu 2026-06-30 20:01:13 +00:00
7db1df9ab6 polish9
Co-authored-by: m.sonaglioni <m.sonaglioni@jmpgames.it>
Co-committed-by: m.sonaglioni <m.sonaglioni@jmpgames.it>
2026-06-30 19:58:03 +00:00
8198f7df1f fix snow and exposure 2026-06-30 17:04:40 +02:00
952058b0e0 fix snow for train and wagons 2026-06-30 11:08:37 +02:00
475749c4df fix wires, fix exposition for wheater change, add base wind, add fireflies when is night 2026-06-30 10:08:18 +02:00
086167a5a6 fix transition from splash 2026-06-29 18:16:30 +02:00
885bac9a4a Merge branch 'main' of https://gitea.jmpgames.it/jmp-games/tgcc 2026-06-29 18:10:58 +02:00
496a271946 fix transition 2026-06-29 18:10:38 +02:00
d0d052f65b polish 8 2026-06-29 13:33:30 +00:00
67a99051bd update save mode 2026-06-29 15:23:44 +02:00
fb848a9848 add new transaction and add splash screen 2026-06-29 14:59:58 +02:00
bc30a169dc fix stats manager 2026-06-29 10:48:58 +02:00
f5576959b7 add achievement for train change 2026-06-29 10:21:56 +02:00
b8ab8f4971 Merge pull request 'add whistle to train' (#38) from whitleandstats into main
Reviewed-on: #38
2026-06-29 08:20:37 +00:00
77df5fbbfd add human dresses 2026-06-27 18:13:09 +02:00
Matteo Sonaglioni
ed5eb706a1 fix ai 2026-06-27 17:47:15 +02:00
Matteo Sonaglioni
58f9188794 Merge branch 'main' into polish8 2026-06-27 16:40:46 +02:00
Matteo Sonaglioni
b463f55f53 nav mesh chunk 2026-06-27 16:23:24 +02:00
c0a68da7d1 update and improve ui 2026-06-27 11:54:01 +00:00
97bbca95e8 add sit state and colors to cat 2026-06-25 19:46:13 +00:00
Matteo Sonaglioni
ed25b40969 add nav mesh chunk pt1 2026-06-25 18:02:44 +02:00
2b1370bd40 update biome generator to support new ai 2026-06-24 17:44:41 +00:00
326 changed files with 14930 additions and 1602 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 KiB

View File

@@ -2,16 +2,16 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://d4e1lbng4uqk"
path="res://.godot/imported/quad_main.png-af26b29d5c3350fc4d75e08ad350ccc7.ctex"
uid="uid://bjowpx1ap4uxt"
path="res://.godot/imported/back.png-bddbf3418b746eb53bc79fd4d0989d41.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://core/game_menu/assets/page_3/quad_main.png"
dest_files=["res://.godot/imported/quad_main.png-af26b29d5c3350fc4d75e08ad350ccc7.ctex"]
source_file="res://addons/PageFlip/Assets/back.png"
dest_files=["res://.godot/imported/back.png-bddbf3418b746eb53bc79fd4d0989d41.ctex"]
[params]

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cen51wqc15b14"
path="res://.godot/imported/blank_page.png-589b6dfce0585742cc1d305c391c9cd9.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/PageFlip/Assets/blank_page.png"
dest_files=["res://.godot/imported/blank_page.png-589b6dfce0585742cc1d305c391c9cd9.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

View File

@@ -0,0 +1,19 @@
[remap]
importer="oggvorbisstr"
type="AudioStreamOggVorbis"
uid="uid://bhitebdghyhua"
path="res://.godot/imported/book_impact.ogg-ae2f194921fcd1bc549a3ddb37fab4ba.oggvorbisstr"
[deps]
source_file="res://addons/PageFlip/Assets/book_impact.ogg"
dest_files=["res://.godot/imported/book_impact.ogg-ae2f194921fcd1bc549a3ddb37fab4ba.oggvorbisstr"]
[params]
loop=false
loop_offset=0
bpm=0
beat_count=0
bar_beats=4

Binary file not shown.

After

Width:  |  Height:  |  Size: 765 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dbdwbowx32d3v"
path="res://.godot/imported/front.png-76dff7071666496195badceef4e0ce67.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/PageFlip/Assets/front.png"
dest_files=["res://.godot/imported/front.png-76dff7071666496195badceef4e0ce67.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 772 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dt1tiecgw5rip"
path="res://.godot/imported/interior.png-d4b06daf084fdb8a90836ec57d2dd53f.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/PageFlip/Assets/interior.png"
dest_files=["res://.godot/imported/interior.png-d4b06daf084fdb8a90836ec57d2dd53f.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

View File

@@ -0,0 +1,19 @@
[remap]
importer="oggvorbisstr"
type="AudioStreamOggVorbis"
uid="uid://bylfc3b5pmbij"
path="res://.godot/imported/page_flip.ogg-aabb6ae51ff161ae6afa52da11fe75de.oggvorbisstr"
[deps]
source_file="res://addons/PageFlip/Assets/page_flip.ogg"
dest_files=["res://.godot/imported/page_flip.ogg-aabb6ae51ff161ae6afa52da11fe75de.oggvorbisstr"]
[params]
loop=false
loop_offset=0
bpm=0
beat_count=0
bar_beats=4

View File

@@ -0,0 +1,49 @@
shader_type canvas_item;
uniform sampler2D front_texture : source_color, filter_linear_mipmap;
uniform sampler2D back_texture : source_color, filter_linear_mipmap;
uniform sampler2D spine_shadow_gradient : source_color, filter_linear, repeat_disable;
uniform float shadow_intensity : hint_range(0.0, 1.0) = 0.0;
uniform float max_shadow_spread : hint_range(0.0, 1.0) = 0.35;
uniform bool debug_mode = false;
uniform bool is_backward = false;
void fragment() {
vec2 uv_dx = dFdx(UV);
vec2 uv_dy = dFdy(UV);
float face_dir = uv_dx.x * uv_dy.y - uv_dx.y * uv_dy.x;
bool is_front = face_dir > 0.0;
vec4 base_color;
if (is_front) {
if (is_backward) {
// Let's try flipping Y just in case they meant upside down!
// And keep X normal, since UV goes 0 to 1.
base_color = texture(front_texture, UV);
} else {
base_color = texture(front_texture, UV);
}
} else {
if (is_backward) {
base_color = texture(back_texture, vec2(1.0 - UV.x, UV.y));
} else {
base_color = texture(back_texture, vec2(1.0 - UV.x, UV.y));
}
}
float current_spread = max_shadow_spread * (shadow_intensity + 0.001);
float sample_x = UV.x / current_spread;
float shadow_alpha = texture(spine_shadow_gradient, vec2(sample_x, 0.0)).a;
if (sample_x > 1.0) {
shadow_alpha = 0.0;
}
shadow_alpha *= shadow_intensity;
vec3 final_rgb = mix(base_color.rgb, vec3(0.0, 0.0, 0.0), shadow_alpha);
COLOR = vec4(final_rgb, base_color.a);
}

View File

@@ -0,0 +1 @@
uid://b57sdbj15qx37

View File

@@ -0,0 +1,9 @@
[gd_resource type="ShaderMaterial" load_steps=2 format=3 uid="uid://ddw2ie8wnrnre"]
[ext_resource type="Shader" uid="uid://b57sdbj15qx37" path="res://addons/PageFlip/Assets/page_flip_final.gdshader" id="1_cl0rr"]
[resource]
shader = ExtResource("1_cl0rr")
shader_parameter/shadow_intensity = 0.0
shader_parameter/max_shadow_spread = 0.35
shader_parameter/debug_mode = false

View File

@@ -0,0 +1,8 @@
[gd_resource type="GradientTexture2D" format=3 uid="uid://rm7bporlv3cf"]
[sub_resource type="Gradient" id="Gradient_3i6i7"]
offsets = PackedFloat32Array(0, 0.2731183, 0.44731182, 1)
colors = PackedColorArray(0, 0, 0, 0.521, 0, 0, 0, 0.492, 0, 0, 0, 0.358, 0, 0, 0, 0)
[resource]
gradient = SubResource("Gradient_3i6i7")

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cit41jypw2sy1"
path="res://.godot/imported/spine.png-c2fa10bef4996b84a954651c908149a7.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/PageFlip/Assets/spine.png"
dest_files=["res://.godot/imported/spine.png-c2fa10bef4996b84a954651c908149a7.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

229
addons/PageFlip/book_api.gd Normal file
View File

@@ -0,0 +1,229 @@
@tool
class_name BookAPI
extends RefCounted
## Static utility class for the PageFlip2D system by Newold.
## Provides helper methods to configure the book and facilitate interaction
## from embedded scenes (UI, puzzles, maps).
##
## [b]How to use:[/b][br]
## This class is designed to be used statically. You do not need to instance it.
## Simply call [code]BookAPI.function_name()[/code] from anywhere in your project.
## It automatically tracks the active [PageFlip2D] instance.
## (When a PageFlip scene enters the tree, it registers itself as the current_book.)
# ==============================================================================
# ENUMS (Mirrored for easy access)
# ==============================================================================
enum JumpTarget {
## Jump to the closed state showing the Front Cover.
FRONT_COVER,
## Jump to the closed state showing the Back Cover.
BACK_COVER,
## Jump to a specific content page number.
CONTENT_PAGE
}
# Internal reference to the currently active book.
static var _current_book: PageFlip2D
# ==============================================================================
# SETUP & REFERENCES
# ==============================================================================
## Registers a book instance as the currently active one.
## Automatically called by [PageFlip2D] in its [method Node._ready].
static func set_current_book(book: PageFlip2D) -> void:
_current_book = book
## Returns the currently active book instance, or null if none is registered.
static func get_current_book() -> PageFlip2D:
return _current_book
# ==============================================================================
# NAVIGATION CONTROLS
# ==============================================================================
## Turns the page forward (to the next page/spread).
## Does nothing if the book is animating or at the end.
static func next_page() -> void:
if is_instance_valid(_current_book):
force_release_control(_current_book)
_current_book.next_page()
## Turns the page backward (to the previous page/spread).
## Does nothing if the book is animating or at the beginning.
static func prev_page() -> void:
if is_instance_valid(_current_book):
force_release_control(_current_book)
_current_book.prev_page()
## Forces the active book to close towards a specific cover.
## [param to_front_cover]: If true, closes to the Front Cover (Right to Left). If false, closes to Back Cover.
static func force_close_book(to_front_cover: bool) -> void:
if is_instance_valid(_current_book):
force_release_control(_current_book)
_current_book.force_close_book(to_front_cover)
## Navigates to a specific page number (1-based index).
## Acts as a wrapper for go_to_spread, calculating the correct index automatically.
## [b]ASYNC:[/b] Must be called with 'await' if animated is true.
## [param page_num]: The 1-based page number (1 = first texture in pages_paths).
## [param target]: Specifies if the target is a content page or a cover.
static func go_to_page(page_num: int = 1, target: JumpTarget = JumpTarget.CONTENT_PAGE, animated: bool = true) -> void:
var book = _current_book
if not is_instance_valid(book): return
var target_spread_idx: int = 0
match target:
JumpTarget.FRONT_COVER:
target_spread_idx = -1
JumpTarget.BACK_COVER:
target_spread_idx = book.total_spreads
JumpTarget.CONTENT_PAGE:
# Calculate spread index: 1-2 -> Spread 0, 3-4 -> Spread 1, etc.
var safe_page = max(1, page_num)
target_spread_idx = int(safe_page / 2.0)
target_spread_idx = clampi(target_spread_idx, 0, book.total_spreads - 1)
await go_to_spread(book, target_spread_idx, animated)
## Navigates to a specific spread index directly.
## [b]ASYNC:[/b] Must be called with 'await' if animated is true.
## - Animated: Fast-forwards through pages with dynamic speed.
## - Instant: Snaps to page and manually triggers the scene activation handshake.
static func go_to_spread(book: PageFlip2D, target_spread: int, animated: bool = true) -> void:
if not is_instance_valid(book): return
# Clamp target
var final_target = clampi(target_spread, -1, book.total_spreads)
var diff = final_target - book.current_spread
if diff == 0:
return
force_release_control(book)
if not animated:
# INSTANT TELEPORT
book.current_spread = final_target
book.call("_update_static_visuals_immediate")
book.call("_update_volume_visuals")
# Force check for interactive scenes after teleport
book.call("_check_scene_activation")
else:
# ANIMATED FAST-FORWARD
if book.is_animating: return # Don't interrupt an existing animation
var original_speed = book.anim_player.speed_scale
# --- DYNAMIC SPEED CALCULATION ---
var steps = abs(diff)
# Base speed: 1.5x -> Max speed: 10.0x
var dynamic_speed = remap(float(steps), 0.0, float(book.total_spreads), 1.5, 10.0)
book.anim_player.speed_scale = dynamic_speed
var going_forward = diff > 0
for i in range(steps):
if not is_instance_valid(book): break
if going_forward: book.next_page()
else: book.prev_page()
# Wait for the physical page turn to finish before starting the next one.
if book.anim_player.is_playing():
await book.anim_player.animation_finished
else:
await book.get_tree().process_frame
# RESTORE STATE
if is_instance_valid(book):
book.anim_player.speed_scale = original_speed
# ==============================================================================
# STATE & INTERACTION HELPERS
# ==============================================================================
## Returns true if the book (active or specific) is currently animating.
static func is_busy(book_instance: PageFlip2D = null) -> bool:
var book = book_instance if book_instance else _current_book
if not is_instance_valid(book): return false
return book.is_animating
## Locates the PageFlip2D controller ancestor from any node inside an interactive page.
static func find_book_controller(caller_node: Node) -> PageFlip2D:
var current = caller_node
while current:
if current is PageFlip2D:
return current
current = current.get_parent()
return null
## Safely locks or unlocks the book's ability to turn pages manually.
## WARNING: If locked, the interactive scene MUST be responsible for unlocking it later.
static func set_interaction_lock(book: PageFlip2D, locked: bool) -> void:
if not is_instance_valid(book): return
book.call("_pageflip_set_input_enabled", not locked)
## Forces the book to regain input control immediately.
## Useful as a failsafe if an interactive scene closes unexpectedly.
static func force_release_control(book: PageFlip2D) -> void:
if not is_instance_valid(book): return
book.call("_pageflip_set_input_enabled", true)
# ==============================================================================
# CONFIGURATION HELPERS
# ==============================================================================
## Configures the visual properties of a Book instance via a dictionary.
static func configure_visuals(book: PageFlip2D, data: Dictionary) -> void:
if not is_instance_valid(book): return
if "pages" in data:
book.pages_paths = data["pages"]
book.call("_prepare_book_content")
if "cover_front_out" in data: book.tex_cover_front_out = data["cover_front_out"]
if "cover_front_in" in data: book.tex_cover_front_in = data["cover_front_in"]
if "cover_back_in" in data: book.tex_cover_back_in = data["cover_back_in"]
if "cover_back_out" in data: book.tex_cover_back_out = data["cover_back_out"]
if "spine_col" in data: book.spine_color = data["spine_col"]
if "spine_width" in data:
book.spine_width = data["spine_width"]
book.call("_build_spine")
if "size" in data:
book.target_page_size = data["size"]
book.call("_apply_new_size")
book.call("_update_static_visuals_immediate")
book.call("_update_volume_visuals")
## Configures the physics simulation of the page turning effect.
static func configure_physics(book: PageFlip2D, data: Dictionary) -> void:
if not is_instance_valid(book) or not book.dynamic_poly: return
var rigger = book.dynamic_poly
for key in data.keys():
rigger.set(key, data[key])
if rigger.has_method("rebuild"):
rigger.rebuild(book.target_page_size)

View File

@@ -0,0 +1 @@
uid://c2dx1dksgeey6

1416
addons/PageFlip/page_flip.gd Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
uid://ctw83iqgqxjjt

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,587 @@
@tool
class_name DynamicPage
extends Polygon2D
# ==============================================================================
# ENUMS & CONSTANTS
# ==============================================================================
## Defines the material physical properties for the page simulation.
enum PagePreset {
CUSTOM,
DEFAULT,
STANDARD_PAPER,
HEAVY_GRIMOIRE,
LIGHT_MAGAZINE,
OLD_SCROLL,
RIGID_BOARD,
WET_CLOTH,
PLASTIC_SHEET,
METAL_PLATE
}
## Determines the direction of the page turn curve.
enum CurlMode {
STRAIGHT,
TOP_CORNER_FIRST,
BOTTOM_CORNER_FIRST
}
const SKELETON_NAME = "AutoSkeleton"
const SHADOW_NAME = "AutoShadow"
# ==============================================================================
# SIGNALS
# ==============================================================================
signal change_page_requested
signal end_animation
# ==============================================================================
# INTERNAL CACHE
# ==============================================================================
var _custom_cache: Dictionary = {}
# ==============================================================================
# CONFIGURATION
# ==============================================================================
@export_category("Rig Generator")
## Horizontal mesh subdivision. Higher values create smoother bends.
@export_range(1, 20) var subdivision_x: int = 8
## Vertical mesh subdivision. Higher values allow for better corner curling.
@export_range(1, 10) var subdivision_y: int = 5
## Generates the mesh, skeleton, weights and animations.
@export var rebuild_all: bool = false : set = _on_generate_pressed
@export_category("Animation Generator")
@export_group("Quick Presets")
## Select a material style to auto-configure physics.
@export var animation_preset: PagePreset = PagePreset.CUSTOM : set = _on_preset_changed
@export_group("Manual Configuration")
## The AnimationPlayer node to store the generated animations.
@export var anim_player: AnimationPlayer
## Duration of the page turn animation in seconds.
@export var anim_duration: float = 0.75
@export_subgroup("Paper Physics")
## Stiffness of the material. 0.5 = Rubber, 5.0 = Wood.
@export_range(0.5, 5.0, 0.1) var paper_stiffness: float = 2.0
## Bend angle during the lift phase (Negative = Tip drags down).
@export_range(-180.0, 180.0) var lift_bend: float = -10.0
## Bend angle during the landing phase (Negative = Tip floats up).
@export_range(-180.0, 180.0) var land_bend: float = -8.0
@export_subgroup("Curl Effect")
## Which part of the page initiates the movement.
@export var curl_mode: CurlMode = CurlMode.TOP_CORNER_FIRST
## Time delay for the trailing corner (0.0 = None, 1.0 = High lag).
@export_range(0.0, 1.0, 0.05) var curl_lag: float = 0.8
@export_subgroup("Shadow FX")
## Create a dynamic shadow behind the page (Background Shadow).
@export var enable_shadow: bool = false
## The gradient texture used for the back shadow.
@export var shadow_gradient: GradientTexture2D
@export_subgroup("Fine Timing")
## Normalized time (0.0 - 1.0) for the peak lift position.
@export_range(0.05, 0.45, 0.01) var timing_peak_lift: float = 0.15
## Normalized time (0.0 - 1.0) for the landing contact.
@export_range(0.55, 0.95, 0.01) var timing_peak_land: float = 0.85
@export var generate_anims_btn: bool = false : set = _on_anim_pressed
# ==============================================================================
# RUNTIME INITIALIZATION
# ==============================================================================
func _ready():
self.z_index = 10
if animation_preset == PagePreset.CUSTOM:
_save_state_to_cache()
func rebuild(current_page_size: Vector2 = Vector2.ZERO) -> void:
if not anim_player: return
_clean_previous_rig()
_create_rig_logic(current_page_size)
_generate_animations_logic()
# ==============================================================================
# PRESET LOGIC
# ==============================================================================
func _on_preset_changed(val):
if animation_preset == PagePreset.CUSTOM:
_save_state_to_cache()
animation_preset = val
if val == PagePreset.CUSTOM:
if not _custom_cache.is_empty():
_load_state_from_cache()
print("[PageRigger] Restored Custom Settings.")
notify_property_list_changed()
return
# Defaults
curl_mode = CurlMode.BOTTOM_CORNER_FIRST
curl_lag = 0.3
enable_shadow = false
anim_duration = 0.75
match val:
PagePreset.DEFAULT:
paper_stiffness = 2.0; lift_bend = -15.0; land_bend = 5.0
curl_mode = CurlMode.TOP_CORNER_FIRST; curl_lag = 0.5
anim_duration = 0.75; timing_peak_lift = 0.15; timing_peak_land = 0.85
PagePreset.STANDARD_PAPER:
paper_stiffness = 2.5; lift_bend = -12.0; land_bend = 3.0
curl_mode = CurlMode.TOP_CORNER_FIRST; curl_lag = 0.4
anim_duration = 0.65; timing_peak_lift = 0.12; timing_peak_land = 0.88
PagePreset.HEAVY_GRIMOIRE:
paper_stiffness = 4.0; lift_bend = -3.0; land_bend = 1.0
curl_mode = CurlMode.STRAIGHT; curl_lag = 0.1
anim_duration = 1.1; timing_peak_lift = 0.25; timing_peak_land = 0.75
PagePreset.LIGHT_MAGAZINE:
paper_stiffness = 0.8; lift_bend = -16.0; land_bend = 0.0
curl_mode = CurlMode.BOTTOM_CORNER_FIRST; curl_lag = 0.6
anim_duration = 0.8; timing_peak_lift = 0.10; timing_peak_land = 0.92
PagePreset.OLD_SCROLL:
paper_stiffness = 1.8; lift_bend = -20.0; land_bend = 8.0
curl_mode = CurlMode.TOP_CORNER_FIRST; curl_lag = 0.9
anim_duration = 0.9; timing_peak_lift = 0.18; timing_peak_land = 0.82
PagePreset.RIGID_BOARD:
paper_stiffness = 5.0; lift_bend = 0.0; land_bend = 0.0
curl_mode = CurlMode.STRAIGHT; curl_lag = 0.0
anim_duration = 0.8; timing_peak_lift = 0.2; timing_peak_land = 0.8
PagePreset.WET_CLOTH:
paper_stiffness = 0.3; lift_bend = -28.0; land_bend = -0.0
curl_mode = CurlMode.BOTTOM_CORNER_FIRST; curl_lag = 0.6
anim_duration = 1.3; timing_peak_lift = 0.2; timing_peak_land = 0.95
PagePreset.PLASTIC_SHEET:
paper_stiffness = 3.5; lift_bend = -12.0; land_bend = 12.0
curl_mode = CurlMode.TOP_CORNER_FIRST; curl_lag = 0.2
anim_duration = 0.5; timing_peak_lift = 0.08; timing_peak_land = 0.92
PagePreset.METAL_PLATE:
paper_stiffness = 5.0; lift_bend = 0.0; land_bend = 0.0
curl_mode = CurlMode.STRAIGHT; curl_lag = 0.0
anim_duration = 1.4; timing_peak_lift = 0.15; timing_peak_land = 0.98
notify_property_list_changed()
if anim_player and skeleton != NodePath(""):
_generate_animations_logic()
print("[PageRigger] Preset Applied: ", PagePreset.keys()[val])
func _save_state_to_cache():
_custom_cache = {
"stiffness": paper_stiffness, "lift": lift_bend, "land": land_bend,
"curl_m": curl_mode, "curl_l": curl_lag,
"t_lift": timing_peak_lift, "t_land": timing_peak_land,
"dur": anim_duration, "shadow": enable_shadow
}
func _load_state_from_cache():
paper_stiffness = _custom_cache.get("stiffness", 1.5)
lift_bend = _custom_cache.get("lift", -30.0)
land_bend = _custom_cache.get("land", -15.0)
curl_mode = _custom_cache.get("curl_m", CurlMode.BOTTOM_CORNER_FIRST)
curl_lag = _custom_cache.get("curl_l", 0.3)
timing_peak_lift = _custom_cache.get("t_lift", 0.15)
timing_peak_land = _custom_cache.get("t_land", 0.85)
anim_duration = _custom_cache.get("dur", 1.0)
enable_shadow = false # Force disable shadow
# ==============================================================================
# RIGGING LOGIC
# ==============================================================================
func _calculate_polygon_rect() -> Rect2:
if polygon.size() == 0:
return Rect2(0,0,0,0)
var min_v = polygon[0]
var max_v = polygon[0]
for v in polygon:
min_v.x = min(min_v.x, v.x)
min_v.y = min(min_v.y, v.y)
max_v.x = max(max_v.x, v.x)
max_v.y = max(max_v.y, v.y)
return Rect2(min_v, max_v - min_v)
func _create_rig_logic(current_page_size: Vector2 = Vector2.ZERO):
self.z_index = 10
var original_size = Vector2(512, 820)
var tex_size: Vector2 = Vector2.ZERO
if current_page_size != Vector2.ZERO:
tex_size = current_page_size
elif texture:
tex_size = texture.get_size()
if tex_size == Vector2.ZERO:
tex_size = original_size
var step_x = tex_size.x / subdivision_x
var step_y = tex_size.y / subdivision_y
# Prepare Gradient Texture for Background Shadow
var applied_shadow_tex: Texture2D = null
if not shadow_gradient:
shadow_gradient = preload("uid://rm7bporlv3cf")
var dup = shadow_gradient.duplicate()
if dup is GradientTexture2D:
dup.width = int(tex_size.x)
applied_shadow_tex = dup
# --- 0. BACKGROUND SHADOW ---
if enable_shadow:
var shadow = Polygon2D.new()
shadow.name = SHADOW_NAME
shadow.z_index = -1
if applied_shadow_tex:
shadow.texture = applied_shadow_tex
shadow.color = Color.WHITE
else:
shadow.color = Color(0, 0, 0, 0.5)
var margin = 4.0
shadow.polygon = PackedVector2Array([
Vector2(margin, margin), Vector2(tex_size.x - margin, margin),
Vector2(tex_size.x - margin, tex_size.y - margin), Vector2(margin, tex_size.y - margin)
])
shadow.uv = shadow.polygon
add_child(shadow)
# --- 1. MESH & UV ---
var new_uvs = PackedVector2Array()
for y in range(subdivision_y + 1):
for x in range(subdivision_x + 1):
new_uvs.append(Vector2(x * step_x, y * step_y))
self.uv = new_uvs
self.polygon = new_uvs
var new_polygons = []
var rc = subdivision_x + 1
for y in range(subdivision_y):
for x in range(subdivision_x):
var i = y * rc + x
new_polygons.append(PackedInt32Array([i, i + 1, i + rc + 1, i + rc]))
self.polygons = new_polygons
# --- 2. SKELETON ---
var sk = Skeleton2D.new()
sk.name = SKELETON_NAME
add_child(sk)
self.skeleton = NodePath(SKELETON_NAME)
# --- 3. BONES (Structured Hierarchy) ---
for y in range(subdivision_y + 1):
var parent_bone: Bone2D = null
for x in range(subdivision_x + 1):
var b = Bone2D.new()
b.name = "Bone_%d_%d" % [x, y]
b.set_autocalculate_length_and_angle(false)
b.set_length(step_x)
if x == 0:
# Root bone (Spine)
sk.add_child(b)
b.position = Vector2(0, y * step_y)
else:
# Child bone
if parent_bone:
parent_bone.add_child(b)
b.position = Vector2(step_x, 0)
b.set_rest(b.transform)
parent_bone = b
# --- 4. WEIGHTS (Gradient Skinning) ---
_apply_weights_to_polygon(self, sk)
queue_redraw()
notify_property_list_changed()
func _apply_weights_to_polygon(poly: Polygon2D, sk: Skeleton2D):
poly.clear_bones()
var bone_map = {}
for y in range(subdivision_y + 1):
for x in range(subdivision_x + 1):
var bname = "Bone_%d_%d" % [x, y]
var bone_node = sk.find_child(bname, true, false)
if bone_node:
bone_map[bname] = bone_node.get_path()
var vertex_count = poly.polygon.size()
var weights_per_bone = {}
for bpath in bone_map.values():
var w_arr = PackedFloat32Array()
w_arr.resize(vertex_count)
w_arr.fill(0.0)
weights_per_bone[bpath] = w_arr
var vert_idx = 0
for y in range(subdivision_y + 1):
for x in range(subdivision_x + 1):
var primary_name = "Bone_%d_%d" % [x, y]
var prev_name = "Bone_%d_%d" % [x - 1, y]
var next_name = "Bone_%d_%d" % [x + 1, y]
var primary_path = bone_map.get(primary_name)
var prev_path = bone_map.get(prev_name)
var next_path = bone_map.get(next_name)
var w_center = 0.7
var w_neighbor = 0.15
if primary_path: weights_per_bone[primary_path][vert_idx] += w_center
if prev_path: weights_per_bone[prev_path][vert_idx] += w_neighbor
else: weights_per_bone[primary_path][vert_idx] += w_neighbor
if next_path: weights_per_bone[next_path][vert_idx] += w_neighbor
else: weights_per_bone[primary_path][vert_idx] += w_neighbor
vert_idx += 1
for bpath in weights_per_bone:
poly.add_bone(bpath, weights_per_bone[bpath])
# ==============================================================================
# ANIMATION LOGIC
# ==============================================================================
func _generate_animations_logic():
var library: AnimationLibrary
if anim_player.has_animation_library(""): library = anim_player.get_animation_library("")
else: library = AnimationLibrary.new(); anim_player.add_animation_library("", library)
_create_single_anim(library, "turn_flexible_page", false, false)
_create_single_anim(library, "turn_rigid_page", true, false)
_create_single_anim(library, "turn_flexible_page_mirror", false, true)
_create_single_anim(library, "turn_rigid_page_mirror", true, true)
notify_property_list_changed()
func _create_single_anim(library: AnimationLibrary, anim_name: String, is_rigid: bool, is_mirror: bool):
var anim = Animation.new()
anim.length = anim_duration
anim.step = 0.01
if library.has_animation(anim_name): library.remove_animation(anim_name)
library.add_animation(anim_name, anim)
var sk_node = find_child(SKELETON_NAME, true, false)
if not sk_node: return
var my_path = anim_player.get_node(anim_player.root_node).get_path_to(self)
var visible_col = Color(1, 1, 1, 1)
var invisible_col = Color(1, 1, 1, 0)
var faded_col = Color(1, 1, 1, 0.6)
var t_mid = anim_duration * 0.5
var t_end_snap = anim_duration * 0.95
# ==========================================================================
# 1. VISIBILITY & Z-INDEX
# ==========================================================================
var z_track = anim.add_track(Animation.TYPE_VALUE)
anim.track_set_path(z_track, str(my_path) + ":z_index")
anim.track_set_interpolation_type(z_track, Animation.INTERPOLATION_NEAREST)
anim.track_insert_key(z_track, 0.0, 10)
anim.track_insert_key(z_track, anim_duration * 0.15, 25)
anim.track_insert_key(z_track, anim_duration * 0.65, 10)
# ==========================================================================
# 2. BACKGROUND SHADOW
# ==========================================================================
var shadow_node = find_child(SHADOW_NAME, true, false)
if shadow_node and enable_shadow:
var shadow_path = anim_player.get_node(anim_player.root_node).get_path_to(shadow_node)
var t_scale = anim.add_track(Animation.TYPE_VALUE)
anim.track_set_path(t_scale, str(shadow_path) + ":scale")
anim.track_set_interpolation_type(t_scale, Animation.INTERPOLATION_CUBIC)
var t_mod = anim.add_track(Animation.TYPE_VALUE)
anim.track_set_path(t_mod, str(shadow_path) + ":modulate")
var s_start = Vector2(-1.0, 1.0) if is_mirror else Vector2(1.0, 1.0)
var s_end = Vector2(1.0, 1.0) if is_mirror else Vector2(-1.0, 1.0)
anim.track_insert_key(t_scale, 0.0, s_start)
anim.track_insert_key(t_mod, 0.0, invisible_col)
anim.track_insert_key(t_mod, anim_duration * 0.1, visible_col)
anim.track_insert_key(t_scale, t_mid, Vector2(0.01, 1.0))
anim.track_insert_key(t_mod, t_mid, faded_col)
anim.track_insert_key(t_scale, t_end_snap, s_end)
anim.track_insert_key(t_scale, anim_duration, s_end)
anim.track_insert_key(t_mod, t_end_snap, invisible_col)
anim.track_insert_key(t_mod, anim_duration, invisible_col)
# ==========================================================================
# 3. BONE ANIMATION
# ==========================================================================
for y in range(subdivision_y + 1):
var row_factor = 1.0
if not is_rigid and curl_mode != CurlMode.STRAIGHT:
var y_ratio = float(y) / float(max(1, subdivision_y))
if curl_mode == CurlMode.TOP_CORNER_FIRST:
row_factor = lerp(1.0, 1.0 - curl_lag, y_ratio)
elif curl_mode == CurlMode.BOTTOM_CORNER_FIRST:
row_factor = lerp(1.0 - curl_lag, 1.0, y_ratio)
var time_offset = (1.0 - row_factor) * (anim_duration * 0.1)
for x in range(subdivision_x + 1):
var bone_name = "Bone_%d_%d" % [x, y]
var bone = sk_node.find_child(bone_name, true, false)
if not bone: continue
var t_idx = anim.add_track(Animation.TYPE_VALUE)
var path = anim_player.get_node(anim_player.root_node).get_path_to(bone)
anim.track_set_path(t_idx, str(path) + ":rotation_degrees")
anim.track_set_interpolation_type(t_idx, Animation.INTERPOLATION_CUBIC)
var deg_flat_right = 0.0; var deg_flat_left = -179.9; var deg_mid = -90.0
if is_rigid:
if x == 0:
var s = deg_flat_left if is_mirror else deg_flat_right
var e = deg_flat_right if is_mirror else deg_flat_left
anim.track_insert_key(t_idx, 0.0, s)
anim.track_insert_key(t_idx, anim_duration * 0.5, deg_mid)
anim.track_insert_key(t_idx, anim_duration, e)
else:
anim.track_insert_key(t_idx, 0.0, 0.0)
anim.track_insert_key(t_idx, anim_duration, 0.0)
else:
var x_ratio = float(x) / float(subdivision_x)
var influence = pow(x_ratio, paper_stiffness)
var t_lift = clamp((anim_duration * timing_peak_lift) + time_offset, 0.0, (anim_duration * 0.5) - 0.05)
var t_mid_bone = anim_duration * 0.5
var t_land = clamp((anim_duration * timing_peak_land) - time_offset, t_mid_bone + 0.05, anim_duration)
if x == 0:
# ROOT BONE
var s = deg_flat_left if is_mirror else deg_flat_right
var e = deg_flat_right if is_mirror else deg_flat_left
var sl = -15.0 * row_factor
if is_mirror: sl = deg_flat_left - sl
var slt = lerp(-90.0, -180.0, timing_peak_land)
if is_mirror: slt = lerp(-90.0, 0.0, timing_peak_land)
anim.track_insert_key(t_idx, 0.0, s)
anim.track_insert_key(t_idx, t_lift, sl)
anim.track_insert_key(t_idx, t_mid_bone, deg_mid)
anim.track_insert_key(t_idx, t_land, slt)
var t_settle = lerp(t_land, anim_duration, 0.7)
var s_settle = lerp(slt, e, 0.85)
anim.track_insert_key(t_idx, t_settle, s_settle)
anim.track_insert_key(t_idx, anim_duration, e)
else:
# SURFACE BONES (CURVED)
var bm = -1.0 if is_mirror else 1.0
anim.track_insert_key(t_idx, 0.0, 0.0)
anim.track_insert_key(t_idx, t_lift, lift_bend * row_factor * bm * influence)
# REMOVED FORCED 0.0 AT MIDPOINT FOR ORGANIC CURVE
var val_land = land_bend * row_factor * bm * influence
anim.track_insert_key(t_idx, t_land, val_land)
var t_settle = lerp(t_land, anim_duration, 0.75)
anim.track_insert_key(t_idx, t_settle, val_land * 0.15)
anim.track_insert_key(t_idx, anim_duration, 0.0)
# ==========================================================================
# 4. MAIN POLYGON SCALE ("SQUASH & STRETCH")
# ==========================================================================
if not is_rigid:
var t_main_scale = anim.add_track(Animation.TYPE_VALUE)
anim.track_set_path(t_main_scale, str(my_path) + ":scale")
anim.track_set_interpolation_type(t_main_scale, Animation.INTERPOLATION_LINEAR)
var squash_x = 0.88
anim.track_insert_key(t_main_scale, 0.0, Vector2(1, 1))
anim.track_insert_key(t_main_scale, t_mid, Vector2(1, 1))
anim.track_insert_key(t_main_scale, t_mid + (anim_duration * 0.1), Vector2(squash_x, 1))
anim.track_insert_key(t_main_scale, anim_duration * 0.85, Vector2(1, 1))
anim.track_insert_key(t_main_scale, anim_duration, Vector2(1, 1))
var method_track = anim.add_track(Animation.TYPE_METHOD)
anim.track_set_path(method_track, str(my_path))
anim.track_insert_key(method_track, anim_duration * 0.5, {"method": "_trigger_midpoint", "args": []})
anim.track_insert_key(method_track, anim_duration, {"method": "_trigger_end", "args": []})
# ==============================================================================
# HELPER FUNCTIONS
# ==============================================================================
func _trigger_midpoint(): emit_signal("change_page_requested")
func _trigger_end(): emit_signal("end_animation")
func _on_generate_pressed(val):
if val:
rebuild_all=false
_clean_previous_rig()
_create_rig_logic()
_generate_animations_logic()
func _on_anim_pressed(val):
if val:
generate_anims_btn=false
if anim_player and skeleton!=NodePath(""):
_generate_animations_logic()
func _clean_previous_rig():
for c in get_children():
remove_child(c)
c.free()
var old_shadow = find_child(SHADOW_NAME, true, false)
if old_shadow: old_shadow.free()
clear_bones()
skeleton = NodePath("")

View File

@@ -0,0 +1 @@
uid://ce5ib2f4qff24

View File

@@ -15,8 +15,8 @@ var _enable_state_machine: bool = true
@export var anim_player: AnimationPlayer
@export_group("Entities")
enum EntityType { HUMANOID, ANIMAL }
@export var entity_type: EntityType = EntityType.HUMANOID
enum EntityType { FARMER, CITIZEN_WALKER, CITIZEN_SITTER, CAT, CROW, FOX, GOAT, RACOON, WAGYU }
@export var entity_type: EntityType = EntityType.FARMER
@export var entity_name: String = ""
@export var allowed_biomes: Array[String] = []
@export_range(0.0, 100.0, 0.1) var spawn_uniqueness: float = 1.0
@@ -32,7 +32,8 @@ func _ready() -> void:
toggle_enable_state_machine()
func toggle_enable_state_machine() -> void:
state_machine.enable = _enable_state_machine
if state_machine:
state_machine.enable = _enable_state_machine
func _physics_process(delta: float) -> void:
if !_enable_state_machine:

View File

@@ -0,0 +1,38 @@
extends AIBase
class_name AICat
@export_group("Cat Colors")
@export var mesh: MeshInstance3D
@export var fur_colors: Array[Color] = []
@export var eye_colors: Array[Color] = []
@export var fur_material_index: int = 0
@export var eye_material_index: int = 1
func _ready() -> void:
super._ready()
_apply_random_color()
func _apply_random_color() -> void:
if fur_colors.is_empty() or eye_colors.is_empty():
return
if not mesh or not mesh.mesh:
return
var max_index = min(fur_colors.size(), eye_colors.size())
var random_idx = randi() % max_index
_override_material_color(mesh, fur_material_index, fur_colors[random_idx])
_override_material_color(mesh, eye_material_index, eye_colors[random_idx])
func _override_material_color(mesh_node: MeshInstance3D, surface_idx: int, color: Color) -> void:
if surface_idx < 0 or surface_idx >= mesh_node.mesh.get_surface_count():
return
var mat = mesh_node.mesh.surface_get_material(surface_idx)
if mat and mat is StandardMaterial3D:
var new_mat = mat.duplicate() as StandardMaterial3D
new_mat.albedo_color = color
mesh_node.set_surface_override_material(surface_idx, new_mat)

View File

@@ -0,0 +1 @@
uid://cx67xas1hxv3x

View File

@@ -2,12 +2,63 @@
[ext_resource type="PackedScene" uid="uid://clx701xdwelgx" path="res://core/ai/agents/base/ai_base.tscn" id="1_85o24"]
[ext_resource type="Script" uid="uid://d3hy70ec8vqo5" path="res://core/ai/framework/run_animation_state.gd" id="2_6mu8r"]
[ext_resource type="Script" uid="uid://cx67xas1hxv3x" path="res://core/ai/agents/cat/ai_cat.gd" id="2_cat_script"]
[ext_resource type="PackedScene" uid="uid://c5rccx22gs6jt" path="res://core/ai/agents/cat/Cat_rig.fbx" id="2_rohxe"]
[ext_resource type="Script" uid="uid://bngfthvt04ivv" path="res://core/ai/framework/patrol_state.gd" id="3_0jm3k"]
[ext_resource type="Script" uid="uid://dty1p02kqviwf" path="res://core/ai/framework/sit_state.gd" id="3_scd7t"]
[ext_resource type="Shader" uid="uid://d0ch5ofrgf7y6" path="res://core/daynight/trunk_shader.gdshader" id="7_rxsfd"]
[node name="AiCat" unique_id=1228675528 node_paths=PackedStringArray("anim_player") instance=ExtResource("1_85o24")]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_1rb57"]
render_priority = 0
shader = ExtResource("7_rxsfd")
shader_parameter/albedo_color = Color(0.7389186, 0.53468716, 0.19165063, 1)
shader_parameter/use_texture = true
shader_parameter/uv_scale = Vector2(1, 1)
shader_parameter/palette_shift_y = 0.0
shader_parameter/gradient_start_y = 0.0
shader_parameter/gradient_end_y = 10.0
shader_parameter/light_steps = 3.0
shader_parameter/step_softness = 0.1
shader_parameter/shadow_color = Color(0.4, 0.4, 0.6, 1)
shader_parameter/shadow_offset = 0.0
shader_parameter/cast_shadow_strength = 0.6
shader_parameter/use_ghibli_glint = true
shader_parameter/glint_color = Color(1, 0.95, 0.85, 1)
shader_parameter/glint_intensity = 1.0
shader_parameter/glint_sharpness = 32.0
shader_parameter/emission_color = Color(0, 0, 0, 1)
shader_parameter/emission_energy = 0.0
[sub_resource type="ShaderMaterial" id="ShaderMaterial_42ie3"]
render_priority = 0
shader = ExtResource("7_rxsfd")
shader_parameter/albedo_color = Color(0.099985994, 0.09998601, 0.099985965, 1)
shader_parameter/use_texture = true
shader_parameter/uv_scale = Vector2(1, 1)
shader_parameter/palette_shift_y = 0.0
shader_parameter/gradient_start_y = 0.0
shader_parameter/gradient_end_y = 10.0
shader_parameter/light_steps = 3.0
shader_parameter/step_softness = 0.1
shader_parameter/shadow_color = Color(0.4, 0.4, 0.6, 1)
shader_parameter/shadow_offset = 0.0
shader_parameter/cast_shadow_strength = 0.6
shader_parameter/use_ghibli_glint = true
shader_parameter/glint_color = Color(1, 0.95, 0.85, 1)
shader_parameter/glint_intensity = 1.0
shader_parameter/glint_sharpness = 32.0
shader_parameter/emission_color = Color(0, 0, 0, 1)
shader_parameter/emission_energy = 0.0
[node name="AiCat" unique_id=1228675528 node_paths=PackedStringArray("mesh", "anim_player") instance=ExtResource("1_85o24")]
script = ExtResource("2_cat_script")
mesh = NodePath("Cat_rig/Rig_Cat/Skeleton3D/Cat")
fur_colors = Array[Color]([Color(0.8716863, 0.762116, 0.1809479, 1)])
eye_colors = Array[Color]([Color(0.12955844, 0.12955847, 0.12955844, 1), Color(0.6901961, 0.3019608, 0.12156863, 1), Color(0.6830768, 0.6830776, 0.68307686, 1), Color(0.6273405, 0.15743047, 0, 1)])
fur_material_index = 0
eye_material_index = 1
anim_player = NodePath("Cat_rig/AnimationPlayer")
entity_type = 1
entity_type = 3
entity_name = "Cat"
[node name="StateMachine" parent="." index="1" unique_id=1286404264 node_paths=PackedStringArray("initial_state")]
@@ -17,9 +68,16 @@ initial_state = NodePath("IdleState")
script = ExtResource("2_6mu8r")
state_id = &"idle"
next_state_id = &"patrol"
random_next_state_ids = Array[StringName]([&"patrol", &"sit"])
animation_name = "Cat_Idle"
[node name="PatrolState" type="Node" parent="StateMachine" index="1" unique_id=1861645340]
[node name="SitState" type="Node" parent="StateMachine" index="1" unique_id=860354787]
script = ExtResource("3_scd7t")
state_id = &"sit"
next_state_id = &"idle"
animation_name = "Cat_Sit"
[node name="PatrolState" type="Node" parent="StateMachine" index="2" unique_id=1861645340]
script = ExtResource("3_0jm3k")
state_id = &"patrol"
next_state_id = &"idle"
@@ -28,7 +86,7 @@ exit_on_action_finished = true
[node name="Cat_rig" parent="." index="3" unique_id=1332997618 instance=ExtResource("2_rohxe")]
[node name="Skeleton3D" parent="Cat_rig/Rig_Cat" parent_id_path=PackedInt32Array(1332997618, 1292226211) index="0" unique_id=807490174]
[node name="Skeleton3D" parent="Cat_rig/Rig_Cat" parent_id_path=PackedInt32Array(1332997618, 1024066488) index="0" unique_id=1455145313]
bones/1/position = Vector3(1.6719584e-08, 0.23547882, 0.34218493)
bones/1/rotation = Quaternion(0.12769094, -0.6954821, -0.12769029, 0.69548184)
bones/2/rotation = Quaternion(-1.5819447e-07, -1.9079575e-07, -0.5904159, 0.8070992)
@@ -57,4 +115,8 @@ bones/27/rotation = Quaternion(-8.140452e-08, 1.1560887e-07, -0.47071794, 0.8822
bones/28/position = Vector3(0.18089616, -0.000116375166, 0.011642809)
bones/28/rotation = Quaternion(4.5638826e-05, -8.8217595e-05, 0.5290293, 0.84860367)
[node name="Cat" parent="Cat_rig/Rig_Cat/Skeleton3D" index="0" unique_id=869144045]
surface_material_override/0 = SubResource("ShaderMaterial_1rb57")
surface_material_override/1 = SubResource("ShaderMaterial_42ie3")
[editable path="Cat_rig"]

View File

@@ -7,18 +7,22 @@
[node name="AiCrow" unique_id=1228675528 node_paths=PackedStringArray("anim_player") instance=ExtResource("1_tx3nx")]
anim_player = NodePath("Crow_rig/AnimationPlayer")
entity_type = 4
entity_name = "Crow"
[node name="StateMachine" parent="." index="1" unique_id=1286404264 node_paths=PackedStringArray("initial_state")]
initial_state = NodePath("WaitTrainState")
[node name="WaitTrainState" type="Node" parent="StateMachine" index="0" unique_id=1000000000]
script = ExtResource("3_wait")
fly_distance_threshold = 10.0
state_id = &"wait"
next_state_id = &"fly"
animation_name = "Idle_Crow"
[node name="FlyAwayState" type="Node" parent="StateMachine" index="1" unique_id=1000000001]
script = ExtResource("4_fly")
destroy_after_seconds = 20.0
state_id = &"fly"
animation_name = "Fly_Crow"

View File

@@ -5,9 +5,34 @@
[ext_resource type="PackedScene" uid="uid://4y4tffc723lg" path="res://core/ai/agents/fox/Fox_rig.fbx" id="2_xaafp"]
[ext_resource type="Script" uid="uid://bngfthvt04ivv" path="res://core/ai/framework/patrol_state.gd" id="3_d1sp2"]
[ext_resource type="Script" uid="uid://b5y4u0itec8g1" path="res://core/ai/framework/run_state.gd" id="4_d1sp2"]
[ext_resource type="Shader" uid="uid://d0ch5ofrgf7y6" path="res://core/daynight/trunk_shader.gdshader" id="6_oqxvo"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_4pdxi"]
render_priority = 0
shader = ExtResource("6_oqxvo")
shader_parameter/albedo_color = Color(0.5408599, 0.27705142, 0.12841594, 1)
shader_parameter/use_texture = true
shader_parameter/uv_scale = Vector2(3, 3)
shader_parameter/palette_shift_y = 0.0
shader_parameter/gradient_start_y = 0.0
shader_parameter/gradient_end_y = 1.5
shader_parameter/light_steps = 3.0
shader_parameter/step_softness = 0.1
shader_parameter/shadow_color = Color(0.4, 0.4, 0.6, 1)
shader_parameter/shadow_offset = 0.0
shader_parameter/cast_shadow_strength = 0.6
shader_parameter/use_ghibli_glint = true
shader_parameter/glint_color = Color(1, 0.95, 0.85, 1)
shader_parameter/glint_intensity = 1.0
shader_parameter/glint_sharpness = 32.0
shader_parameter/emission_color = Color(0, 0, 0, 1)
shader_parameter/emission_energy = 0.0
[node name="AiFox" unique_id=1228675528 node_paths=PackedStringArray("anim_player") instance=ExtResource("1_m3efo")]
navigation_layers = 4
anim_player = NodePath("Fox_rig/AnimationPlayer")
entity_type = 5
entity_name = "Fox"
[node name="StateMachine" parent="." index="1" unique_id=1286404264 node_paths=PackedStringArray("initial_state")]
initial_state = NodePath("IdleState")
@@ -35,7 +60,7 @@ exit_on_action_finished = true
[node name="Fox_rig" parent="." index="3" unique_id=2044859181 instance=ExtResource("2_xaafp")]
[node name="Skeleton3D" parent="Fox_rig/Rig_Fox" parent_id_path=PackedInt32Array(2044859181, 1371677834) index="0" unique_id=625291101]
[node name="Skeleton3D" parent="Fox_rig/Rig_Fox" parent_id_path=PackedInt32Array(2044859181, 975246732) index="0" unique_id=1559174379]
bones/1/position = Vector3(1.2443564e-08, 0.24551632, 0.408434)
bones/1/rotation = Quaternion(0.12769088, -0.6954821, -0.12769023, 0.69548184)
bones/2/rotation = Quaternion(-1.492881e-07, -1.7862074e-07, -0.5904159, 0.8070992)
@@ -58,4 +83,7 @@ bones/26/rotation = Quaternion(-3.3980676e-05, -0.00016874354, 0.9618461, -0.273
bones/27/rotation = Quaternion(-1.9324155e-08, 4.5031282e-08, -0.47071794, 0.8822838)
bones/28/rotation = Quaternion(4.549153e-05, -8.8271285e-05, 0.5290293, 0.84860367)
[node name="fox" parent="Fox_rig/Rig_Fox/Skeleton3D" index="0" unique_id=2042924802]
surface_material_override/1 = SubResource("ShaderMaterial_4pdxi")
[editable path="Fox_rig"]

View File

@@ -4,9 +4,55 @@
[ext_resource type="PackedScene" uid="uid://cumnmnbdjbgas" path="res://core/ai/agents/goat/Goat_rig.fbx" id="2_oxwbf"]
[ext_resource type="Script" uid="uid://d3hy70ec8vqo5" path="res://core/ai/framework/run_animation_state.gd" id="2_ucoix"]
[ext_resource type="Script" uid="uid://bngfthvt04ivv" path="res://core/ai/framework/patrol_state.gd" id="3_lqqd8"]
[ext_resource type="Shader" uid="uid://d0ch5ofrgf7y6" path="res://core/daynight/trunk_shader.gdshader" id="5_lqqd8"]
[ext_resource type="Material" uid="uid://cn20mp8ep3yxu" path="res://tgcc/chunk/material/wires.tres" id="6_xcxu7"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_xcxu7"]
render_priority = 0
shader = ExtResource("5_lqqd8")
shader_parameter/albedo_color = Color(0.46774077, 0.51844496, 0.510305, 1)
shader_parameter/use_texture = true
shader_parameter/uv_scale = Vector2(3, 3)
shader_parameter/palette_shift_y = 0.0
shader_parameter/gradient_start_y = 0.0
shader_parameter/gradient_end_y = 1.5
shader_parameter/light_steps = 3.0
shader_parameter/step_softness = 0.1
shader_parameter/shadow_color = Color(0.4, 0.4, 0.6, 1)
shader_parameter/shadow_offset = 0.0
shader_parameter/cast_shadow_strength = 0.6
shader_parameter/use_ghibli_glint = true
shader_parameter/glint_color = Color(1, 0.95, 0.85, 1)
shader_parameter/glint_intensity = 1.0
shader_parameter/glint_sharpness = 32.0
shader_parameter/emission_color = Color(0, 0, 0, 1)
shader_parameter/emission_energy = 0.0
[sub_resource type="ShaderMaterial" id="ShaderMaterial_lqqd8"]
render_priority = 0
shader = ExtResource("5_lqqd8")
shader_parameter/albedo_color = Color(0.49370736, 0.43829006, 0.29924837, 1)
shader_parameter/use_texture = true
shader_parameter/uv_scale = Vector2(3, 3)
shader_parameter/palette_shift_y = 0.0
shader_parameter/gradient_start_y = 0.0
shader_parameter/gradient_end_y = 1.5
shader_parameter/light_steps = 3.0
shader_parameter/step_softness = 0.1
shader_parameter/shadow_color = Color(0.4, 0.4, 0.6, 1)
shader_parameter/shadow_offset = 0.0
shader_parameter/cast_shadow_strength = 0.6
shader_parameter/use_ghibli_glint = true
shader_parameter/glint_color = Color(1, 0.95, 0.85, 1)
shader_parameter/glint_intensity = 1.0
shader_parameter/glint_sharpness = 32.0
shader_parameter/emission_color = Color(0, 0, 0, 1)
shader_parameter/emission_energy = 0.0
[node name="AiGoat" unique_id=1228675528 node_paths=PackedStringArray("anim_player") instance=ExtResource("1_f7hhh")]
anim_player = NodePath("Goat_rig/AnimationPlayer")
entity_type = 6
entity_name = "Goat"
[node name="StateMachine" parent="." index="1" unique_id=1286404264 node_paths=PackedStringArray("initial_state")]
initial_state = NodePath("IdleState")
@@ -26,7 +72,7 @@ exit_on_action_finished = true
[node name="Goat_rig" parent="." index="3" unique_id=1336829719 instance=ExtResource("2_oxwbf")]
[node name="Skeleton3D" parent="Goat_rig/Rig_Goat" parent_id_path=PackedInt32Array(1336829719, 1896192446) index="0" unique_id=1573667924]
[node name="Skeleton3D" parent="Goat_rig/Rig_Goat" parent_id_path=PackedInt32Array(1336829719, 1679574624) index="0" unique_id=1406072579]
bones/1/position = Vector3(-8.352713e-09, 0.36986786, 0.8951362)
bones/1/rotation = Quaternion(0.1276911, -0.695482, -0.12769035, 0.69548184)
bones/2/rotation = Quaternion(-8.7811394e-08, -9.458198e-08, -0.5904155, 0.80709946)
@@ -49,4 +95,10 @@ bones/26/rotation = Quaternion(2.713829e-07, 8.5825764e-07, 0.9653876, -0.260819
bones/27/rotation = Quaternion(-3.8362674e-07, 5.6200027e-09, -0.3680436, 0.92980856)
bones/28/rotation = Quaternion(-0.00015313082, -7.842175e-05, 0.45790914, 0.888999)
[node name="Goat" parent="Goat_rig/Rig_Goat/Skeleton3D" index="0" unique_id=1545212389]
surface_material_override/0 = SubResource("ShaderMaterial_xcxu7")
surface_material_override/1 = SubResource("ShaderMaterial_lqqd8")
surface_material_override/2 = ExtResource("6_xcxu7")
surface_material_override/3 = ExtResource("6_xcxu7")
[editable path="Goat_rig"]

Binary file not shown.

View File

@@ -0,0 +1,44 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://b3j2dbcqwodx1"
path="res://.godot/imported/Farmer1.fbx-c6b3fa9e901f9ab5b38c67c1343eab85.scn"
[deps]
source_file="res://core/ai/agents/human/Farmer1.fbx"
dest_files=["res://.godot/imported/Farmer1.fbx-c6b3fa9e901f9ab5b38c67c1343eab85.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=true
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
fbx/importer=0
fbx/allow_geometry_helper_nodes=false
fbx/embedded_image_handling=1
fbx/naming_version=2

Binary file not shown.

View File

@@ -0,0 +1,44 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://c5x3ycaxixpxy"
path="res://.godot/imported/Farmer2.fbx-da830fcedaed7d46b77458a4c0e1f611.scn"
[deps]
source_file="res://core/ai/agents/human/Farmer2.fbx"
dest_files=["res://.godot/imported/Farmer2.fbx-da830fcedaed7d46b77458a4c0e1f611.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=true
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
fbx/importer=0
fbx/allow_geometry_helper_nodes=false
fbx/embedded_image_handling=1
fbx/naming_version=2

View File

@@ -3,6 +3,7 @@
[ext_resource type="PackedScene" uid="uid://bdqeshcwwnyc4" path="res://core/ai/agents/human/ai_citizen.tscn" id="1_cduuu"]
[node name="AiCitizenSitter" unique_id=1228675528 instance=ExtResource("1_cduuu")]
entity_type = 2
entity_name = "CitizenSitter"
[node name="Skeleton3D" parent="BaseMesh/BaseMesh" parent_id_path=PackedInt32Array(1846171523, 1142246531) index="0" unique_id=928995817]

View File

@@ -5,6 +5,7 @@
[ext_resource type="Script" uid="uid://bngfthvt04ivv" path="res://core/ai/framework/patrol_state.gd" id="3_8d0tj"]
[node name="AiCitizenWalker" unique_id=1228675528 instance=ExtResource("1_dms8s")]
entity_type = 1
entity_name = "CitizenWalker"
[node name="StateMachine" parent="." index="1" unique_id=1286404264 node_paths=PackedStringArray("initial_state")]

View File

@@ -3,13 +3,39 @@
[ext_resource type="PackedScene" uid="uid://mvh2v6v72stt" path="res://core/ai/agents/human/ai_human.tscn" id="1_l2y7m"]
[ext_resource type="Script" uid="uid://bngfthvt04ivv" path="res://core/ai/framework/patrol_state.gd" id="3_2oda6"]
[ext_resource type="Script" uid="uid://d3hy70ec8vqo5" path="res://core/ai/framework/run_animation_state.gd" id="4_2oda6"]
[ext_resource type="Shader" uid="uid://d0ch5ofrgf7y6" path="res://core/daynight/trunk_shader.gdshader" id="6_ejkex"]
[ext_resource type="Texture2D" uid="uid://jn4seoee6vtw" path="res://tgcc/chunk/prop/house/main_texture.png" id="7_ax7ee"]
[ext_resource type="Material" uid="uid://b2lg2y1k7grmo" path="res://tgcc/chunk/prop/tree/trunk.tres" id="9_gownw"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_gownw"]
render_priority = 0
shader = ExtResource("6_ejkex")
shader_parameter/albedo_color = Color(1, 1, 1, 1)
shader_parameter/albedo_texture = ExtResource("7_ax7ee")
shader_parameter/use_texture = true
shader_parameter/uv_scale = Vector2(1, 1)
shader_parameter/palette_shift_y = 0.0
shader_parameter/gradient_start_y = 0.0
shader_parameter/gradient_end_y = 10.0
shader_parameter/light_steps = 3.0
shader_parameter/step_softness = 0.1
shader_parameter/shadow_color = Color(0.4, 0.4, 0.6, 1)
shader_parameter/shadow_offset = 0.0
shader_parameter/cast_shadow_strength = 0.6
shader_parameter/use_ghibli_glint = true
shader_parameter/glint_color = Color(1, 0.95, 0.85, 1)
shader_parameter/glint_intensity = 0.446000021185
shader_parameter/glint_sharpness = 7.000000285
shader_parameter/emission_color = Color(0, 0, 0, 1)
shader_parameter/emission_energy = 0.0
[node name="AiFarmer" unique_id=1228675528 instance=ExtResource("1_l2y7m")]
navigation_layers = 2
entity_name = "Farmer"
allowed_biomes = Array[String](["countryside"])
[node name="StateMachine" parent="." index="1" unique_id=1286404264 node_paths=PackedStringArray("initial_state")]
initial_state = NodePath("GatherState")
initial_state = NodePath("IdleState")
[node name="PatrolState" type="Node" parent="StateMachine" index="0" unique_id=930272128]
script = ExtResource("3_2oda6")
@@ -33,8 +59,64 @@ state_id = &"idle"
next_state_id = &"patrol"
animation_name = "custom/idle"
[node name="Skeleton3D" parent="BaseMesh/BaseMesh" parent_id_path=PackedInt32Array(1846171523, 1142246531) index="0" unique_id=928995817]
bones/8/rotation = Quaternion(-0.6173422, -0.37346625, 0.5666242, -0.3979305)
bones/46/rotation = Quaternion(0.059241787, 0.12928401, 0.9836761, -0.110261135)
[node name="Skeleton3D" parent="BaseMesh/BaseMesh" parent_id_path=PackedInt32Array(1846171523, 1363988051) index="0" unique_id=1848874512]
bones/0/position = Vector3(-0.0015795716, 0.9761277, 0.0012886743)
bones/0/rotation = Quaternion(0.008345705, 0.02440254, -0.0222881, 0.999419)
bones/1/rotation = Quaternion(-0.033856627, 0.0019547925, 0.01148837, 0.9993588)
bones/2/rotation = Quaternion(0.003385691, 0.0057030413, 0.004773842, 0.9999666)
bones/3/rotation = Quaternion(0.0033856947, 0.0057030534, 0.0047738357, 0.9999666)
bones/4/rotation = Quaternion(0.03554347, -0.0036022358, -0.01067691, 0.9993046)
bones/5/rotation = Quaternion(0.023500564, -0.0268053, 0.016007349, 0.9992362)
bones/8/rotation = Quaternion(-0.677935, -0.3162402, 0.5391133, -0.3869797)
bones/9/rotation = Quaternion(0.33057448, -0.0144906035, -0.024771411, 0.9433436)
bones/10/rotation = Quaternion(0.071588665, 0.16423635, 0.26876602, 0.9463965)
bones/11/rotation = Quaternion(-0.11033899, 0.19317266, 0.18225361, 0.95775425)
bones/12/rotation = Quaternion(0.28979003, -0.100065045, 0.021221647, 0.95160836)
bones/13/rotation = Quaternion(-0.01075587, -0.003262491, 0.085242614, 0.9962969)
bones/17/rotation = Quaternion(0.372185, -0.04203017, 0.003265603, 0.9272007)
bones/18/rotation = Quaternion(0.6449709, -0.022805, 0.11591787, 0.7550203)
bones/22/rotation = Quaternion(0.5152635, -0.09862117, 0.07484319, 0.8480425)
bones/23/rotation = Quaternion(0.7634141, -0.01797779, 0.14009176, 0.63027775)
bones/27/rotation = Quaternion(0.6460654, -0.34361044, 0.58023506, 0.35757324)
bones/28/rotation = Quaternion(0.3564352, 0.033001784, 0.1479881, 0.9219352)
bones/29/rotation = Quaternion(0.10407414, -0.119882874, -0.20823832, 0.96510804)
bones/30/rotation = Quaternion(-0.040577345, -0.20657076, -0.14159827, 0.96728075)
bones/31/rotation = Quaternion(0.18718895, 0.11185156, -0.005364931, 0.97592044)
bones/32/rotation = Quaternion(0.077440694, -0.18545257, 0.02808432, 0.9791944)
bones/36/rotation = Quaternion(0.33726785, 0.06133867, 0.07482985, 0.93642324)
bones/37/rotation = Quaternion(0.5483169, 0.027307179, -0.058035128, 0.83380747)
bones/41/rotation = Quaternion(0.4086348, 0.09420283, 0.037183065, 0.90706164)
bones/42/rotation = Quaternion(0.59161603, 0.030198008, -0.037664413, 0.8047733)
bones/46/rotation = Quaternion(0.060233127, 0.24369022, 0.966249, -0.05787964)
bones/47/rotation = Quaternion(-0.56581247, 0.0105282655, -0.0027436528, 0.8244622)
bones/48/rotation = Quaternion(0.46872035, 0.0146656195, -0.0033694527, 0.88321847)
bones/49/rotation = Quaternion(0.49349385, 0.06718427, -0.01829647, 0.86695755)
bones/52/rotation = Quaternion(-0.0765912, 0.12600712, 0.988389, -0.03665043)
bones/53/rotation = Quaternion(-0.25056988, -0.06629382, 0.018621337, 0.96564656)
bones/54/rotation = Quaternion(0.549743, -0.041815143, -0.046032935, 0.83301574)
bones/55/rotation = Quaternion(0.3627838, -0.05369254, 0.01255593, 0.9302406)
[node name="hat_001" parent="Farmer1/BaseMesh/Skeleton3D" parent_id_path=PackedInt32Array(925374995, 224377346) index="1" unique_id=1950307793]
surface_material_override/0 = SubResource("ShaderMaterial_gownw")
[node name="pants" parent="Farmer1/BaseMesh/Skeleton3D" parent_id_path=PackedInt32Array(925374995, 224377346) index="2" unique_id=1080342530]
surface_material_override/0 = ExtResource("9_gownw")
[node name="shirt2" parent="Farmer1/BaseMesh/Skeleton3D" parent_id_path=PackedInt32Array(925374995, 224377346) index="3" unique_id=1846653994]
surface_material_override/0 = ExtResource("9_gownw")
surface_material_override/1 = ExtResource("9_gownw")
surface_material_override/2 = ExtResource("9_gownw")
[node name="pants" parent="Farmer2/BaseMesh/Skeleton3D" parent_id_path=PackedInt32Array(1239853450, 1824387143) index="1" unique_id=1777820543]
surface_material_override/0 = ExtResource("9_gownw")
[node name="shirt1" parent="Farmer2/BaseMesh/Skeleton3D" parent_id_path=PackedInt32Array(1239853450, 1824387143) index="2" unique_id=1243989703]
surface_material_override/0 = ExtResource("9_gownw")
surface_material_override/1 = ExtResource("9_gownw")
[node name="DressHuman" parent="." index="6" unique_id=107727715]
colors = Array[Color]([Color(0.8, 0.45490196, 0.32156864, 1), Color(0.84797, 0.6868576, 0.24382448, 1), Color(0.4862745, 0.60784316, 0.6901961, 1), Color(0.24718326, 0.3552445, 0.23638204, 1), Color(0.34000763, 0.32978323, 0.29223797, 1)])
[editable path="BaseMesh"]
[editable path="Farmer1"]
[editable path="Farmer2"]

View File

@@ -6,6 +6,14 @@
[ext_resource type="Animation" uid="uid://ptj85lvvtjpg" path="res://core/ai/agents/human/sitting.res" id="4_8kg0q"]
[ext_resource type="Animation" uid="uid://oq22ilhxjejj" path="res://core/ai/agents/human/idle.res" id="4_cuxdk"]
[ext_resource type="Animation" uid="uid://6xnsf8x7nmsl" path="res://core/ai/agents/human/walking.res" id="6_cuxdk"]
[ext_resource type="PackedScene" uid="uid://b3j2dbcqwodx1" path="res://core/ai/agents/human/Farmer1.fbx" id="7_hguxe"]
[ext_resource type="Material" uid="uid://blqelpjvdv23j" path="res://tgcc/chunk/material/grassflat_chunk.tres" id="8_362f3"]
[ext_resource type="PackedScene" uid="uid://c5x3ycaxixpxy" path="res://core/ai/agents/human/Farmer2.fbx" id="8_ke7sb"]
[ext_resource type="Script" uid="uid://dauqq8cqmwrqh" path="res://core/ai/agents/human/dress_human.gd" id="9_2tpdi"]
[ext_resource type="Material" uid="uid://b4luvp3fi0p43" path="res://tgcc/chunk/material/railway_chunk.tres" id="9_12auf"]
[ext_resource type="Shader" uid="uid://d0ch5ofrgf7y6" path="res://core/daynight/trunk_shader.gdshader" id="10_3t1a4"]
[ext_resource type="Texture2D" uid="uid://jn4seoee6vtw" path="res://tgcc/chunk/prop/house/main_texture.png" id="11_o6vi4"]
[ext_resource type="Material" uid="uid://wkegx4a21x7u" path="res://tgcc/chunk/prop/fence/fences.tres" id="11_v2pkc"]
[sub_resource type="AnimationLibrary" id="AnimationLibrary_8kg0q"]
_data = {
@@ -15,13 +23,123 @@ _data = {
&"walking": ExtResource("6_cuxdk")
}
[sub_resource type="ShaderMaterial" id="ShaderMaterial_vuqrb"]
render_priority = 0
shader = ExtResource("10_3t1a4")
shader_parameter/albedo_color = Color(1, 1, 1, 1)
shader_parameter/albedo_texture = ExtResource("11_o6vi4")
shader_parameter/use_texture = true
shader_parameter/uv_scale = Vector2(1, 1)
shader_parameter/palette_shift_y = 0.0
shader_parameter/gradient_start_y = 0.0
shader_parameter/gradient_end_y = 10.0
shader_parameter/light_steps = 3.0
shader_parameter/step_softness = 0.1
shader_parameter/shadow_color = Color(0.4, 0.4, 0.6, 1)
shader_parameter/shadow_offset = 0.0
shader_parameter/cast_shadow_strength = 0.6
shader_parameter/use_ghibli_glint = false
shader_parameter/glint_color = Color(1, 0.95, 0.85, 1)
shader_parameter/glint_intensity = 2.000000095
shader_parameter/glint_sharpness = 7.000000285
shader_parameter/emission_color = Color(0, 0, 0, 1)
shader_parameter/emission_energy = 0.0
[sub_resource type="AnimationLibrary" id="AnimationLibrary_ke7sb"]
_data = {
&"gathering": ExtResource("3_8kg0q"),
&"idle": ExtResource("4_cuxdk"),
&"sitting": ExtResource("4_8kg0q"),
&"walking": ExtResource("6_cuxdk")
}
[sub_resource type="ShaderMaterial" id="ShaderMaterial_v2pkc"]
render_priority = 0
shader = ExtResource("10_3t1a4")
shader_parameter/albedo_color = Color(1, 1, 1, 1)
shader_parameter/albedo_texture = ExtResource("11_o6vi4")
shader_parameter/use_texture = true
shader_parameter/uv_scale = Vector2(1, 1)
shader_parameter/palette_shift_y = 0.0
shader_parameter/gradient_start_y = 0.0
shader_parameter/gradient_end_y = 10.0
shader_parameter/light_steps = 3.0
shader_parameter/step_softness = 0.1
shader_parameter/shadow_color = Color(0.4, 0.4, 0.6, 1)
shader_parameter/shadow_offset = 0.0
shader_parameter/cast_shadow_strength = 0.6
shader_parameter/use_ghibli_glint = false
shader_parameter/glint_color = Color(1, 0.95, 0.85, 1)
shader_parameter/glint_intensity = 2.000000095
shader_parameter/glint_sharpness = 7.000000285
shader_parameter/emission_color = Color(0, 0, 0, 1)
shader_parameter/emission_energy = 0.0
[sub_resource type="AnimationLibrary" id="AnimationLibrary_2tpdi"]
_data = {
&"gathering": ExtResource("3_8kg0q"),
&"idle": ExtResource("4_cuxdk"),
&"sitting": ExtResource("4_8kg0q"),
&"walking": ExtResource("6_cuxdk")
}
[node name="AiHuman" unique_id=1228675528 node_paths=PackedStringArray("anim_player") instance=ExtResource("1_hko2w")]
anim_player = NodePath("BaseMesh/AnimationPlayer")
[node name="BaseMesh" parent="." index="3" unique_id=1846171523 instance=ExtResource("3_ef4cu")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.9, 0)
[node name="Skeleton3D" parent="BaseMesh/BaseMesh" parent_id_path=PackedInt32Array(1846171523, 1142246531) index="0" unique_id=928995817]
[node name="Skeleton3D" parent="BaseMesh/BaseMesh" parent_id_path=PackedInt32Array(1846171523, 1363988051) index="0" unique_id=1848874512]
bones/0/position = Vector3(-0.0024333135, 0.9952637, 6.9276895e-05)
bones/0/rotation = Quaternion(-0.0049152793, -0.050206795, -0.026513178, 0.99837476)
bones/1/rotation = Quaternion(-0.025209453, 0.006135946, 0.009180705, 0.9996213)
bones/2/rotation = Quaternion(0.020680578, 0.011754706, 0.015464293, 0.99959743)
bones/3/rotation = Quaternion(0.020680578, 0.011754692, 0.015464287, 0.99959743)
bones/4/rotation = Quaternion(-0.053108443, 0.009324013, 0.011697456, 0.9984768)
bones/5/rotation = Quaternion(0.03947722, 0.0123098595, -0.024802445, 0.99883676)
bones/8/rotation = Quaternion(-0.5728458, -0.38286844, 0.60871977, -0.39334446)
bones/9/rotation = Quaternion(0.44939622, 0.29187396, 0.053696252, 0.84259677)
bones/10/rotation = Quaternion(-0.013349593, 0.006303966, 0.231745, 0.97266454)
bones/11/rotation = Quaternion(-0.13493852, -0.23365982, 0.088579476, 0.95882654)
bones/12/rotation = Quaternion(0.1921569, 0.10821218, -0.024087887, 0.9750824)
bones/13/rotation = Quaternion(0.025333803, 0.00917047, 0.048555605, 0.9984571)
bones/14/rotation = Quaternion(-0.0120385215, 0.035021365, -0.027293455, 0.99894124)
bones/17/rotation = Quaternion(0.09417869, -0.072669275, -0.17156787, 0.9779642)
bones/18/rotation = Quaternion(0.14308922, 0.0019350327, -0.0097575225, 0.98965985)
bones/19/rotation = Quaternion(0.114431076, 0.0009974723, -0.016153814, 0.99329937)
bones/22/rotation = Quaternion(0.11025663, -0.026056329, -0.115814656, 0.9867886)
bones/23/rotation = Quaternion(0.08941777, 0.0010620031, -0.023814844, 0.9957089)
bones/24/rotation = Quaternion(0.18236126, 0.0039793584, -0.014504941, 0.9831166)
bones/27/rotation = Quaternion(0.5637914, -0.40525162, 0.5912719, 0.41025364)
bones/28/rotation = Quaternion(0.5117543, -0.062450167, 0.07040776, 0.8539615)
bones/29/rotation = Quaternion(0.06749446, 0.22771753, -0.20722775, 0.9490237)
bones/30/rotation = Quaternion(-0.0005478785, -0.33554533, -0.112540804, 0.93527734)
bones/31/rotation = Quaternion(0.13877106, 0.12508087, 0.031252213, 0.9818965)
bones/32/rotation = Quaternion(-0.01564488, 0.0028465544, -0.073795564, 0.9971466)
bones/33/rotation = Quaternion(0.09055836, 0.16444178, -0.016598457, 0.9820808)
bones/36/rotation = Quaternion(0.048626706, 0.08521321, 0.1502388, 0.98376954)
bones/37/rotation = Quaternion(0.20746112, 0.00031290663, 0.0112788575, 0.97817826)
bones/38/rotation = Quaternion(0.15843387, -0.0010695796, -0.0025179624, 0.9873659)
bones/41/rotation = Quaternion(0.16202472, 0.04171574, 0.09497025, 0.98131984)
bones/42/rotation = Quaternion(0.14799795, 0.00100551, 0.030993575, 0.9885015)
bones/43/rotation = Quaternion(0.04765674, -0.005312021, -0.037802245, 0.9981341)
bones/46/rotation = Quaternion(0.024758164, 0.13509843, 0.9874187, -0.07835583)
bones/47/rotation = Quaternion(-0.1871983, 0.0008643933, -0.010582049, 0.98226476)
bones/48/rotation = Quaternion(0.46037424, -0.13497493, 0.042778272, 0.87636036)
bones/49/rotation = Quaternion(0.3209879, 0.038273156, 0.0024189365, 0.9463065)
bones/52/rotation = Quaternion(-0.060150255, 0.009860813, 0.99663967, -0.05471906)
bones/53/rotation = Quaternion(-0.10502596, -0.00032293255, 0.008123855, 0.9944363)
bones/54/rotation = Quaternion(0.51151097, 0.066536464, -0.07767137, 0.8531686)
bones/55/rotation = Quaternion(0.3453064, -0.067497015, 0.02391528, 0.93575406)
[node name="AnimationPlayer" parent="BaseMesh" index="1" unique_id=930749540]
libraries/custom = SubResource("AnimationLibrary_8kg0q")
[node name="Farmer1" parent="." index="4" unique_id=925374995 instance=ExtResource("7_hguxe")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.9, 0)
visible = false
[node name="Skeleton3D" parent="Farmer1/BaseMesh" parent_id_path=PackedInt32Array(925374995, 1608049295) index="0" unique_id=224377346]
bones/0/position = Vector3(0.00060560287, 0.9719096, 0.007789615)
bones/0/rotation = Quaternion(-0.03158553, -0.024531638, -0.086598895, 0.9954402)
bones/1/rotation = Quaternion(-0.068302006, -0.011589706, 0.088431515, 0.99367017)
@@ -29,7 +147,7 @@ bones/2/rotation = Quaternion(0.013750468, -0.0028497525, 0.022636604, 0.9996452
bones/3/rotation = Quaternion(0.014052153, -0.0046672956, 0.021981178, 0.99964875)
bones/4/rotation = Quaternion(0.08060878, 0.0009885994, -0.05385771, 0.99528927)
bones/5/rotation = Quaternion(-0.08819712, -0.010719821, 0.004734955, 0.9960341)
bones/8/rotation = Quaternion(-0.5780019, -0.40066734, 0.5948007, -0.38934776)
bones/8/rotation = Quaternion(-0.6173422, -0.37346625, 0.5666242, -0.3979305)
bones/9/rotation = Quaternion(0.5403529, 0.038538188, -0.087646246, 0.8359735)
bones/10/rotation = Quaternion(-0.009744837, 0.0007412914, 0.18789424, 0.98214066)
bones/11/rotation = Quaternion(0.019992959, 0.15807849, 0.15262179, 0.9753554)
@@ -55,7 +173,7 @@ bones/38/rotation = Quaternion(0.13336712, -0.0009009653, 0.002359003, 0.9910635
bones/41/rotation = Quaternion(0.12012116, 0.015946638, 0.088212825, 0.9887037)
bones/42/rotation = Quaternion(0.11693482, 0.00096280884, 0.06057904, 0.99128985)
bones/43/rotation = Quaternion(0.22191456, 0.026510797, -0.016629422, 0.9745638)
bones/46/rotation = Quaternion(0.00039673893, 0.021240532, 0.99960107, -0.018613452)
bones/46/rotation = Quaternion(0.059241787, 0.12928401, 0.9836761, -0.110261135)
bones/47/rotation = Quaternion(-0.34151906, -0.06546942, 0.0071559767, 0.93756455)
bones/48/rotation = Quaternion(0.60213244, 0.010313871, -0.012120304, 0.7982376)
bones/49/rotation = Quaternion(0.31586254, 0.059334766, -0.020474449, 0.9467265)
@@ -64,7 +182,93 @@ bones/53/rotation = Quaternion(-0.20515193, 0.049833227, 0.0071537, 0.9774345)
bones/54/rotation = Quaternion(0.55275166, -0.049315806, -0.007871797, 0.8318483)
bones/55/rotation = Quaternion(0.326561, -0.058840513, 0.019667907, 0.9431378)
[node name="AnimationPlayer" parent="BaseMesh" index="1" unique_id=2096005878]
libraries/custom = SubResource("AnimationLibrary_8kg0q")
[node name="Cesto" parent="Farmer1/BaseMesh/Skeleton3D" index="0" unique_id=1473592366]
surface_material_override/0 = ExtResource("8_362f3")
surface_material_override/1 = ExtResource("9_12auf")
surface_material_override/2 = ExtResource("9_12auf")
[node name="hat_001" parent="Farmer1/BaseMesh/Skeleton3D" index="1" unique_id=1950307793]
surface_material_override/0 = SubResource("ShaderMaterial_vuqrb")
surface_material_override/1 = ExtResource("11_v2pkc")
[node name="pants" parent="Farmer1/BaseMesh/Skeleton3D" index="2" unique_id=1080342530]
surface_material_override/0 = ExtResource("11_v2pkc")
[node name="shirt2" parent="Farmer1/BaseMesh/Skeleton3D" index="3" unique_id=1846653994]
surface_material_override/0 = ExtResource("11_v2pkc")
surface_material_override/1 = ExtResource("11_v2pkc")
surface_material_override/2 = ExtResource("11_v2pkc")
[node name="AnimationPlayer" parent="Farmer1" index="1" unique_id=2137081705]
libraries/custom = SubResource("AnimationLibrary_ke7sb")
[node name="Farmer2" parent="." index="5" unique_id=1239853450 instance=ExtResource("8_ke7sb")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.9, 0)
visible = false
[node name="Skeleton3D" parent="Farmer2/BaseMesh" parent_id_path=PackedInt32Array(1239853450, 2068119799) index="0" unique_id=1824387143]
bones/0/position = Vector3(0.00060560287, 0.9719096, 0.007789615)
bones/0/rotation = Quaternion(-0.03158553, -0.024531638, -0.086598895, 0.9954402)
bones/1/rotation = Quaternion(-0.068302006, -0.011589706, 0.088431515, 0.99367017)
bones/2/rotation = Quaternion(0.013750468, -0.0028497525, 0.022636604, 0.99964523)
bones/3/rotation = Quaternion(0.014052153, -0.0046672956, 0.021981178, 0.99964875)
bones/4/rotation = Quaternion(0.08060878, 0.0009885994, -0.05385771, 0.99528927)
bones/5/rotation = Quaternion(-0.08819712, -0.010719821, 0.004734955, 0.9960341)
bones/8/rotation = Quaternion(-0.6173422, -0.37346625, 0.5666242, -0.3979305)
bones/9/rotation = Quaternion(0.5403529, 0.038538188, -0.087646246, 0.8359735)
bones/10/rotation = Quaternion(-0.009744837, 0.0007412914, 0.18789424, 0.98214066)
bones/11/rotation = Quaternion(0.019992959, 0.15807849, 0.15262179, 0.9753554)
bones/12/rotation = Quaternion(0.11525436, -0.03521942, -0.0147265345, 0.9926023)
bones/13/rotation = Quaternion(0.004553697, -0.0011956134, 0.0748576, 0.9971832)
bones/14/rotation = Quaternion(-0.021573644, -0.09607655, -0.02610063, 0.9947978)
bones/17/rotation = Quaternion(0.10615231, -0.012490018, -0.06538699, 0.9921191)
bones/18/rotation = Quaternion(0.112639524, -0.0005986789, -0.020016164, 0.99343413)
bones/19/rotation = Quaternion(0.13624819, 0.001439244, -0.018421004, 0.9905025)
bones/22/rotation = Quaternion(0.051831737, -0.007218998, -0.063239366, 0.9966254)
bones/23/rotation = Quaternion(0.12439526, 0.00031310506, -0.03746358, 0.99152523)
bones/24/rotation = Quaternion(0.14832872, 0.0028264069, -0.017447466, 0.9887802)
bones/27/rotation = Quaternion(0.6085938, -0.37735197, 0.5827399, 0.3842309)
bones/28/rotation = Quaternion(0.42811802, -0.12440211, 0.04666202, 0.8939026)
bones/29/rotation = Quaternion(-0.010464899, -0.0008133942, -0.24076757, 0.97052604)
bones/30/rotation = Quaternion(0.01554073, -0.15455346, -0.11519627, 0.9811226)
bones/31/rotation = Quaternion(0.109474085, 0.02398801, 0.02464503, 0.99339455)
bones/32/rotation = Quaternion(-0.03558804, 0.04901748, 0.08471445, 0.9945624)
bones/33/rotation = Quaternion(0.014632019, 0.019343862, -0.1317728, 0.9909832)
bones/36/rotation = Quaternion(0.19392295, 0.020005528, 0.11780725, 0.973712)
bones/37/rotation = Quaternion(0.090232305, 2.462184e-07, 0.01726049, 0.9957712)
bones/38/rotation = Quaternion(0.13336712, -0.0009009653, 0.002359003, 0.9910635)
bones/41/rotation = Quaternion(0.12012116, 0.015946638, 0.088212825, 0.9887037)
bones/42/rotation = Quaternion(0.11693482, 0.00096280884, 0.06057904, 0.99128985)
bones/43/rotation = Quaternion(0.22191456, 0.026510797, -0.016629422, 0.9745638)
bones/46/rotation = Quaternion(0.059241787, 0.12928401, 0.9836761, -0.110261135)
bones/47/rotation = Quaternion(-0.34151906, -0.06546942, 0.0071559767, 0.93756455)
bones/48/rotation = Quaternion(0.60213244, 0.010313871, -0.012120304, 0.7982376)
bones/49/rotation = Quaternion(0.31586254, 0.059334766, -0.020474449, 0.9467265)
bones/52/rotation = Quaternion(-0.07240856, 0.034467246, 0.9931159, -0.085380435)
bones/53/rotation = Quaternion(-0.20515193, 0.049833227, 0.0071537, 0.9774345)
bones/54/rotation = Quaternion(0.55275166, -0.049315806, -0.007871797, 0.8318483)
bones/55/rotation = Quaternion(0.326561, -0.058840513, 0.019667907, 0.9431378)
[node name="hat_001" parent="Farmer2/BaseMesh/Skeleton3D" index="0" unique_id=1838787788]
surface_material_override/0 = SubResource("ShaderMaterial_v2pkc")
surface_material_override/1 = ExtResource("11_v2pkc")
[node name="pants" parent="Farmer2/BaseMesh/Skeleton3D" index="1" unique_id=1777820543]
surface_material_override/0 = ExtResource("11_v2pkc")
[node name="shirt1" parent="Farmer2/BaseMesh/Skeleton3D" index="2" unique_id=1243989703]
surface_material_override/0 = ExtResource("11_v2pkc")
surface_material_override/1 = ExtResource("11_v2pkc")
[node name="AnimationPlayer" parent="Farmer2" index="1" unique_id=995025267]
libraries/custom = SubResource("AnimationLibrary_2tpdi")
[node name="DressHuman" type="Node3D" parent="." index="6" unique_id=107727715 node_paths=PackedStringArray("farmers", "main_anim_player")]
script = ExtResource("9_2tpdi")
farmers = [NodePath("../Farmer1"), NodePath("../Farmer2")]
colors = Array[Color]([Color(0.4089676, 0.23789883, 0.083061926, 1), Color(0.4862745, 0.60784316, 0.6901961, 1), Color(0.3529412, 0.41960785, 0.32941177, 1), Color(0.31533447, 0.3330399, 0.29725653, 1)])
main_anim_player = NodePath("../BaseMesh/AnimationPlayer")
[editable path="BaseMesh"]
[editable path="Farmer1"]
[editable path="Farmer2"]

View File

@@ -0,0 +1,59 @@
extends Node
@export var farmers: Array[Node3D]
@export var colors: Array[Color]
@export var main_anim_player: AnimationPlayer
var dress_anim_player: AnimationPlayer
func _ready() -> void:
if farmers.is_empty():
return
for farmer in farmers:
if farmer:
farmer.hide()
var selected_farmer = farmers.pick_random()
if selected_farmer:
selected_farmer.show()
dress_anim_player = selected_farmer.get_node_or_null("AnimationPlayer")
if main_anim_player and dress_anim_player:
main_anim_player.current_animation_changed.connect(_on_animation_sync)
main_anim_player.animation_started.connect(_on_animation_sync)
if main_anim_player.current_animation != "":
_on_animation_sync(main_anim_player.current_animation)
dress_anim_player.seek(main_anim_player.current_animation_position)
if colors.size() > 0:
var parts_to_color = ["pants", "shirt"]
var shared_color = colors.pick_random()
for part_name in parts_to_color:
var piece_node = _find_mesh_case_insensitive(selected_farmer, part_name)
if piece_node:
var mat = StandardMaterial3D.new()
mat.albedo_color = shared_color
piece_node.set_surface_override_material(0, mat)
func _on_animation_sync(anim_name: StringName) -> void:
if dress_anim_player and dress_anim_player.has_animation(anim_name):
dress_anim_player.play(anim_name)
dress_anim_player.speed_scale = main_anim_player.speed_scale
func _find_mesh_case_insensitive(parent: Node, part_name: String) -> MeshInstance3D:
var target = part_name.to_lower()
for child in parent.get_children():
if child.name.to_lower().contains(target) and child is MeshInstance3D:
return child
var found = _find_mesh_case_insensitive(child, target)
if found:
return found
return null

View File

@@ -0,0 +1 @@
uid://dauqq8cqmwrqh

Binary file not shown.

Binary file not shown.

View File

@@ -6,7 +6,10 @@
[ext_resource type="Script" uid="uid://bngfthvt04ivv" path="res://core/ai/framework/patrol_state.gd" id="3_x67t3"]
[node name="AiRacoon" unique_id=1228675528 node_paths=PackedStringArray("anim_player") instance=ExtResource("1_seif5")]
navigation_layers = 4
anim_player = NodePath("Raccoon_rig/AnimationPlayer")
entity_type = 7
entity_name = "Racoon"
[node name="StateMachine" parent="." index="1" unique_id=1286404264 node_paths=PackedStringArray("initial_state")]
initial_state = NodePath("IdleState")
@@ -26,7 +29,7 @@ exit_on_action_finished = true
[node name="Raccoon_rig" parent="." index="3" unique_id=338211330 instance=ExtResource("2_obtl0")]
[node name="Skeleton3D" parent="Raccoon_rig/Rig_Raccoon" parent_id_path=PackedInt32Array(338211330, 1484615769) index="0" unique_id=689430915]
[node name="Skeleton3D" parent="Raccoon_rig/Rig_Raccoon" parent_id_path=PackedInt32Array(338211330, 1450300070) index="0" unique_id=745849430]
bones/1/position = Vector3(2.0224038e-08, 0.20926544, 0.2908604)
bones/1/rotation = Quaternion(0.12769087, -0.6954821, -0.12769023, 0.69548184)
bones/1/scale = Vector3(1, 0.99999994, 0.99999994)

View File

@@ -4,10 +4,75 @@
[ext_resource type="Script" uid="uid://d3hy70ec8vqo5" path="res://core/ai/framework/run_animation_state.gd" id="2_euyvm"]
[ext_resource type="PackedScene" uid="uid://dg6eq5bjdv77x" path="res://core/ai/agents/wagyu/Wagyu_rig.fbx" id="2_kinfw"]
[ext_resource type="Script" uid="uid://bngfthvt04ivv" path="res://core/ai/framework/patrol_state.gd" id="3_stslt"]
[ext_resource type="Shader" uid="uid://d0ch5ofrgf7y6" path="res://core/daynight/trunk_shader.gdshader" id="5_stslt"]
[ext_resource type="Material" uid="uid://cn20mp8ep3yxu" path="res://tgcc/chunk/material/wires.tres" id="7_qxgon"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_jndo6"]
render_priority = 0
shader = ExtResource("5_stslt")
shader_parameter/albedo_color = Color(0.3003036, 0.13408488, 0.037156556, 1)
shader_parameter/use_texture = true
shader_parameter/uv_scale = Vector2(3, 3)
shader_parameter/palette_shift_y = 0.0
shader_parameter/gradient_start_y = 0.0
shader_parameter/gradient_end_y = 1.5
shader_parameter/light_steps = 3.0
shader_parameter/step_softness = 0.1
shader_parameter/shadow_color = Color(0.4, 0.4, 0.6, 1)
shader_parameter/shadow_offset = 0.0
shader_parameter/cast_shadow_strength = 0.6
shader_parameter/use_ghibli_glint = true
shader_parameter/glint_color = Color(1, 0.95, 0.85, 1)
shader_parameter/glint_intensity = 1.0
shader_parameter/glint_sharpness = 32.0
shader_parameter/emission_color = Color(0, 0, 0, 1)
shader_parameter/emission_energy = 0.0
[sub_resource type="ShaderMaterial" id="ShaderMaterial_ffprj"]
render_priority = 0
shader = ExtResource("5_stslt")
shader_parameter/albedo_color = Color(0.8936267, 0.48305064, 0.25341055, 1)
shader_parameter/use_texture = true
shader_parameter/uv_scale = Vector2(3, 3)
shader_parameter/palette_shift_y = 0.0
shader_parameter/gradient_start_y = 0.0
shader_parameter/gradient_end_y = 1.5
shader_parameter/light_steps = 3.0
shader_parameter/step_softness = 0.1
shader_parameter/shadow_color = Color(0.4, 0.4, 0.6, 1)
shader_parameter/shadow_offset = 0.0
shader_parameter/cast_shadow_strength = 0.6
shader_parameter/use_ghibli_glint = true
shader_parameter/glint_color = Color(1, 0.95, 0.85, 1)
shader_parameter/glint_intensity = 1.0
shader_parameter/glint_sharpness = 32.0
shader_parameter/emission_color = Color(0, 0, 0, 1)
shader_parameter/emission_energy = 0.0
[sub_resource type="ShaderMaterial" id="ShaderMaterial_4po7g"]
render_priority = 0
shader = ExtResource("5_stslt")
shader_parameter/albedo_color = Color(0.91262335, 0.6514041, 0.37075257, 1)
shader_parameter/use_texture = true
shader_parameter/uv_scale = Vector2(3, 3)
shader_parameter/palette_shift_y = 0.0
shader_parameter/gradient_start_y = 0.0
shader_parameter/gradient_end_y = 1.5
shader_parameter/light_steps = 3.0
shader_parameter/step_softness = 0.1
shader_parameter/shadow_color = Color(0.4, 0.4, 0.6, 1)
shader_parameter/shadow_offset = 0.0
shader_parameter/cast_shadow_strength = 0.6
shader_parameter/use_ghibli_glint = true
shader_parameter/glint_color = Color(1, 0.95, 0.85, 1)
shader_parameter/glint_intensity = 1.0
shader_parameter/glint_sharpness = 32.0
shader_parameter/emission_color = Color(0, 0, 0, 1)
shader_parameter/emission_energy = 0.0
[node name="AiWagyu" unique_id=1228675528 node_paths=PackedStringArray("anim_player") instance=ExtResource("1_01jto")]
anim_player = NodePath("Wagyu_rig/AnimationPlayer")
entity_type = 1
entity_type = 8
entity_name = "Wagyu"
[node name="StateMachine" parent="." index="1" unique_id=1286404264 node_paths=PackedStringArray("initial_state")]
@@ -28,7 +93,7 @@ exit_on_action_finished = true
[node name="Wagyu_rig" parent="." index="3" unique_id=434062845 instance=ExtResource("2_kinfw")]
[node name="Skeleton3D" parent="Wagyu_rig/Rig_wagyu" parent_id_path=PackedInt32Array(434062845, 984050088) index="0" unique_id=1381831503]
[node name="Skeleton3D" parent="Wagyu_rig/Rig_wagyu" parent_id_path=PackedInt32Array(434062845, 1389976890) index="0" unique_id=1274413548]
bones/1/position = Vector3(3.0605813e-06, 0.93198204, 1.5827273)
bones/1/rotation = Quaternion(0.12769, -0.69548225, -0.12769146, 0.6954816)
bones/2/rotation = Quaternion(-7.474808e-08, -1.0355375e-07, -0.5904155, 0.80709946)
@@ -51,4 +116,10 @@ bones/26/rotation = Quaternion(3.2779312e-07, 1.2327837e-06, 0.9652686, -0.26125
bones/27/rotation = Quaternion(-6.191086e-07, -2.305114e-07, -0.36804327, 0.9298087)
bones/28/rotation = Quaternion(-0.0001528551, -7.8230434e-05, 0.45790893, 0.8889991)
[node name="Wagyu" parent="Wagyu_rig/Rig_wagyu/Skeleton3D" index="0" unique_id=2005444162]
surface_material_override/0 = SubResource("ShaderMaterial_jndo6")
surface_material_override/1 = SubResource("ShaderMaterial_ffprj")
surface_material_override/2 = ExtResource("7_qxgon")
surface_material_override/3 = SubResource("ShaderMaterial_4po7g")
[editable path="Wagyu_rig"]

View File

@@ -0,0 +1,40 @@
extends State
class_name SitState
var reverse: bool = false
func enter() -> void:
reverse = false
super.enter()
if agent.anim_player and not agent.anim_player.animation_finished.is_connected(_on_animation_finished):
agent.anim_player.animation_finished.connect(_on_animation_finished)
if runtime_timer and not runtime_timer.is_stopped():
runtime_timer.stop()
run_animation()
func exit() -> void:
super.exit()
if agent.anim_player and agent.anim_player.animation_finished.is_connected(_on_animation_finished):
agent.anim_player.animation_finished.disconnect(_on_animation_finished)
func _on_animation_finished(anim_name: StringName) -> void:
if animation_name == anim_name:
if not reverse:
if min_wait_time > 0:
var wait_time := randf_range(min_wait_time, max_wait_time)
runtime_timer.start(wait_time)
else:
_on_timer_timeout()
else:
transitioned.emit(self, get_next_state())
func _on_timer_timeout() -> void:
reverse = true
if agent.anim_player and agent.anim_player.has_animation(animation_name):
agent.anim_player.play_backwards(animation_name, blend_time)
else:
transitioned.emit(self, get_next_state())

View File

@@ -0,0 +1 @@
uid://dty1p02kqviwf

View File

@@ -4,11 +4,6 @@ extends Node3D
const CHUNK_TYPE_BIOME: int = 0
const CHUNK_TYPE_STRAIGHT_TRACK: int = 1
const CHUNK_TYPE_CURVED_TRACK: int = 2
const ENTITY_TYPE_HUMANOID: int = 0
const ENTITY_TYPE_ANIMAL: int = 1
const ENTITY_SPAWN_ANY: int = 0
const ENTITY_SPAWN_HUMANOID_ONLY: int = 1
const ENTITY_SPAWN_ANIMAL_ONLY: int = 2
const CHUNK_GENERATION_FRAME_BUDGET_USEC: int = 1000 #2 ms/frame to generate chunks
const CHUNK_CLEANUP_FRAME_BUDGET_USEC: int = 1000 #1 ms/frame per cleanup
@@ -91,7 +86,7 @@ const RIVER_NEIGHBOUR_OFFSETS: Dictionary = {
##max cells to search around a lamppost chunk
@export_range(1, 6, 1) var lamppost_search_radius_cells: int = 3
##max allowed distance between lamppost pairs
@export var lamppost_max_wire_distance: float = 60.0
@export var lamppost_max_wire_distance: float = 35.0
##if true wire connections blocked by colliders are discarded
@export var lamppost_obstacle_check_enabled: bool = true
@@ -922,11 +917,10 @@ func _spawn_entities_for_chunk(root: Node, biome_name: String) -> void:
func _get_spawn_point_type_filter(spawn_point: Node) -> int:
if "allowed_type" in spawn_point:
match spawn_point.allowed_type:
ENTITY_SPAWN_HUMANOID_ONLY:
return ENTITY_TYPE_HUMANOID
ENTITY_SPAWN_ANIMAL_ONLY:
return ENTITY_TYPE_ANIMAL
if spawn_point.allowed_type == 0:
return -1
else:
return spawn_point.allowed_type - 1
return -1
func _pick_compatible_entity(biome_name: String, type_filter: int) -> PackedScene:

View File

@@ -1,7 +1,7 @@
extends Marker3D
class_name EntitySpawnPoint
enum AllowedType { ANY, HUMANOID_ONLY, ANIMAL_ONLY }
enum AllowedType { ANY, FARMER, CITIZEN_WALKER, CITIZEN_SITTER, CAT, CROW, FOX, GOAT, RACOON, WAGYU }
@export var allowed_type: AllowedType = AllowedType.ANY
@export_range(0.0, 1.0, 0.01) var spawn_chance: float = 1.0

View File

@@ -1,7 +1,8 @@
extends Path3D
const STEAM_DISTANCE_STAT: String = "stat_distance_km"
const DISTANCE_KM_PER_UNIT: float = 0.001
const DISTANCE_KM_PER_UNIT: float = 0.01
const STATION_STOP_GROUP: StringName = &"railway_station"
@export_group("Train")
##train speed
@@ -48,6 +49,10 @@ const DISTANCE_KM_PER_UNIT: float = 0.001
@export_group("Train Stops")
##if true the train stop the ran on stops
@export var enable_stops: bool = true
##if true the train only stops on markers with a generated station nearby
@export var require_station_for_stop: bool = true
##max horizontal distance between a stop marker and a station chunk
@export var station_stop_detection_radius: float = 35.0
##time of stop
@export var stop_time: float = 4.0
##distance when the train start to brake
@@ -83,17 +88,23 @@ var environment_config: EnvironmentConfig
var wagon_instances: Array[Node3D] = []
var wagon_progress_offsets: Array[float] = []
var _pending_steam_distance_km: float = 0.0
var _initial_is_inmotion: bool = true
var _is_photo_mode_active: bool = false
func _ready() -> void:
randomize()
GameState.on_enable_photo_mode_request.connect(func(): _is_photo_mode_active = true)
GameState.on_disable_photo_mode_request.connect(func(): _is_photo_mode_active = false)
_cache_environment_config()
_initial_is_inmotion = is_inmotion
if curve != null and curve.get_baked_length() > 0:
build_rails()
build_train()
_plan_stops()
_apply_initial_train_start()
_apply_train_start_delay()
else:
print("WARNING: Draw Path3D for rails!")
@@ -123,21 +134,51 @@ func _apply_initial_train_start() -> void:
if total_length <= 0.0:
return
#start from a random position
if environment_config != null and environment_config.train_start_from_random_position:
train_progress = randf() * total_length
_update_next_stop_index_from_progress()
elif environment_config != null and not stop_offset.is_empty():
#start from a specific stop
var stop_index: int = clampi(environment_config.train_start_stop_index, 0, stop_offset.size() - 1)
train_progress = stop_offset[stop_index]
_set_next_stop_index_from_current(stop_index)
if environment_config != null:
match environment_config.train_start_from_random_position:
EnvironmentConfig.TrainStartMode.RANDOM_POSITION:
train_progress = randf() * total_length
_update_next_stop_index_from_progress()
EnvironmentConfig.TrainStartMode.SPECIFIED_STATION:
if stop_offset.is_empty():
train_progress = wrapf(train_progress, 0.0, total_length)
_update_next_stop_index_from_progress()
else:
var stop_index: int = clampi(environment_config.train_start_stop_index, 0, stop_offset.size() - 1)
train_progress = stop_offset[stop_index]
_set_next_stop_index_from_current(stop_index)
EnvironmentConfig.TrainStartMode.SPECIFIED_POSITION:
train_progress = wrapf(environment_config.train_start_position, 0.0, total_length)
_update_next_stop_index_from_progress()
else:
train_progress = wrapf(train_progress, 0.0, total_length)
_update_next_stop_index_from_progress()
_snap_train_to_progress()
func _apply_train_start_delay() -> void:
if not _initial_is_inmotion:
return
var should_start_after_delay: bool = true
var start_delay_seconds: float = 0.0
if environment_config != null:
should_start_after_delay = environment_config.train_start_after_delay
start_delay_seconds = maxf(environment_config.train_start_delay_seconds, 0.0)
if start_delay_seconds <= 0.0:
if not should_start_after_delay:
is_inmotion = false
return
is_inmotion = false
await get_tree().create_timer(start_delay_seconds).timeout
if not is_inside_tree():
return
if not should_start_after_delay:
return
is_inmotion = _initial_is_inmotion
func _set_next_stop_index_from_current(current_stop_index: int) -> void:
if stop_offset.is_empty():
next_stop_index = 0
@@ -251,6 +292,9 @@ func build_rails() -> void:
rail_piece.add_child(rail_dx)
func _plan_stops() -> void:
stop_offset.clear()
stops_position.clear()
var current_stops = []
for child in get_children():
if child is Marker3D:
@@ -264,10 +308,63 @@ func _plan_stops() -> void:
stop_offset.append(data["offset"])
stops_position.append(data["position"])
func _advance_next_stop_index(go_forward: bool) -> void:
if stop_offset.is_empty():
next_stop_index = 0
return
if go_forward:
next_stop_index += 1
if next_stop_index >= stop_offset.size():
next_stop_index = 0
else:
next_stop_index -= 1
if next_stop_index < 0:
next_stop_index = stop_offset.size() - 1
func _find_next_valid_stop(go_forward: bool) -> bool:
if stop_offset.is_empty():
return false
for i in range(stop_offset.size()):
if _is_stop_valid(next_stop_index):
return true
_advance_next_stop_index(go_forward)
return false
func _is_stop_valid(stop_index: int) -> bool:
if not require_station_for_stop:
return true
if stop_index < 0 or stop_index >= stops_position.size():
return false
return _has_station_near_position(stops_position[stop_index])
func _has_station_near_position(stop_position: Vector3) -> bool:
var radius_sq := station_stop_detection_radius * station_stop_detection_radius
for station in get_tree().get_nodes_in_group(STATION_STOP_GROUP):
var station_node := station as Node3D
if station_node == null or not is_instance_valid(station_node):
continue
var delta := station_node.global_position - stop_position
var horizontal_dist_sq := delta.x * delta.x + delta.z * delta.z
if horizontal_dist_sq <= radius_sq:
return true
return false
func _input(event: InputEvent) -> void:
if _is_photo_mode_active: return
if EnvironmentManagerRoot.is_keyboard_input_blocked(get_tree()):
return
if event is InputEventKey and event.pressed and not event.echo:
if event.keycode == KEY_T:
_goto_next_stop()
if event.is_action_pressed("train_horn"):
UIEvents.toot_toot.emit(true)
#elif event.keycode == KEY_F:
#_test_manual_fireworks()
@@ -293,6 +390,9 @@ func _test_manual_fireworks() -> void:
func _goto_next_stop() -> void:
if stop_offset.size() == 0 or stop_ongoing or is_restarting:
return
if not _find_next_valid_stop(train_speed >= 0.0):
return
var target_offset = stop_offset[next_stop_index]
train_progress = target_offset
_execute_stop(train_speed >= 0)
@@ -302,12 +402,13 @@ func _physics_process(delta: float) -> void:
train_move(delta)
func input_controls_management(delta: float) -> void:
if not is_inmotion: return
if Input.is_action_pressed("ui_up"):
if EnvironmentManagerRoot.is_keyboard_input_blocked(get_tree()): return
if not is_inmotion or _is_photo_mode_active: return
if Input.is_action_pressed("train_speed_up"):
train_speed += manual_acceleration * delta
elif Input.is_action_pressed("ui_down"):
elif Input.is_action_pressed("train_speed_down"):
train_speed -= manual_acceleration * delta
elif Input.is_action_pressed("ui_text_backspace"):
elif Input.is_action_pressed("train_stop"):
train_speed = 0
train_speed = clamp(train_speed, speed_min, speed_max)
@@ -318,15 +419,20 @@ func train_move(delta: float) -> void:
if not stop_ongoing:
var last_progress = train_progress
var has_valid_stop := false
if enable_stops and stop_offset.size() > 0 and not is_restarting:
var target_offset = stop_offset[next_stop_index]
var dist = target_offset - train_progress
dist = wrapf(dist + total_length / 2.0, 0.0, total_length) - total_length / 2.0
if abs(dist) < brake_distance and sign(dist) == sign(train_speed):
var t = abs(dist) / brake_distance
stop_multiply = max(smoothstep(0.0, 1.0, t), 0.05)
has_valid_stop = _find_next_valid_stop(train_speed >= 0.0)
if has_valid_stop:
var target_offset = stop_offset[next_stop_index]
var dist = target_offset - train_progress
dist = wrapf(dist + total_length / 2.0, 0.0, total_length) - total_length / 2.0
if abs(dist) < brake_distance and sign(dist) == sign(train_speed):
var t = abs(dist) / brake_distance
stop_multiply = max(smoothstep(0.0, 1.0, t), 0.05)
else:
stop_multiply = 1.0
else:
stop_multiply = 1.0
@@ -334,7 +440,7 @@ func train_move(delta: float) -> void:
train_progress += current_speed * delta
_track_steam_distance(abs(current_speed) * delta)
if enable_stops and stop_offset.size() > 0:
if enable_stops and stop_offset.size() > 0 and has_valid_stop:
var target_offset = stop_offset[next_stop_index]
var exceeded_forward = (current_speed > 0 and last_progress < target_offset and train_progress >= target_offset)
var exceeded_back = (current_speed < 0 and last_progress > target_offset and train_progress <= target_offset)
@@ -392,7 +498,14 @@ func train_move(delta: float) -> void:
#Calculate train distance for steam stats
func _track_steam_distance(distance_units: float) -> void:
if distance_units <= 0.0 or not SteamManager.is_on_steam:
if distance_units <= 0.0:
return
# Always track the global distance in our save file (for UI and persistency)
GameState.save_data.total_distance_km += distance_units * DISTANCE_KM_PER_UNIT
# Steam specific logic
if not SteamManager.is_on_steam:
return
_pending_steam_distance_km += distance_units * DISTANCE_KM_PER_UNIT
@@ -414,19 +527,16 @@ func _check_distance_achievements(total_distance_km: int) -> void:
AchievementManager.unlock("ACH_DISTANCE_200")
func _execute_stop(go_forward: bool = true) -> void:
if not _find_next_valid_stop(go_forward):
stop_multiply = 1.0
return
stop_ongoing = true
stop_multiply = 0.0
var current_stop_index = next_stop_index
if go_forward:
next_stop_index += 1
if next_stop_index >= stop_offset.size():
next_stop_index = 0
else:
next_stop_index -= 1
if next_stop_index < 0:
next_stop_index = stop_offset.size() - 1
_advance_next_stop_index(go_forward)
if fireworks_scene != null:
var marker_position = stops_position[current_stop_index]

View File

@@ -1,5 +1,5 @@
shader_type spatial;
render_mode blend_mix, depth_draw_opaque, cull_disabled;
render_mode blend_mix, depth_draw_opaque, cull_disabled, shadows_disabled;
//Wire color
uniform vec4 albedo_color : source_color = vec4(0.1, 0.1, 0.1, 1.0);

View File

@@ -5,3 +5,4 @@
[resource]
render_priority = 0
shader = ExtResource("1_6saq1")
shader_parameter/albedo_color = Color(0.1, 0.1, 0.1, 1)

View File

@@ -24,8 +24,6 @@ signal camera_changed(camera: Camera3D)
var is_zoomed : bool = false
var zoom_tween : Tween
var is_moving_enabled : bool = true
var is_cinematic_mode : bool = false
var cinematic_timer : float = 0.0
var cinematic_index : int = 0
@@ -34,6 +32,8 @@ var array_camera : Array[Camera3D] = []
var initial_pivot_transformation : Transform3D
func _ready():
UIEvents.change_camera_request.connect(on_change_camera_request)
if pivot:
initial_pivot_transformation = pivot.transform
@@ -46,111 +46,90 @@ func _ready():
if camera_iso:
set_camera(camera_iso)
func sync_zoom(new_size: float, new_fov: float, photo_is_zoomed: bool = false) -> void:
if camera_iso:
if zoom_tween and zoom_tween.is_valid():
zoom_tween.kill()
camera_iso.size = new_size
camera_iso.fov = new_fov
is_zoomed = photo_is_zoomed
var target_size = zoom_size if is_zoomed else normal_size
if not is_equal_approx(camera_iso.size, target_size):
zoom_tween = create_tween()
zoom_tween.set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
zoom_tween.tween_property(camera_iso, "size", target_size, zoom_time)
zoom_tween.parallel().tween_property(camera_iso, "fov", target_size, zoom_time)
func set_camera(camera: Camera3D):
camera.make_current()
emit_signal("camera_changed", camera)
func _input(event):
if event is InputEventKey and event.pressed and not event.echo:
#R-> Reset isometric camera
if event.keycode == KEY_R and is_moving_enabled and pivot:
pivot.transform = initial_pivot_transformation
print("Isometric camera resetted!")
return
func _process(delta: float) -> void:
var current_cam = get_viewport().get_camera_3d()
var is_photo_mode = current_cam != null and not current_cam in array_camera
if not is_photo_mode:
if is_cinematic_mode and array_camera.size() > 0:
cinematic_timer += delta
if cinematic_timer >= change_camera_time:
cinematic_timer = 0.0
cinematic_index = (cinematic_index + 1) % array_camera.size()
var next_cam = array_camera[cinematic_index]
set_camera(next_cam)
#C-> Toggle cinematic mode
if event.keycode == KEY_C:
is_cinematic_mode = !is_cinematic_mode
if is_cinematic_mode:
cinematic_timer = 0.0
for i in range(array_camera.size()):
if array_camera[i].current:
cinematic_index = i
break
print("Cinematic Mode: enabled")
else:
print("Cinematic Mode: disabled")
return
#Z-> soft zoom
if event.keycode == KEY_Z and camera_iso:
is_zoomed = !is_zoomed
var target_size = zoom_size if is_zoomed else normal_size
if zoom_tween and zoom_tween.is_valid():
zoom_tween.kill()
zoom_tween = create_tween()
zoom_tween.set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
zoom_tween.tween_property(camera_iso, "size", target_size, zoom_time)
return
#manual controls (1-5)
var manual_action = false
if event.keycode == KEY_1 and camera_iso:
set_camera(camera_iso)
is_moving_enabled = true
manual_action = true
elif event.keycode == KEY_2 and camera_front:
set_camera(camera_front)
is_moving_enabled = false
manual_action = true
elif event.keycode == KEY_3 and camera_side1:
set_camera(camera_side1)
is_moving_enabled = false
manual_action = true
elif event.keycode == KEY_4 and camera_side2:
set_camera(camera_side2)
is_moving_enabled = false
manual_action = true
elif event.keycode == KEY_5 and camera_top:
set_camera(camera_top)
is_moving_enabled = false
manual_action = true
if manual_action and is_cinematic_mode:
is_cinematic_mode = false
print("Cinematic Mode: Disabled")
if is_moving_enabled and pivot:
if event is InputEventMouseMotion and Input.is_mouse_button_pressed(MOUSE_BUTTON_RIGHT):
pivot.rotate_y(deg_to_rad(-event.relative.x * rotation_speed))
func _process(delta):
if is_cinematic_mode and array_camera.size() > 0:
cinematic_timer += delta
if cinematic_timer >= change_camera_time:
cinematic_timer = 0.0
cinematic_index = (cinematic_index + 1) % array_camera.size()
var next_cam = array_camera[cinematic_index]
set_camera(next_cam)
is_moving_enabled = (next_cam == camera_iso)
if not is_moving_enabled or pivot == null:
if camera_iso == null or current_cam != camera_iso:
return
var input_dir = Vector3.ZERO
if Input.is_key_pressed(KEY_W): input_dir.z -= 1
if Input.is_key_pressed(KEY_S): input_dir.z += 1
if Input.is_key_pressed(KEY_A): input_dir.x -= 1
if Input.is_key_pressed(KEY_D): input_dir.x += 1
if input_dir != Vector3.ZERO:
input_dir = input_dir.normalized()
if Input.is_action_just_pressed("zoom_in"):
if is_zoomed == false:
return
is_zoomed = false
var target_size = normal_size
var forward = pivot.transform.basis.z
var right = pivot.transform.basis.x
forward.y = 0
right.y = 0
if zoom_tween and zoom_tween.is_valid():
zoom_tween.kill()
zoom_tween = create_tween()
zoom_tween.set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
zoom_tween.tween_property(camera_iso, "size", target_size, zoom_time)
zoom_tween.parallel().tween_property(camera_iso, "fov", target_size, zoom_time)
elif Input.is_action_just_pressed("zoom_out"):
if is_zoomed == true:
return
is_zoomed = true
var target_size = zoom_size
forward = forward.normalized()
right = right.normalized()
if zoom_tween and zoom_tween.is_valid():
zoom_tween.kill()
zoom_tween = create_tween()
zoom_tween.set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
zoom_tween.tween_property(camera_iso, "size", target_size, zoom_time)
zoom_tween.parallel().tween_property(camera_iso, "fov", target_size, zoom_time)
func on_change_camera_request(camera_index: int) -> void:
var next_cam = array_camera[camera_index]
set_camera(next_cam)
func _unhandled_input(event: InputEvent) -> void:
var current_cam = get_viewport().get_camera_3d()
var is_photo_mode = current_cam != null and not current_cam in array_camera
if is_photo_mode:
return
var motion = (forward * input_dir.z + right * input_dir.x)
pivot.position += motion * move_speed * delta
if event is InputEventKey and event.pressed and not event.echo:
match event.keycode:
KEY_1:
if array_camera.size() > 0: set_camera(array_camera[0])
KEY_2:
if array_camera.size() > 1: set_camera(array_camera[1])
KEY_3:
if array_camera.size() > 2: set_camera(array_camera[2])
KEY_4:
if array_camera.size() > 3: set_camera(array_camera[3])
KEY_5:
if array_camera.size() > 4: set_camera(array_camera[4])

View File

@@ -12,6 +12,10 @@ var environment_config: EnvironmentConfig
@export var time_scale: float = 1.0
@export var paused: bool = false
var _time_tween: Tween
var time_transition_duration: float = 2
signal time_changed(time: float)
var current_time: float = 0.0
@@ -26,6 +30,7 @@ func _ready() -> void:
UIEvents.toggle_pause_daytime.connect(_on_toggle_pause_daytime)
UIEvents.time_option_item_changed.connect(_time_option_changed)
paused = environment_config.start_day_time_paused
current_time = environment_config.start_time
update_time(current_time)
@@ -67,16 +72,49 @@ func get_time_option_index(currtime: float) -> int:
return TIME_OPTION_DAY
return TIME_OPTION_SUNSET
func _time_option_changed(index: int) -> void:
var target_time: float = 0.0
match index:
TIME_OPTION_SUNRISE:
set_time(environment_config.sunrise)
target_time = environment_config.sunrise
TIME_OPTION_DAY:
set_time(environment_config.day)
target_time = environment_config.day
TIME_OPTION_SUNSET:
set_time(environment_config.sunset)
target_time = environment_config.sunset
TIME_OPTION_NIGHT:
set_time(environment_config.night)
target_time = environment_config.night
if _time_tween:
_time_tween.kill()
_time_tween = create_tween()
var start_time = current_time
# Gestione logica lineare: Notte(0.0) - Mattina(0.25) - Giorno(0.45) - Tramonto(0.8) - Notte(1.0)
# Per evitare di attraversare fasi intermedie opposte, forziamo il percorso su questo segmento.
if index == TIME_OPTION_NIGHT:
# Da Mattina a Notte -> andiamo a 0.0. Dal Giorno in poi -> andiamo a 1.0.
if start_time < environment_config.day:
target_time = 0.0
else:
target_time = 1.0
else:
# Se partiamo da Notte (valori vicini a 0.0 o 1.0)
if start_time < 0.1 or start_time > 0.9:
if index == TIME_OPTION_SUNRISE:
# Per andare a Mattina, partiamo dal lato 0.0
if start_time > 0.9:
start_time -= 1.0
else:
# Per andare a Giorno o Tramonto, partiamo dal lato 1.0
if start_time < 0.1:
start_time += 1.0
_time_tween.tween_method(set_time, start_time, target_time, time_transition_duration)
func _on_set_day_time(value: float) -> void:
set_time(value)

View File

@@ -7,6 +7,14 @@ const DYNAMIC_ENVIRONMENT_UPDATES_PER_FRAME: int = 32 #how many update of the en
@export var environment_config: EnvironmentConfig
@export_group("Input")
@export var block_keyboard_input: bool = false:
set(value):
if block_keyboard_input == value:
return
block_keyboard_input = value
_apply_keyboard_input_block()
@export_group("Camera")
@export var camera: Camera3D
@export var camera_pivot: Node3D
@@ -39,8 +47,25 @@ var weather_controller: WeatherController
var day_tween: Tween
var day_time: float = 0.0
var pending_environment_nodes: Dictionary = {}
var weather_shader_no_noise: Material
var _blocked_keyboard_events_by_action: Dictionary = {}
static func is_keyboard_input_blocked(tree: SceneTree) -> bool:
if tree == null:
return false
for node in tree.get_nodes_in_group("keyboard_input_blocker"):
var environment_manager := node as EnvironmentManagerRoot
if environment_manager != null and environment_manager.block_keyboard_input:
return true
return false
func _enter_tree() -> void:
add_to_group("keyboard_input_blocker")
func _ready() -> void:
_apply_keyboard_input_block()
#connect shader when new node is added
get_tree().node_added.connect(_on_tree_node_added)
@@ -80,12 +105,57 @@ func _ready() -> void:
weather_controller.name = "WeatherController"
add_child(weather_controller)
if day_night_controller != null:
select_day_time(day_night_controller.current_time)
func _process(_delta: float) -> void:
_process_pending_environment_nodes()
func _input(event: InputEvent) -> void:
if block_keyboard_input and event is InputEventKey:
get_viewport().set_input_as_handled()
func _exit_tree() -> void:
_restore_keyboard_action_events()
remove_from_group("keyboard_input_blocker")
func flush_pending_environment_nodes() -> void:
_process_pending_environment_nodes(-1)
func _apply_keyboard_input_block() -> void:
if block_keyboard_input:
_remove_keyboard_action_events()
else:
_restore_keyboard_action_events()
func _remove_keyboard_action_events() -> void:
if not _blocked_keyboard_events_by_action.is_empty():
return
for action in InputMap.get_actions():
var keyboard_events: Array[InputEvent] = []
for event in InputMap.action_get_events(action):
if event is InputEventKey:
keyboard_events.append(event)
if keyboard_events.is_empty():
continue
_blocked_keyboard_events_by_action[action] = keyboard_events
Input.action_release(action)
for keyboard_event in keyboard_events:
InputMap.action_erase_event(action, keyboard_event)
func _restore_keyboard_action_events() -> void:
for action in _blocked_keyboard_events_by_action.keys():
if not InputMap.has_action(action):
continue
for keyboard_event in _blocked_keyboard_events_by_action[action]:
InputMap.action_add_event(action, keyboard_event)
_blocked_keyboard_events_by_action.clear()
func _on_tree_node_added(node: Node) -> void:
if node.is_in_group("wind_node") or node.is_in_group("weather_node") or node.is_in_group("weather_vegetables_node"):
_queue_dynamic_environment_node(node)
@@ -135,10 +205,10 @@ func _apply_dynamic_environment_materials(node: Node) -> void:
if node.is_in_group("wind_node"):
_apply_wind_noise_to_node(node, NOISE_TEXTURE)
if node.is_in_group("weather_node"):
_apply_weather_overlay_to_node(node, WEATHER_SHADER)
if node.is_in_group("weather_node") or node.is_in_group("weather_vegetables_node"):
_apply_weather_overlay_to_node(node, _get_weather_overlay_material(node))
if _should_clear_weather_overlay(node):
if _should_ignore_weather_overlay(node):
_clear_weather_overlay_from_node(node)
func ApplyWindNoiseToMaterials():
@@ -162,19 +232,30 @@ func _apply_wind_noise_to_node(node: Node, noise_tex: Texture2D) -> void:
func ApplyWeatherShaderToMaterials():
for node in get_tree().get_nodes_in_group("weather_node"):
_apply_weather_overlay_to_node(node, WEATHER_SHADER)
_apply_weather_overlay_to_node(node, _get_weather_overlay_material(node))
for node in get_tree().get_nodes_in_group("weather_vegetables_node"):
if _should_clear_weather_overlay(node):
_clear_weather_overlay_from_node(node)
_apply_weather_overlay_to_node(node, _get_weather_overlay_material(node))
func _get_weather_overlay_material(node: Node) -> Material:
if not node.is_in_group("weather_overlay_no_noise"):
return WEATHER_SHADER
if weather_shader_no_noise == null:
weather_shader_no_noise = WEATHER_SHADER.duplicate() as Material
var shader_material := weather_shader_no_noise as ShaderMaterial
if shader_material:
shader_material.set_shader_parameter("snow_noise_enabled", false)
return weather_shader_no_noise
func _apply_weather_overlay_to_node(node: Node, material: Material) -> void:
if _should_clear_weather_overlay(node):
if _should_ignore_weather_overlay(node):
_clear_weather_overlay_from_node(node)
return
if node is GeometryInstance3D:
if _geometry_uses_alpha_texture(node):
if _should_clear_weather_overlay(node) or _geometry_uses_alpha_texture(node):
node.material_overlay = null
else:
node.material_overlay = material
@@ -214,6 +295,9 @@ func _shader_material_uses_alpha_texture(material: ShaderMaterial) -> bool:
return material.shader.code.find("alpha_texture") != -1
func _should_ignore_weather_overlay(node: Node) -> bool:
return node.is_in_group("weather_overlay_ignore")
func _should_clear_weather_overlay(node: Node) -> bool:
return node.is_in_group("weather_vegetables_node")
@@ -233,7 +317,7 @@ func select_day_time(normalized_time: float) -> void:
if normalized_time < environment_config.sunrise:
#Sunrise: night → morning
day_time = 3.0 - (normalized_time / environment_config.sunrise) * 2.0 # 3.0 → 1.0
day_time = 3.0 + (normalized_time / environment_config.sunrise) * 1.0 # 3.0 → 4.0
elif normalized_time < environment_config.day:
#Morning: morning → afternoon
var t: float = (normalized_time - environment_config.sunrise) / (environment_config.day - environment_config.sunrise)

View File

@@ -20,13 +20,13 @@ render_priority = 0
shader = ExtResource("1_qxph4")
shader_parameter/noise_texture = SubResource("NoiseTexture2D_kavln")
shader_parameter/ray_color = Color(1, 0.78431374, 0.27058825, 1)
shader_parameter/base_alpha = 1.0
shader_parameter/noise_stretching = 3.17200010317
shader_parameter/base_alpha = 0.150000007125
shader_parameter/noise_stretching = 3.000000095
shader_parameter/noise_scale = 1.0
shader_parameter/scrolling_speed = Vector2(0, 0.15)
shader_parameter/depth_softness = 1.0
shader_parameter/edge_fade_power = 2.0
shader_parameter/intensity_multiplier = 0.5330000253175
shader_parameter/intensity_multiplier = 0.50000002375
[node name="GodRay" type="Node3D" unique_id=1679441931]
script = ExtResource("2_v3yr3")

View File

@@ -13,6 +13,7 @@ global uniform float global_snow_accumulation_speed = 0.005;
global uniform float global_snow_melt_time = -1.0;
global uniform float global_snow_melt_speed = 0.1;
global uniform float global_snow_amount = 0.0;
global uniform vec4 global_snow_color = vec4(0.92, 0.96, 1.0, 1.0);
global uniform float global_rain_intensity;
// --- PARAMETRI ESTETICI ---
@@ -133,7 +134,7 @@ void fragment() {
// Applichiamo la variazione al colore finale dell'erba
vec3 varied_grass_color = mix(v_final_color, variance_color.rgb, noise_sample * variance_intensity);
float snow_amount = smoothstep(0.0, 1.0, get_snow_progress());
float snow_amount = pow(get_snow_progress(), 0.55);
float top_mask = 1.0 - shifted_uv.y;
float snow_start = 1.0 - clamp(snow_coverage, 0.05, 1.0);
@@ -141,8 +142,9 @@ void fragment() {
snow_mask *= step(0.01, snow_amount);
snow_mask = clamp(snow_mask, 0.0, 1.0);
vec3 dark_snow = snow_color.rgb * (1.0 - shadow_intensity);
vec3 shaded_snow = mix(dark_snow, snow_color.rgb, v_shade_factor);
vec3 snow_base_color = max(snow_color.rgb, global_snow_color.rgb);
float snow_light = mix(0.82, 1.0, max(v_shade_factor, 0.35));
vec3 shaded_snow = clamp(snow_base_color * snow_light, 0.0, 1.0);
// Mescoliamo il colore variato con la neve
vec3 final_albedo = mix(varied_grass_color, shaded_snow, snow_mask);

View File

@@ -111,8 +111,8 @@ void fragment() {
float snow_mask = smoothstep(1.0 - snow_amount * 1.35, 1.08 - snow_amount * 1.35, top_mask) * snow_visibility;
snow_mask *= step(0.01, snow_amount);
vec3 dark_snow = global_snow_color.rgb * (1.0 - shadow_intensity);
vec3 shaded_snow = mix(dark_snow, global_snow_color.rgb, v_shade_factor);
float snow_light = mix(0.82, 1.0, max(v_shade_factor, 0.35));
vec3 shaded_snow = clamp(global_snow_color.rgb * snow_light, 0.0, 1.0);
vec3 final_albedo = mix(v_final_color, shaded_snow, snow_mask);
// Rain wetness: darken and make shinier

View File

@@ -53,7 +53,7 @@ var is_storm: bool = false
var cold_tween: Tween
var wind_tween: Tween
var is_windy: bool = false
var thereare_fireflies: bool = false
var thereare_fireflies: bool = true
var current_wind_speed: float = 0.0
var current_wind_strength: float = 0.0
var current_wind_fade: float = 0.0
@@ -128,10 +128,8 @@ func _process(delta: float) -> void:
_follow_camera()
var is_night = day_time >= 2.5
if particles_fireflies:
particles_fireflies.emitting = thereare_fireflies and is_night and not is_raining and not is_snowing and not is_storm
_update_fireflies_visibility()
var base_tint: Color
var base_sky_top: Color
var base_sky_horizon: Color
@@ -172,7 +170,7 @@ func _process(delta: float) -> void:
base_grad_intensity = lerp(environment_config.grad_intensity_morning, environment_config.grad_intensity_afternoon, t)
base_water_color = environment_config.water_color_morning.lerp(environment_config.water_color_afternoon, t)
base_rotation_sun = environment_config.sun_rotation_morning.lerp(environment_config.sun_rotation_afternoon, t)
else:
elif day_time <= 3.0:
var t = day_time - 2.0
base_tint = environment_config.afternoon_color.lerp(environment_config.night_color, t)
base_sky_top = environment_config.sky_top_afternoon.lerp(environment_config.sky_top_night, t)
@@ -186,6 +184,20 @@ func _process(delta: float) -> void:
base_grad_intensity = lerp(environment_config.grad_intensity_afternoon, environment_config.grad_intensity_night, t)
base_water_color = environment_config.water_color_afternoon.lerp(environment_config.water_color_night, t)
base_rotation_sun = environment_config.sun_rotation_afternoon.lerp(environment_config.sun_rotation_night, t)
else:
var t = day_time - 3.0
base_tint = environment_config.night_color.lerp(environment_config.morning_color, t)
base_sky_top = environment_config.sky_top_night.lerp(environment_config.sky_top_morning, t)
base_sky_horizon = environment_config.sky_horizon_night.lerp(environment_config.sky_horizon_morning, t)
base_fog_color = environment_config.fog_color_night.lerp(environment_config.fog_color_morning, t)
base_fog_density = lerp(environment_config.fog_density_night, environment_config.fog_density_morning, t)
base_bloom = lerp(environment_config.glow_night, environment_config.glow_morning, t)
base_exposure = lerp(environment_config.exposure_night, environment_config.exposure_morning, t)
base_grad_top = environment_config.grad_top_night.lerp(environment_config.grad_top_morning, t)
base_grad_bot = environment_config.grad_bot_night.lerp(environment_config.grad_bot_morning, t)
base_grad_intensity = lerp(environment_config.grad_intensity_night, environment_config.grad_intensity_morning, t)
base_water_color = environment_config.water_color_night.lerp(environment_config.water_color_morning, t)
base_rotation_sun = environment_config.sun_rotation_night.lerp(environment_config.sun_rotation_morning, t)
var weather_color = environment_config.rain_mode_color
if is_storm:
@@ -197,11 +209,9 @@ func _process(delta: float) -> void:
var final_fog_color = base_fog_color.lerp(base_fog_color * weather_color, clamp(rain_intensity, 0.0, 1.0))
var final_fog_density = lerp(base_fog_density, base_fog_density * 4.0, clamp(rain_intensity, 0.0, 1.0))
var final_water_color = base_water_color.darkened(clamp(environment_config.water_darkening_rain, 0.0, 1.0) * clamp(rain_intensity, 0.0, 1.0))
var rain_weather_amount: float = 0.0
if is_raining:
rain_weather_amount = clamp(rain_intensity, 0.0, 1.0)
var rain_weather_amount: float = clamp(rain_intensity, 0.0, 1.0)
var storm_weather_amount: float = 0.0
if is_raining and is_storm:
if is_storm:
if environment_config.storm_rain_intensity_multiplier > 1.0:
storm_weather_amount = clamp((rain_intensity - 1.0) / (environment_config.storm_rain_intensity_multiplier - 1.0), 0.0, 1.0)
else:
@@ -316,26 +326,30 @@ func create_sound_players():
func _get_rain_day_color() -> Color:
if day_time <= 2.0:
return environment_config.rain_morning_color.lerp(environment_config.rain_afternoon_color, day_time - 1.0)
return environment_config.rain_afternoon_color.lerp(environment_config.rain_night_color, day_time - 2.0)
elif day_time <= 3.0:
return environment_config.rain_afternoon_color.lerp(environment_config.rain_night_color, day_time - 2.0)
return environment_config.rain_night_color.lerp(environment_config.rain_morning_color, day_time - 3.0)
func _get_storm_day_color() -> Color:
if day_time <= 2.0:
return environment_config.storm_morning_color.lerp(environment_config.storm_afternoon_color, day_time - 1.0)
return environment_config.storm_afternoon_color.lerp(environment_config.storm_night_color, day_time - 2.0)
elif day_time <= 3.0:
return environment_config.storm_afternoon_color.lerp(environment_config.storm_night_color, day_time - 2.0)
return environment_config.storm_night_color.lerp(environment_config.storm_morning_color, day_time - 3.0)
func _get_rain_day_exposure() -> float:
if day_time <= 2.0:
return lerp(environment_config.rain_exposure_morning, environment_config.rain_exposure_afternoon, day_time - 1.0)
return lerp(environment_config.rain_exposure_afternoon, environment_config.rain_exposure_night, day_time - 2.0)
elif day_time <= 3.0:
return lerp(environment_config.rain_exposure_afternoon, environment_config.rain_exposure_night, day_time - 2.0)
return lerp(environment_config.rain_exposure_night, environment_config.rain_exposure_morning, day_time - 3.0)
func _get_storm_day_exposure() -> float:
if day_time <= 2.0:
return lerp(environment_config.storm_exposure_morning, environment_config.storm_exposure_afternoon, day_time - 1.0)
return lerp(environment_config.storm_exposure_afternoon, environment_config.storm_exposure_night, day_time - 2.0)
elif day_time <= 3.0:
return lerp(environment_config.storm_exposure_afternoon, environment_config.storm_exposure_night, day_time - 2.0)
return lerp(environment_config.storm_exposure_night, environment_config.storm_exposure_morning, day_time - 3.0)
#region camera
func _set_camera(curr_camera: Camera3D):
@@ -389,9 +403,7 @@ func _follow_camera() -> void:
func toggle_fireflies(value: bool):
thereare_fireflies = value
var is_night = day_time >= 2.5
if particles_fireflies:
particles_fireflies.emitting = thereare_fireflies and is_night and not is_raining
_update_fireflies_visibility()
#disable fireflies and set default values and materials
func init_fireflies():
@@ -402,7 +414,16 @@ func init_fireflies():
var proc_mat = particles_fireflies.process_material as ParticleProcessMaterial
if proc_mat:
proc_mat.emission_box_extents = Vector3(environment_config.fireflies_spawn_ray, environment_config.fireflies_spawn_height, environment_config.fireflies_spawn_ray)
_update_fireflies_visibility()
func _should_show_fireflies() -> bool:
var is_night: bool = day_time >= 2.5
return thereare_fireflies and is_night and not is_raining and not is_snowing and not is_storm
func _update_fireflies_visibility() -> void:
if particles_fireflies:
particles_fireflies.emitting = _should_show_fireflies()
#endregion
#region Wind
@@ -410,7 +431,7 @@ func init_fireflies():
func toggle_wind(value: bool):
is_windy = value
if particles_wind:
particles_wind.emitting = is_windy
particles_wind.emitting = true
_apply_wind_state()
_emit_weather_event_label()
@@ -420,7 +441,7 @@ func init_wind():
_update_wind_amount_from_strength(environment_config.wind_strength)
if particles_wind:
particles_wind.visible = true
particles_wind.emitting = false
particles_wind.emitting = true
particles_wind.amount = environment_config.wind_amount
var proc_mat_wind = particles_wind.process_material as ParticleProcessMaterial
if proc_mat_wind:
@@ -451,6 +472,11 @@ func _apply_wind_config() -> void:
_apply_wind_state(true)
func _get_target_wind_strength() -> float:
if is_windy:
return environment_config.wind_boost_strength
return environment_config.wind_strength
func _apply_wind_state(immediate: bool = false) -> void:
if environment_config == null:
return
@@ -458,20 +484,23 @@ func _apply_wind_state(immediate: bool = false) -> void:
if wind_tween and wind_tween.is_valid():
wind_tween.kill()
var active_wind_speed := environment_config.wind_speed if is_windy else 0.0
var active_wind_strength := environment_config.wind_strength if is_windy else 0.0
var active_wind_fade := 1.0 if is_windy else 0.0
if particles_wind:
particles_wind.emitting = true
var active_wind_speed := environment_config.wind_speed
var active_wind_strength := _get_target_wind_strength()
var active_wind_fade := 1.0
if immediate:
_set_current_wind_speed(active_wind_speed)
_set_current_wind_strength(active_wind_strength)
_set_current_wind_fade(active_wind_fade)
return
_set_current_wind_speed(environment_config.wind_speed)
_set_current_wind_strength(environment_config.wind_strength)
_set_current_wind_speed(active_wind_speed)
_set_current_wind_fade(active_wind_fade)
wind_tween = create_tween()
wind_tween.tween_method(_set_current_wind_fade, current_wind_fade, active_wind_fade, environment_config.wind_fade_in_out_time)
wind_tween.tween_callback(_finish_wind_fade_out)
wind_tween.tween_method(_set_current_wind_strength, current_wind_strength, active_wind_strength, environment_config.wind_fade_in_out_time)
wind_tween.tween_callback(_finish_wind_transition)
func _set_current_wind_speed(value: float) -> void:
current_wind_speed = value
@@ -481,6 +510,7 @@ func _set_current_wind_speed(value: float) -> void:
func _set_current_wind_strength(value: float) -> void:
current_wind_strength = value
RenderingServer.global_shader_parameter_set("global_wind_strength", value)
_set_wind_particles_amount_from_strength(value)
_sync_wind_event_state()
func _set_current_wind_fade(value: float) -> void:
@@ -494,13 +524,10 @@ func _sync_wind_event_state() -> void:
#used to notify wind_decoration when wind change state
wind_parameters_changed.emit(current_wind_speed, current_wind_strength, current_wind_fade, environment_config.wind_direction)
func _finish_wind_fade_out() -> void:
if is_windy:
return
_set_current_wind_speed(0.0)
_set_current_wind_strength(0.0)
_set_current_wind_fade(0.0)
func _finish_wind_transition() -> void:
_set_current_wind_speed(environment_config.wind_speed)
_set_current_wind_strength(_get_target_wind_strength())
_set_current_wind_fade(1.0)
func change_wind_strength(value: float) -> void:
if environment_config == null:
@@ -508,10 +535,11 @@ func change_wind_strength(value: float) -> void:
environment_config.wind_strength = value
_update_wind_amount_from_strength(value)
if is_windy or current_wind_fade > 0.0:
if current_wind_fade > 0.0 and not is_windy:
_set_current_wind_strength(value)
if particles_wind:
particles_wind.amount = environment_config.wind_amount
_apply_wind_state()
func _update_wind_amount_from_strength(value: float) -> void:
if environment_config == null:
@@ -519,12 +547,22 @@ func _update_wind_amount_from_strength(value: float) -> void:
if max_wind_amount <= 0:
max_wind_amount = max(environment_config.wind_amount, 1)
environment_config.wind_amount = _get_wind_particles_amount_from_strength(value)
func _get_wind_particles_amount_from_strength(value: float) -> int:
if max_wind_amount <= 0:
max_wind_amount = 1
var normalized_strength: float = clamp(value, 0.0, 1.0)
var amount_ratio: float = normalized_strength
if normalized_strength > 0.0 and normalized_strength < 0.3:
amount_ratio = lerp(0.08, 0.25, normalized_strength / 0.3)
environment_config.wind_amount = roundi(max_wind_amount * amount_ratio)
return roundi(max_wind_amount * amount_ratio)
func _set_wind_particles_amount_from_strength(value: float) -> void:
if particles_wind:
particles_wind.amount = _get_wind_particles_amount_from_strength(value)
func trigger_random_weather_event(duration: float = 0.0) -> void:
if random_weather_restore_tween and random_weather_restore_tween.is_valid():

View File

@@ -17,6 +17,7 @@ global uniform float global_snow_cap_flatness_end = 0.96;
global uniform float global_snow_cap_noise_scale = 0.22;
global uniform float global_snow_cap_noise_strength = 0.18;
const float SNOW_VISUAL_RESPONSE = 0.55;
uniform bool snow_noise_enabled = true;
uniform float snow_noise_scale : hint_range(0.01, 1.0) = 0.15;
uniform float snow_edge_softness : hint_range(0.01, 0.5) = 0.2;
uniform float snow_roughness_variation : hint_range(0.0, 0.3) = 0.15;
@@ -92,6 +93,10 @@ float get_visual_snow_progress(float snow_progress) {
}
float get_snow_noise_mask(vec3 world_pos, float snow_progress) {
if (!snow_noise_enabled) {
return 1.0;
}
float detail_noise = texture(noise_texture, world_pos.xz * snow_noise_scale).r;
float broad_noise = texture(noise_texture, world_pos.xz * snow_noise_scale * 0.35 + vec2(19.1, 7.4)).r;
float combined_noise = mix(detail_noise, broad_noise, 0.35);
@@ -118,7 +123,7 @@ void vertex() {
world_normal.y
);
float accumulation_growth = smoothstep(0.02, 0.45, snow_progress);
float cap_noise = fbm(world_pos.xz * global_snow_cap_noise_scale + vec2(11.3, 4.7));
float cap_noise = snow_noise_enabled ? fbm(world_pos.xz * global_snow_cap_noise_scale + vec2(11.3, 4.7)) : 0.5;
float cap_variation = mix(1.0 - global_snow_cap_noise_strength, 1.0 + global_snow_cap_noise_strength, cap_noise);
v_snow_amount = snow_progress;
@@ -133,7 +138,7 @@ void fragment() {
float facing_up = clamp(world_normal.y, 0.0, 1.0);
vec3 geometric_normal = normalize(cross(dFdx(world_pos), dFdy(world_pos)));
float snow_facing_up = max(facing_up, abs(geometric_normal.y));
float noise_val = texture(noise_texture, world_pos.xz * snow_noise_scale).r;
float noise_val = snow_noise_enabled ? texture(noise_texture, world_pos.xz * snow_noise_scale).r : 0.5;
//Snow
float snow_progress = v_snow_amount;

View File

@@ -1,9 +1,12 @@
class_name EnvironmentConfig
extends Resource
enum TrainStartMode { RANDOM_POSITION, SPECIFIED_STATION, SPECIFIED_POSITION }
@export_group("Day")
@export var start_time: float = 0.0 #start time of the day
@export var day_duration: float = 300.0 #Duration of a full day cycle in seconds
@export var start_day_time_paused: bool = false #Start with day time paused, without advancing the day cycle
@export var sunrise: float = 0.25 #day_time 1.0→2.0 (night colors → morning colors)
@export var day: float = 0.45 #day_time 2.0→2.0 (stays morning/afternoon)
@export var sunset: float = 0.80 #day_time 2.0→3.0 (afternoon colors → night colors)
@@ -156,8 +159,12 @@ extends Resource
#Train start settings
@export_group("Train Start")
@export var train_start_from_random_position: bool = true #When enabled the train starts from a random offset on the rail curve instead of a stop
@export_enum("random_position", "specified_station", "specified_position") var train_start_from_random_position: int = TrainStartMode.RANDOM_POSITION #Train start mode
@export_range(0, 64, 1, "or_greater") var train_start_stop_index: int = 1 #Stop index used for the train start when random start is disabled
@export var train_start_position: float = 0.0 #Offset on the rail curve used when train_start_from_random_position is specified_position
@export var train_start_delay_seconds: float = 0.0 #Seconds the train waits before starting at game launch
@export var train_start_after_delay: bool = true #When enabled the train starts after train_start_delay_seconds, otherwise it stays stopped
@export var train_start_acceleration_seconds: float = 4.0 #Seconds used to progressively reach normal train speed after launch
#Snow settings
@export_group("Snow")
@@ -185,7 +192,8 @@ extends Resource
@export var wind_direction: Vector2 = Vector2(0.5, 0.4) #Global wind direction (XZ)
@export var wind_speed: float = 0.2 #Global wind animation speed
@export var wind_scale: float = 0.025 #Global wind noise scale
@export var wind_strength: float = 0.3 #Global wind displacement strength
@export var wind_strength: float = 0.12 #Low ambient wind displacement strength
@export var wind_boost_strength: float = 1.0 #Wind displacement strength while wind event is active
@export var cloud_scale: float = 0.5 #Cloud noise scale in sky shader
@export var cloud_speed: float = 0.05 #Cloud movement speed in sky shader
@export_range(0.01, 1.0) var cloud_scale_envshadows_rate: float = 0.01 #Cloud scale multiplier for environment shadows

Binary file not shown.

View File

@@ -0,0 +1,36 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://d2vn50t5k7xbk"
path="res://.godot/imported/LTMakeup-Regular.otf-3aec1bac2ab646ee8d91792b37ffa3b8.fontdata"
[deps]
source_file="res://core/font/LTMakeup-Regular.otf"
dest_files=["res://.godot/imported/LTMakeup-Regular.otf-3aec1bac2ab646ee8d91792b37ffa3b8.fontdata"]
[params]
Rendering=null
antialiasing=1
generate_mipmaps=false
disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
modulate_color_glyphs=false
hinting=1
subpixel_positioning=4
keep_rounding_remainders=true
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}

View File

@@ -0,0 +1,6 @@
[gd_resource type="Theme" format=3 uid="uid://cwqdjc6t31a8i"]
[ext_resource type="FontFile" uid="uid://d2vn50t5k7xbk" path="res://core/font/LTMakeup-Regular.otf" id="1_itbcg"]
[resource]
default_font = ExtResource("1_itbcg")

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://kvn5l0n11a3q"
path="res://.godot/imported/page.png-6c8405fbc970a849a62cab2019c549ca.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://core/game_menu/assets/page.png"
dest_files=["res://.godot/imported/page.png-6c8405fbc970a849a62cab2019c549ca.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dyvwywse5raqt"
path="res://.godot/imported/1_dx.png-72d52e4e36c6fed20f7226414ff0abd6.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://core/game_menu/assets/page_1/1_dx.png"
dest_files=["res://.godot/imported/1_dx.png-72d52e4e36c6fed20f7226414ff0abd6.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dbpfa1xgxxn8s"
path="res://.godot/imported/1_sx.png-f04965d63490ae436799d59856936013.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://core/game_menu/assets/page_1/1_sx.png"
dest_files=["res://.godot/imported/1_sx.png-f04965d63490ae436799d59856936013.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://d2s020wikunuo"
path="res://.godot/imported/barretta_main.png-d118ead98672de7a9802ba85eaf04053.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://core/game_menu/assets/page_1/barretta_main.png"
dest_files=["res://.godot/imported/barretta_main.png-d118ead98672de7a9802ba85eaf04053.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ct7o3u6i5rka6"
path="res://.godot/imported/barretta_second.png-7f0af7da51c3ebb821e017a3fe148c6e.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://core/game_menu/assets/page_1/barretta_second.png"
dest_files=["res://.godot/imported/barretta_second.png-7f0af7da51c3ebb821e017a3fe148c6e.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://clvc6nlbgyvp1"
path="res://.godot/imported/rings.png-21117a64acb1855b44e3ce941dd421bd.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://core/game_menu/assets/page_1/rings.png"
dest_files=["res://.godot/imported/rings.png-21117a64acb1855b44e3ce941dd421bd.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://drwe2xcnp8vs1"
path="res://.godot/imported/2_dx.png-1c9a95db875176635d05c1084fc67cb1.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://core/game_menu/assets/page_2/2_dx.png"
dest_files=["res://.godot/imported/2_dx.png-1c9a95db875176635d05c1084fc67cb1.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cgllgxrstcoy7"
path="res://.godot/imported/2_sx.png-396d61afe82f03c22efe87c2626240ae.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://core/game_menu/assets/page_2/2_sx.png"
dest_files=["res://.godot/imported/2_sx.png-396d61afe82f03c22efe87c2626240ae.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b6ae0kp1m0x74"
path="res://.godot/imported/3_dx.png-c85d01f060ffa9993163c423a29a54fc.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://core/game_menu/assets/page_3/3_dx.png"
dest_files=["res://.godot/imported/3_dx.png-c85d01f060ffa9993163c423a29a54fc.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://diuai5vtjx23l"
path="res://.godot/imported/3_sx.png-537fe112f093326f28478c136b142922.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://core/game_menu/assets/page_3/3_sx.png"
dest_files=["res://.godot/imported/3_sx.png-537fe112f093326f28478c136b142922.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://vg5y4qgc26ko"
path="res://.godot/imported/coming_soon_01.png-25c9049aaff7242878eb6f73c7097db7.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://core/game_menu/assets/page_3/coming_soon_01.png"
dest_files=["res://.godot/imported/coming_soon_01.png-25c9049aaff7242878eb6f73c7097db7.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bmatlcouch6jm"
path="res://.godot/imported/coming_soon_02.png-3a0cf6d408d00a891bcda63b2e091de2.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://core/game_menu/assets/page_3/coming_soon_02.png"
dest_files=["res://.godot/imported/coming_soon_02.png-3a0cf6d408d00a891bcda63b2e091de2.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bm55xiv8jgnni"
path="res://.godot/imported/coming_soon_03.png-57925084415215faf6655b4afb668ed8.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://core/game_menu/assets/page_3/coming_soon_03.png"
dest_files=["res://.godot/imported/coming_soon_03.png-57925084415215faf6655b4afb668ed8.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cj81qdlrulal2"
path="res://.godot/imported/coming_soon_04.png-8f40cb1c6984110b3c2b3d9c3c9c8658.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://core/game_menu/assets/page_3/coming_soon_04.png"
dest_files=["res://.godot/imported/coming_soon_04.png-8f40cb1c6984110b3c2b3d9c3c9c8658.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://biu4i40ck272q"
path="res://.godot/imported/coming_soon_05.png-ac2ff567503cb2e314861075714ac8fb.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://core/game_menu/assets/page_3/coming_soon_05.png"
dest_files=["res://.godot/imported/coming_soon_05.png-ac2ff567503cb2e314861075714ac8fb.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

View File

@@ -2,7 +2,7 @@
[ext_resource type="Script" uid="uid://c7q3d823b1v1h" path="res://core/game_menu/biome_picker.gd" id="1_jqji0"]
[ext_resource type="Texture2D" uid="uid://dc0sl04wem136" path="res://core/game_menu/assets/page_1/color_main_biome.png" id="2_8s4h5"]
[ext_resource type="Texture2D" uid="uid://dj6pt25w5i4jq" path="res://core/game_menu/assets/page_1/lucchetto.png" id="2_jqji0"]
[ext_resource type="Texture2D" uid="uid://bx6gsh5uchkge" path="res://core/game_menu/assets/lock.png" id="3_jqji0"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_jqji0"]
@@ -65,18 +65,19 @@ stretch_mode = 3
[node name="TextureRect" type="TextureRect" parent="Texture" unique_id=288045010]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = -1
anchor_left = 0.36645964
anchor_top = 0.41690964
anchor_right = 0.6335404
anchor_bottom = 0.58309036
offset_left = 1.5
offset_top = 8.5
offset_right = -1.5
offset_bottom = -8.5
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -26.8755
offset_top = -34.375504
offset_right = 26.8755
offset_bottom = 34.375504
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
texture = ExtResource("2_jqji0")
texture = ExtResource("3_jqji0")
expand_mode = 1
[connection signal="pressed" from="." to="." method="_on_pressed"]

View File

@@ -19,6 +19,8 @@ func setup() -> void:
_add_collectible(collectible)
if unlocked_collectible_ids.has(collectible.id):
_unlock_collectible(collectible.id)
if is_inside_tree():
await get_tree().process_frame
func on_collectible_unlocked(collectible_id: StringName) -> void:
_unlock_collectible(collectible_id)

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