diff --git a/assets/ccs_cases_2/audio/CHIPS-01.wav b/assets/ccs_cases_2/audio/CHIPS-01.wav deleted file mode 100644 index 73d4468..0000000 Binary files a/assets/ccs_cases_2/audio/CHIPS-01.wav and /dev/null differ diff --git a/assets/ccs_cases_2/audio/CHIPS-01.wav.import b/assets/ccs_cases_2/audio/CHIPS-01.wav.import deleted file mode 100644 index 4f602c6..0000000 --- a/assets/ccs_cases_2/audio/CHIPS-01.wav.import +++ /dev/null @@ -1,24 +0,0 @@ -[remap] - -importer="wav" -type="AudioStreamWAV" -uid="uid://f0q6fjw8li34" -path="res://.godot/imported/CHIPS-01.wav-582f2a2445236f1807d7d8100300970e.sample" - -[deps] - -source_file="res://assets/ccs_cases_2/audio/CHIPS-01.wav" -dest_files=["res://.godot/imported/CHIPS-01.wav-582f2a2445236f1807d7d8100300970e.sample"] - -[params] - -force/8_bit=false -force/mono=false -force/max_rate=false -force/max_rate_hz=44100 -edit/trim=false -edit/normalize=false -edit/loop_mode=0 -edit/loop_begin=0 -edit/loop_end=-1 -compress/mode=2 diff --git a/assets/ccs_cases_2/audio/CHIPS-02.wav b/assets/ccs_cases_2/audio/CHIPS-02.wav deleted file mode 100644 index b128a50..0000000 Binary files a/assets/ccs_cases_2/audio/CHIPS-02.wav and /dev/null differ diff --git a/assets/ccs_cases_2/audio/CHIPS-02.wav.import b/assets/ccs_cases_2/audio/CHIPS-02.wav.import deleted file mode 100644 index 5b893a7..0000000 --- a/assets/ccs_cases_2/audio/CHIPS-02.wav.import +++ /dev/null @@ -1,24 +0,0 @@ -[remap] - -importer="wav" -type="AudioStreamWAV" -uid="uid://deq0xy3ap7u21" -path="res://.godot/imported/CHIPS-02.wav-1b7c7e1f05d4c32bfd5f1a0045e00062.sample" - -[deps] - -source_file="res://assets/ccs_cases_2/audio/CHIPS-02.wav" -dest_files=["res://.godot/imported/CHIPS-02.wav-1b7c7e1f05d4c32bfd5f1a0045e00062.sample"] - -[params] - -force/8_bit=false -force/mono=false -force/max_rate=false -force/max_rate_hz=44100 -edit/trim=false -edit/normalize=false -edit/loop_mode=0 -edit/loop_begin=0 -edit/loop_end=-1 -compress/mode=2 diff --git a/assets/ccs_cases_2/audio/CHIPS-03.wav b/assets/ccs_cases_2/audio/CHIPS-03.wav deleted file mode 100644 index c614d08..0000000 Binary files a/assets/ccs_cases_2/audio/CHIPS-03.wav and /dev/null differ diff --git a/assets/ccs_cases_2/audio/CHIPS-03.wav.import b/assets/ccs_cases_2/audio/CHIPS-03.wav.import deleted file mode 100644 index 2df2744..0000000 --- a/assets/ccs_cases_2/audio/CHIPS-03.wav.import +++ /dev/null @@ -1,24 +0,0 @@ -[remap] - -importer="wav" -type="AudioStreamWAV" -uid="uid://cp28h2en40qkj" -path="res://.godot/imported/CHIPS-03.wav-8b6513f8b6cb9a7a7db482c04e7994a8.sample" - -[deps] - -source_file="res://assets/ccs_cases_2/audio/CHIPS-03.wav" -dest_files=["res://.godot/imported/CHIPS-03.wav-8b6513f8b6cb9a7a7db482c04e7994a8.sample"] - -[params] - -force/8_bit=false -force/mono=false -force/max_rate=false -force/max_rate_hz=44100 -edit/trim=false -edit/normalize=false -edit/loop_mode=0 -edit/loop_begin=0 -edit/loop_end=-1 -compress/mode=2 diff --git a/assets/ccs_cases_2/audio/CHIPS-04.wav b/assets/ccs_cases_2/audio/CHIPS-04.wav deleted file mode 100644 index 245ff34..0000000 Binary files a/assets/ccs_cases_2/audio/CHIPS-04.wav and /dev/null differ diff --git a/assets/ccs_cases_2/audio/CHIPS-04.wav.import b/assets/ccs_cases_2/audio/CHIPS-04.wav.import deleted file mode 100644 index 0d88c6f..0000000 --- a/assets/ccs_cases_2/audio/CHIPS-04.wav.import +++ /dev/null @@ -1,24 +0,0 @@ -[remap] - -importer="wav" -type="AudioStreamWAV" -uid="uid://d3lj71hfhlvoe" -path="res://.godot/imported/CHIPS-04.wav-149d7eaf2a33e2747d2f6fcbec4af0fe.sample" - -[deps] - -source_file="res://assets/ccs_cases_2/audio/CHIPS-04.wav" -dest_files=["res://.godot/imported/CHIPS-04.wav-149d7eaf2a33e2747d2f6fcbec4af0fe.sample"] - -[params] - -force/8_bit=false -force/mono=false -force/max_rate=false -force/max_rate_hz=44100 -edit/trim=false -edit/normalize=false -edit/loop_mode=0 -edit/loop_begin=0 -edit/loop_end=-1 -compress/mode=2 diff --git a/assets/ccs_cases_2/audio/CLICK-01.wav b/assets/ccs_cases_2/audio/CLICK-01.wav deleted file mode 100644 index 53d21c9..0000000 Binary files a/assets/ccs_cases_2/audio/CLICK-01.wav and /dev/null differ diff --git a/assets/ccs_cases_2/audio/CLICK-01.wav.import b/assets/ccs_cases_2/audio/CLICK-01.wav.import deleted file mode 100644 index 64acb36..0000000 --- a/assets/ccs_cases_2/audio/CLICK-01.wav.import +++ /dev/null @@ -1,24 +0,0 @@ -[remap] - -importer="wav" -type="AudioStreamWAV" -uid="uid://bbyksq0tjsw7t" -path="res://.godot/imported/CLICK-01.wav-12c8c2888253f4fe1c2b6cd3ed702340.sample" - -[deps] - -source_file="res://assets/ccs_cases_2/audio/CLICK-01.wav" -dest_files=["res://.godot/imported/CLICK-01.wav-12c8c2888253f4fe1c2b6cd3ed702340.sample"] - -[params] - -force/8_bit=false -force/mono=false -force/max_rate=false -force/max_rate_hz=44100 -edit/trim=false -edit/normalize=false -edit/loop_mode=0 -edit/loop_begin=0 -edit/loop_end=-1 -compress/mode=2 diff --git a/assets/ccs_cases_2/audio/CLICK-02.wav b/assets/ccs_cases_2/audio/CLICK-02.wav deleted file mode 100644 index 6770335..0000000 Binary files a/assets/ccs_cases_2/audio/CLICK-02.wav and /dev/null differ diff --git a/assets/ccs_cases_2/audio/CLICK-02.wav.import b/assets/ccs_cases_2/audio/CLICK-02.wav.import deleted file mode 100644 index da06a54..0000000 --- a/assets/ccs_cases_2/audio/CLICK-02.wav.import +++ /dev/null @@ -1,24 +0,0 @@ -[remap] - -importer="wav" -type="AudioStreamWAV" -uid="uid://btj7os30hhbqt" -path="res://.godot/imported/CLICK-02.wav-d3e48ccc9b37871e4c1f58ad7a98c6e2.sample" - -[deps] - -source_file="res://assets/ccs_cases_2/audio/CLICK-02.wav" -dest_files=["res://.godot/imported/CLICK-02.wav-d3e48ccc9b37871e4c1f58ad7a98c6e2.sample"] - -[params] - -force/8_bit=false -force/mono=false -force/max_rate=false -force/max_rate_hz=44100 -edit/trim=false -edit/normalize=false -edit/loop_mode=0 -edit/loop_begin=0 -edit/loop_end=-1 -compress/mode=2 diff --git a/assets/ccs_cases_2/audio/CLICK-03.wav b/assets/ccs_cases_2/audio/CLICK-03.wav deleted file mode 100644 index addb819..0000000 Binary files a/assets/ccs_cases_2/audio/CLICK-03.wav and /dev/null differ diff --git a/assets/ccs_cases_2/audio/CLICK-03.wav.import b/assets/ccs_cases_2/audio/CLICK-03.wav.import deleted file mode 100644 index 44fb189..0000000 --- a/assets/ccs_cases_2/audio/CLICK-03.wav.import +++ /dev/null @@ -1,24 +0,0 @@ -[remap] - -importer="wav" -type="AudioStreamWAV" -uid="uid://sg7gexab0vvo" -path="res://.godot/imported/CLICK-03.wav-4bbeb40624144445710defe3f04dff22.sample" - -[deps] - -source_file="res://assets/ccs_cases_2/audio/CLICK-03.wav" -dest_files=["res://.godot/imported/CLICK-03.wav-4bbeb40624144445710defe3f04dff22.sample"] - -[params] - -force/8_bit=false -force/mono=false -force/max_rate=false -force/max_rate_hz=44100 -edit/trim=false -edit/normalize=false -edit/loop_mode=0 -edit/loop_begin=0 -edit/loop_end=-1 -compress/mode=2 diff --git a/assets/ccs_cases_2/audio/CLICK-04.wav b/assets/ccs_cases_2/audio/CLICK-04.wav deleted file mode 100644 index fa820b3..0000000 Binary files a/assets/ccs_cases_2/audio/CLICK-04.wav and /dev/null differ diff --git a/assets/ccs_cases_2/audio/CLICK-04.wav.import b/assets/ccs_cases_2/audio/CLICK-04.wav.import deleted file mode 100644 index da1a203..0000000 --- a/assets/ccs_cases_2/audio/CLICK-04.wav.import +++ /dev/null @@ -1,24 +0,0 @@ -[remap] - -importer="wav" -type="AudioStreamWAV" -uid="uid://dshj5v2aihbb0" -path="res://.godot/imported/CLICK-04.wav-156128b0878fd0ff55b94b89c4fc9c6f.sample" - -[deps] - -source_file="res://assets/ccs_cases_2/audio/CLICK-04.wav" -dest_files=["res://.godot/imported/CLICK-04.wav-156128b0878fd0ff55b94b89c4fc9c6f.sample"] - -[params] - -force/8_bit=false -force/mono=false -force/max_rate=false -force/max_rate_hz=44100 -edit/trim=false -edit/normalize=false -edit/loop_mode=0 -edit/loop_begin=0 -edit/loop_end=-1 -compress/mode=2 diff --git a/assets/ccs_cases_2/audio/DEEPFLAP-01.wav b/assets/ccs_cases_2/audio/DEEPFLAP-01.wav deleted file mode 100644 index a362446..0000000 Binary files a/assets/ccs_cases_2/audio/DEEPFLAP-01.wav and /dev/null differ diff --git a/assets/ccs_cases_2/audio/DEEPFLAP-01.wav.import b/assets/ccs_cases_2/audio/DEEPFLAP-01.wav.import deleted file mode 100644 index 5f7354b..0000000 --- a/assets/ccs_cases_2/audio/DEEPFLAP-01.wav.import +++ /dev/null @@ -1,24 +0,0 @@ -[remap] - -importer="wav" -type="AudioStreamWAV" -uid="uid://bf2gtxwjd6eox" -path="res://.godot/imported/DEEPFLAP-01.wav-df2c3f7c79142841e98da9c5a921057d.sample" - -[deps] - -source_file="res://assets/ccs_cases_2/audio/DEEPFLAP-01.wav" -dest_files=["res://.godot/imported/DEEPFLAP-01.wav-df2c3f7c79142841e98da9c5a921057d.sample"] - -[params] - -force/8_bit=false -force/mono=false -force/max_rate=false -force/max_rate_hz=44100 -edit/trim=false -edit/normalize=false -edit/loop_mode=0 -edit/loop_begin=0 -edit/loop_end=-1 -compress/mode=2 diff --git a/assets/ccs_cases_2/audio/FAN-WHIR-01.wav b/assets/ccs_cases_2/audio/FAN-WHIR-01.wav deleted file mode 100644 index bbca3b1..0000000 Binary files a/assets/ccs_cases_2/audio/FAN-WHIR-01.wav and /dev/null differ diff --git a/assets/ccs_cases_2/audio/FAN-WHIR-01.wav.import b/assets/ccs_cases_2/audio/FAN-WHIR-01.wav.import deleted file mode 100644 index af6c464..0000000 --- a/assets/ccs_cases_2/audio/FAN-WHIR-01.wav.import +++ /dev/null @@ -1,24 +0,0 @@ -[remap] - -importer="wav" -type="AudioStreamWAV" -uid="uid://phq30ylu5bo3" -path="res://.godot/imported/FAN-WHIR-01.wav-95005855ffe41ed39c5614355bed9e5b.sample" - -[deps] - -source_file="res://assets/ccs_cases_2/audio/FAN-WHIR-01.wav" -dest_files=["res://.godot/imported/FAN-WHIR-01.wav-95005855ffe41ed39c5614355bed9e5b.sample"] - -[params] - -force/8_bit=false -force/mono=false -force/max_rate=false -force/max_rate_hz=44100 -edit/trim=false -edit/normalize=false -edit/loop_mode=0 -edit/loop_begin=0 -edit/loop_end=-1 -compress/mode=2 diff --git a/assets/ccs_cases_2/audio/LOUDCLICK-01.wav b/assets/ccs_cases_2/audio/LOUDCLICK-01.wav deleted file mode 100644 index 1b00b85..0000000 Binary files a/assets/ccs_cases_2/audio/LOUDCLICK-01.wav and /dev/null differ diff --git a/assets/ccs_cases_2/audio/LOUDCLICK-01.wav.import b/assets/ccs_cases_2/audio/LOUDCLICK-01.wav.import deleted file mode 100644 index 38460cb..0000000 --- a/assets/ccs_cases_2/audio/LOUDCLICK-01.wav.import +++ /dev/null @@ -1,24 +0,0 @@ -[remap] - -importer="wav" -type="AudioStreamWAV" -uid="uid://dhfgv6iuedgax" -path="res://.godot/imported/LOUDCLICK-01.wav-74ce36dff26bf8d7a8977e58e7442165.sample" - -[deps] - -source_file="res://assets/ccs_cases_2/audio/LOUDCLICK-01.wav" -dest_files=["res://.godot/imported/LOUDCLICK-01.wav-74ce36dff26bf8d7a8977e58e7442165.sample"] - -[params] - -force/8_bit=false -force/mono=false -force/max_rate=false -force/max_rate_hz=44100 -edit/trim=false -edit/normalize=false -edit/loop_mode=0 -edit/loop_begin=0 -edit/loop_end=-1 -compress/mode=2 diff --git a/assets/ccs_cases_2/audio/MAGNET-THWAP-01.wav b/assets/ccs_cases_2/audio/MAGNET-THWAP-01.wav deleted file mode 100644 index 895236d..0000000 Binary files a/assets/ccs_cases_2/audio/MAGNET-THWAP-01.wav and /dev/null differ diff --git a/assets/ccs_cases_2/audio/MAGNET-THWAP-01.wav.import b/assets/ccs_cases_2/audio/MAGNET-THWAP-01.wav.import deleted file mode 100644 index 4c3ff33..0000000 --- a/assets/ccs_cases_2/audio/MAGNET-THWAP-01.wav.import +++ /dev/null @@ -1,24 +0,0 @@ -[remap] - -importer="wav" -type="AudioStreamWAV" -uid="uid://ufi3xj7myijj" -path="res://.godot/imported/MAGNET-THWAP-01.wav-841ae8e9cf025cbca12c9a7dd062cbf7.sample" - -[deps] - -source_file="res://assets/ccs_cases_2/audio/MAGNET-THWAP-01.wav" -dest_files=["res://.godot/imported/MAGNET-THWAP-01.wav-841ae8e9cf025cbca12c9a7dd062cbf7.sample"] - -[params] - -force/8_bit=false -force/mono=false -force/max_rate=false -force/max_rate_hz=44100 -edit/trim=false -edit/normalize=false -edit/loop_mode=0 -edit/loop_begin=0 -edit/loop_end=-1 -compress/mode=2 diff --git a/assets/ccs_cases_2/audio/THUMP-01.wav b/assets/ccs_cases_2/audio/THUMP-01.wav deleted file mode 100644 index 8af084f..0000000 Binary files a/assets/ccs_cases_2/audio/THUMP-01.wav and /dev/null differ diff --git a/assets/ccs_cases_2/audio/THUMP-01.wav.import b/assets/ccs_cases_2/audio/THUMP-01.wav.import deleted file mode 100644 index 341ab73..0000000 --- a/assets/ccs_cases_2/audio/THUMP-01.wav.import +++ /dev/null @@ -1,24 +0,0 @@ -[remap] - -importer="wav" -type="AudioStreamWAV" -uid="uid://brpia062tfuw7" -path="res://.godot/imported/THUMP-01.wav-96534e39f9abaf0b6479d088cb5d44df.sample" - -[deps] - -source_file="res://assets/ccs_cases_2/audio/THUMP-01.wav" -dest_files=["res://.godot/imported/THUMP-01.wav-96534e39f9abaf0b6479d088cb5d44df.sample"] - -[params] - -force/8_bit=false -force/mono=false -force/max_rate=false -force/max_rate_hz=44100 -edit/trim=false -edit/normalize=false -edit/loop_mode=0 -edit/loop_begin=0 -edit/loop_end=-1 -compress/mode=2 diff --git a/assets/ccs_cases_2/images/slot/lever-sprite-sheet.png b/assets/ccs_cases_2/images/slot/lever-sprite-sheet.png deleted file mode 100644 index 65b1926..0000000 Binary files a/assets/ccs_cases_2/images/slot/lever-sprite-sheet.png and /dev/null differ diff --git a/assets/ccs_cases_2/images/slot/lever-sprite-sheet.png.import b/assets/ccs_cases_2/images/slot/lever-sprite-sheet.png.import deleted file mode 100644 index 7ae2435..0000000 --- a/assets/ccs_cases_2/images/slot/lever-sprite-sheet.png.import +++ /dev/null @@ -1,40 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://d3bo8n2dxx6h4" -path="res://.godot/imported/lever-sprite-sheet.png-28bddeaacbfc9f3064287f9324158563.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://assets/ccs_cases_2/images/slot/lever-sprite-sheet.png" -dest_files=["res://.godot/imported/lever-sprite-sheet.png-28bddeaacbfc9f3064287f9324158563.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 diff --git a/assets/ccs_cases_2/images/slot/numbers.png b/assets/ccs_cases_2/images/slot/numbers.png deleted file mode 100644 index a3dc6a1..0000000 Binary files a/assets/ccs_cases_2/images/slot/numbers.png and /dev/null differ diff --git a/assets/ccs_cases_2/images/slot/numbers.png.import b/assets/ccs_cases_2/images/slot/numbers.png.import deleted file mode 100644 index 53d8187..0000000 --- a/assets/ccs_cases_2/images/slot/numbers.png.import +++ /dev/null @@ -1,40 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://u5gmnonww4s4" -path="res://.godot/imported/numbers.png-f7b7591684a12e158214a353335df9a3.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://assets/ccs_cases_2/images/slot/numbers.png" -dest_files=["res://.godot/imported/numbers.png-f7b7591684a12e158214a353335df9a3.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 diff --git a/assets/ccs_cases_2/images/slot/reel-frame.png b/assets/ccs_cases_2/images/slot/reel-frame.png deleted file mode 100644 index 528c380..0000000 Binary files a/assets/ccs_cases_2/images/slot/reel-frame.png and /dev/null differ diff --git a/assets/ccs_cases_2/images/slot/reel-frame.png.import b/assets/ccs_cases_2/images/slot/reel-frame.png.import deleted file mode 100644 index c639816..0000000 --- a/assets/ccs_cases_2/images/slot/reel-frame.png.import +++ /dev/null @@ -1,40 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://blq8wype071ou" -path="res://.godot/imported/reel-frame.png-45e4b5f53fe075b210e4af141b08081c.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://assets/ccs_cases_2/images/slot/reel-frame.png" -dest_files=["res://.godot/imported/reel-frame.png-45e4b5f53fe075b210e4af141b08081c.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 diff --git a/assets/ccs_cases_2/images/slot/symbols.png b/assets/ccs_cases_2/images/slot/symbols.png deleted file mode 100644 index 4761c73..0000000 Binary files a/assets/ccs_cases_2/images/slot/symbols.png and /dev/null differ diff --git a/assets/ccs_cases_2/images/slot/symbols.png.import b/assets/ccs_cases_2/images/slot/symbols.png.import deleted file mode 100644 index ac72719..0000000 --- a/assets/ccs_cases_2/images/slot/symbols.png.import +++ /dev/null @@ -1,40 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://ujbkwj0i8e2v" -path="res://.godot/imported/symbols.png-d6e1a2099254ac8842c1e175b464450a.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://assets/ccs_cases_2/images/slot/symbols.png" -dest_files=["res://.godot/imported/symbols.png-d6e1a2099254ac8842c1e175b464450a.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 diff --git a/scenes/ccs_cases_2/slot_machine.tscn b/scenes/ccs_cases_2/slot_machine.tscn deleted file mode 100644 index 4a603b6..0000000 --- a/scenes/ccs_cases_2/slot_machine.tscn +++ /dev/null @@ -1,319 +0,0 @@ -[gd_scene format=3 uid="uid://bq3huk364skd3"] - -[ext_resource type="Script" path="res://scripts/ui/ccs_cases_2/slot_machine.gd" id="1_qtu10"] -[ext_resource type="Shader" path="res://shaders/ccs_cases_2/reel_spin.gdshader" id="2_ee4bf"] -[ext_resource type="Texture2D" path="res://assets/ccs_cases_2/images/slot/symbols.png" id="3_ee4bf"] -[ext_resource type="Texture2D" path="res://assets/ccs_cases_2/images/slot/numbers.png" id="3_kbped"] -[ext_resource type="Texture2D" path="res://assets/ccs_cases_2/images/slot/reel-frame.png" id="4_reel_bg"] -[ext_resource type="Texture2D" path="res://assets/ccs_cases_2/images/slot/lever-sprite-sheet.png" id="6_lever_sheet"] - -[sub_resource type="ShaderMaterial" id="ShaderMaterial_bvwqe"] -shader = ExtResource("2_ee4bf") -shader_parameter/tex = ExtResource("3_ee4bf") -shader_parameter/n_rows = 6.0 -shader_parameter/y_offset = 0.0 - -[sub_resource type="ShaderMaterial" id="ShaderMaterial_fj5cn"] -shader = ExtResource("2_ee4bf") -shader_parameter/tex = ExtResource("3_ee4bf") -shader_parameter/n_rows = 6.0 -shader_parameter/y_offset = 0.0 - -[sub_resource type="ShaderMaterial" id="ShaderMaterial_iy58a"] -shader = ExtResource("2_ee4bf") -shader_parameter/tex = ExtResource("3_ee4bf") -shader_parameter/n_rows = 6.0 -shader_parameter/y_offset = 0.0 -shader_parameter/x_offset = -0.018 - -[sub_resource type="ShaderMaterial" id="ShaderMaterial_6a6wx"] -shader = ExtResource("2_ee4bf") -shader_parameter/tex = ExtResource("3_kbped") -shader_parameter/n_rows = 10.0 -shader_parameter/y_offset = 0.0 - -[sub_resource type="ShaderMaterial" id="ShaderMaterial_ee4bf"] -shader = ExtResource("2_ee4bf") -shader_parameter/tex = ExtResource("3_kbped") -shader_parameter/n_rows = 10.0 -shader_parameter/y_offset = 0.0 - -[sub_resource type="ShaderMaterial" id="ShaderMaterial_kbped"] -shader = ExtResource("2_ee4bf") -shader_parameter/tex = ExtResource("3_kbped") -shader_parameter/n_rows = 10.0 -shader_parameter/y_offset = 0.0 - -[sub_resource type="ShaderMaterial" id="ShaderMaterial_sky72"] -shader = ExtResource("2_ee4bf") -shader_parameter/tex = ExtResource("3_kbped") -shader_parameter/n_rows = 10.0 -shader_parameter/y_offset = 0.0 - -[sub_resource type="AtlasTexture" id="AtlasTexture_reel_divider"] -atlas = ExtResource("4_reel_bg") -region = Rect2(24, 72, 56, 880) - -[sub_resource type="AtlasTexture" id="AtlasTexture_smooth_top"] -atlas = ExtResource("4_reel_bg") -region = Rect2(100, 26, 824, 44) - -[sub_resource type="AtlasTexture" id="AtlasTexture_smooth_bottom"] -atlas = ExtResource("4_reel_bg") -region = Rect2(100, 954, 824, 44) - -[sub_resource type="AtlasTexture" id="AtlasTexture_lever_0"] -atlas = ExtResource("6_lever_sheet") -region = Rect2(0, 0, 307, 1024) - -[sub_resource type="AtlasTexture" id="AtlasTexture_lever_1"] -atlas = ExtResource("6_lever_sheet") -region = Rect2(307, 0, 307, 1024) - -[sub_resource type="AtlasTexture" id="AtlasTexture_lever_2"] -atlas = ExtResource("6_lever_sheet") -region = Rect2(614, 0, 307, 1024) - -[sub_resource type="AtlasTexture" id="AtlasTexture_lever_3"] -atlas = ExtResource("6_lever_sheet") -region = Rect2(921, 0, 307, 1024) - -[sub_resource type="AtlasTexture" id="AtlasTexture_lever_4"] -atlas = ExtResource("6_lever_sheet") -region = Rect2(1228, 0, 308, 1024) - -[sub_resource type="SpriteFrames" id="SpriteFrames_lever"] -animations = [{ -"frames": [{"duration": 1.0, "texture": SubResource("AtlasTexture_lever_0")}, {"duration": 1.0, "texture": SubResource("AtlasTexture_lever_1")}, {"duration": 1.0, "texture": SubResource("AtlasTexture_lever_2")}, {"duration": 1.0, "texture": SubResource("AtlasTexture_lever_3")}, {"duration": 1.0, "texture": SubResource("AtlasTexture_lever_4")}], -"loop": false, -"name": &"pull", -"speed": 12.0 -}] - -[node name="Control" type="Control" unique_id=1279508523 node_paths=PackedStringArray("icon_reels", "number_reels")] -layout_mode = 3 -anchors_preset = 0 -offset_right = 1500.0 -offset_bottom = 800.0 -script = ExtResource("1_qtu10") -icon_reels = [NodePath("Spinner1"), NodePath("Spinner2"), NodePath("Spinner3")] -number_reels = [NodePath("Numbers1"), NodePath("Numbers2"), NodePath("Numbers3"), NodePath("Numbers4")] - -[node name="ReelBackground1" type="TextureRect" parent="."] -z_index = -2 -layout_mode = 0 -offset_left = 315.0 -offset_top = 276.0 -offset_right = 646.0 -offset_bottom = 607.0 -mouse_filter = 2 -texture = ExtResource("4_reel_bg") -expand_mode = 1 - -[node name="ReelBackground2" type="TextureRect" parent="."] -z_index = -2 -layout_mode = 0 -offset_left = 594.0 -offset_top = 276.0 -offset_right = 925.0 -offset_bottom = 607.0 -mouse_filter = 2 -texture = ExtResource("4_reel_bg") -expand_mode = 1 - -[node name="ReelBackground3" type="TextureRect" parent="."] -z_index = -2 -layout_mode = 0 -offset_left = 873.0 -offset_top = 276.0 -offset_right = 1204.0 -offset_bottom = 607.0 -mouse_filter = 2 -texture = ExtResource("4_reel_bg") -expand_mode = 1 - -[node name="ReelWhite1" type="ColorRect" parent="."] -z_index = -1 -layout_mode = 0 -offset_left = 341.0 -offset_top = 301.0 -offset_right = 620.0 -offset_bottom = 580.0 -mouse_filter = 2 - -[node name="ReelWhite2" type="ColorRect" parent="."] -z_index = -1 -layout_mode = 0 -offset_left = 620.0 -offset_top = 301.0 -offset_right = 899.0 -offset_bottom = 580.0 -mouse_filter = 2 - -[node name="ReelWhite3" type="ColorRect" parent="."] -z_index = -1 -layout_mode = 0 -offset_left = 899.0 -offset_top = 301.0 -offset_right = 1178.0 -offset_bottom = 580.0 -mouse_filter = 2 - -[node name="Spinner1" type="ColorRect" parent="." unique_id=813668141] -texture_filter = 2 -material = SubResource("ShaderMaterial_bvwqe") -layout_mode = 0 -offset_left = 341.0 -offset_top = 301.0 -offset_right = 620.0 -offset_bottom = 580.0 - -[node name="Spinner2" type="ColorRect" parent="." unique_id=203022686] -material = SubResource("ShaderMaterial_fj5cn") -layout_mode = 0 -offset_left = 620.0 -offset_top = 301.0 -offset_right = 899.0 -offset_bottom = 580.0 - -[node name="Spinner3" type="ColorRect" parent="." unique_id=409654364] -material = SubResource("ShaderMaterial_iy58a") -layout_mode = 0 -offset_left = 899.0 -offset_top = 301.0 -offset_right = 1178.0 -offset_bottom = 580.0 - -[node name="MiddleReelLeftDivider" type="TextureRect" parent="."] -z_index = 1 -layout_mode = 0 -offset_left = 610.0 -offset_top = 301.0 -offset_right = 630.0 -offset_bottom = 580.0 -mouse_filter = 2 -texture = SubResource("AtlasTexture_reel_divider") -expand_mode = 1 - -[node name="MiddleReelRightDivider" type="TextureRect" parent="."] -z_index = 1 -layout_mode = 0 -offset_left = 889.0 -offset_top = 301.0 -offset_right = 909.0 -offset_bottom = 580.0 -mouse_filter = 2 -texture = SubResource("AtlasTexture_reel_divider") -expand_mode = 1 - -[node name="ContinuousTopTrim" type="TextureRect" parent="."] -z_index = 2 -layout_mode = 0 -offset_left = 323.0 -offset_top = 276.0 -offset_right = 1196.0 -offset_bottom = 301.0 -mouse_filter = 2 -texture = SubResource("AtlasTexture_smooth_top") -expand_mode = 1 - -[node name="ContinuousBottomTrim" type="TextureRect" parent="."] -z_index = 2 -layout_mode = 0 -offset_left = 323.0 -offset_top = 580.0 -offset_right = 1196.0 -offset_bottom = 607.0 -mouse_filter = 2 -texture = SubResource("AtlasTexture_smooth_bottom") -expand_mode = 1 - -[node name="LeverPivot" type="Node2D" parent="."] -z_index = 5 -position = Vector2(1202, 592) - -[node name="LeverSprite" type="AnimatedSprite2D" parent="LeverPivot"] -position = Vector2(19, -105) -scale = Vector2(0.8, 0.8) -sprite_frames = SubResource("SpriteFrames_lever") -animation = &"pull" - -[node name="LeverButton" type="Button" parent="."] -z_index = 6 -layout_mode = 0 -offset_left = 1107.0 -offset_top = 257.0 -offset_right = 1287.0 -offset_bottom = 602.0 -mouse_default_cursor_shape = 2 -focus_mode = 0 -self_modulate = Color(1, 1, 1, 0) -flat = true -tooltip_text = "Pull lever" - -[node name="Numbers1" type="ColorRect" parent="." unique_id=2125838097] -texture_filter = 2 -material = SubResource("ShaderMaterial_6a6wx") -layout_mode = 0 -offset_left = 1092.0 -offset_top = 110.0 -offset_right = 1167.0 -offset_bottom = 185.0 - -[node name="Numbers2" type="ColorRect" parent="." unique_id=1145238072] -texture_filter = 2 -material = SubResource("ShaderMaterial_ee4bf") -layout_mode = 0 -offset_left = 1171.0 -offset_top = 110.0 -offset_right = 1246.0 -offset_bottom = 185.0 - -[node name="Numbers3" type="ColorRect" parent="." unique_id=1321048024] -texture_filter = 2 -material = SubResource("ShaderMaterial_kbped") -layout_mode = 0 -offset_left = 1250.0 -offset_top = 110.0 -offset_right = 1325.0 -offset_bottom = 185.0 - -[node name="Numbers4" type="ColorRect" parent="." unique_id=1865653938] -texture_filter = 2 -material = SubResource("ShaderMaterial_sky72") -layout_mode = 0 -offset_left = 1329.0 -offset_top = 110.0 -offset_right = 1404.0 -offset_bottom = 185.0 - -[node name="TestCounterButton" type="Button" parent="."] -layout_mode = 0 -offset_left = 1092.0 -offset_top = 202.0 -offset_right = 1353.0 -offset_bottom = 252.0 -text = "Test Counter Setting" - -[node name="ContinueButton" type="Button" parent="."] -layout_mode = 0 -offset_left = 400.0 -offset_top = 110.0 -offset_right = 620.0 -offset_bottom = 160.0 -mouse_default_cursor_shape = 2 -text = "Continue" - -[node name="SpinResultLabel" type="Label" parent="."] -layout_mode = 0 -offset_left = 683.0 -offset_top = 744.0 -offset_right = 913.0 -offset_bottom = 784.0 -text = "Ready" -horizontal_alignment = 1 -vertical_alignment = 1 - -[connection signal="pressed" from="LeverButton" to="." method="pull_lever"] -[connection signal="pressed" from="TestCounterButton" to="." method="test_counter_setting"] -[connection signal="pressed" from="ContinueButton" to="." method="go_to_doctor_scene"] diff --git a/scripts/ui/ccs_cases_2/slot_machine.gd b/scripts/ui/ccs_cases_2/slot_machine.gd deleted file mode 100644 index d26d0e9..0000000 --- a/scripts/ui/ccs_cases_2/slot_machine.gd +++ /dev/null @@ -1,770 +0,0 @@ -extends Control - -signal number_change_finished(value: int) -signal spin_finished(symbols: Array[int], payout_multiplier: float) -signal continue_requested - -@export var icon_reels: Array[Control] -@export var number_reels: Array[Control] -@export_range(-40.0, 0.0, 0.5) var click_volume_db := -11.0 -@export_range(0.0, 0.2, 0.005) var pitch_variation := 0.055 -@export_range(-40.0, -10.0, 0.5) var reel_whir_volume_db := -30.0 -@export_range(0.0, 1.5, 0.05) var extra_icon_reel_stop_delay := 0.4 -@export_range(0.1, 2.0, 0.05) var number_roll_duration := 0.6 -@export_category("Slot Math") -@export_range(0.0, 1.0, 0.001) var target_rtp := 0.96 -@export var symbol_names := PackedStringArray([ - "Star", "Diamond", "Potion", "Shield", "Chips", "Gift" -]) -@export var symbol_payout_min := PackedInt32Array([1, 50, 400, 300, 5, 0]) -@export var symbol_payout_max := PackedInt32Array([1, 100, 400, 300, 10, 0]) -@export var symbol_rtp_shares := PackedFloat32Array([ - 0.25686958, 0.15625, 0.16666667, 0.15625, 0.20833333, 0.05563042 -]) -@export var loss_symbol_weights := PackedFloat32Array([1.0, 2.0, 4.0, 6.0, 10.0, 3.0]) -@export_range(0.0, 1.0, 0.01) var near_miss_rate := 0.15 -@export_category("Early Session Study") -@export_range(0, 20, 1) var early_boost_spin_count := 5 -@export_range(0.0, 1.0, 0.01) var early_blue_stack_chance := 0.20 - -const CLICK_SOUNDS: Array[AudioStream] = [ - preload("res://assets/ccs_cases_2/audio/CLICK-01.wav"), - preload("res://assets/ccs_cases_2/audio/CLICK-02.wav"), - preload("res://assets/ccs_cases_2/audio/CLICK-03.wav"), - preload("res://assets/ccs_cases_2/audio/CLICK-04.wav"), -] -# The recordings contain different amounts of silence before their transients. -# Starting here preserves a tiny lead-in while keeping the impact synchronized. -const CLICK_START_OFFSETS: Array[float] = [0.040, 0.039, 0.052, 0.061] -const STOP_CLICK: AudioStream = preload("res://assets/ccs_cases_2/audio/LOUDCLICK-01.wav") -# This recording has about 167 ms of silence before its impact. -const STOP_CLICK_START_OFFSET := 0.167 -const STOP_FLAP: AudioStream = preload("res://assets/ccs_cases_2/audio/DEEPFLAP-01.wav") -# The deep layer has about 159 ms of silence before its transient. -const STOP_FLAP_START_OFFSET := 0.159 -const SPIN_START_THUMP: AudioStream = preload("res://assets/ccs_cases_2/audio/THUMP-01.wav") -const LEVER_THWAP: AudioStream = preload("res://assets/ccs_cases_2/audio/MAGNET-THWAP-01.wav") -const LEVER_THWAP_START_OFFSET := 0.110 -const REEL_WHIR: AudioStream = preload("res://assets/ccs_cases_2/audio/FAN-WHIR-01.wav") -const REEL_WHIR_START_OFFSET := 1.72 -const CHIP_SOUNDS: Array[AudioStream] = [ - preload("res://assets/ccs_cases_2/audio/CHIPS-01.wav"), - preload("res://assets/ccs_cases_2/audio/CHIPS-02.wav"), - preload("res://assets/ccs_cases_2/audio/CHIPS-03.wav"), - preload("res://assets/ccs_cases_2/audio/CHIPS-04.wav"), -] -const CHIP_START_OFFSETS: Array[float] = [0.224, 0.154, 0.201, 0.261] -const AUDIO_POOL_SIZE := 16 -const SYMBOL_COUNT := 6 -const SINGLE_COIN_SYMBOL := 0 -const BLUE_COIN_STACK_SYMBOL := 4 -const PRESENT_SYMBOL := 5 -const LEVER_FRAME_POSITIONS: Array[Vector2] = [ - Vector2(19.0, -105.0), - Vector2(23.0, -106.0), - Vector2(12.0, -82.0), - Vector2(12.0, -90.0), - Vector2(5.0, -90.0), -] - -var values: Array[int] = [] -var reel_tweens: Array[Tween] = [] -var number_tweens: Array[Tween] = [] -var number_value := 100 -var number_animation_active := false -var audio_pool: Array[AudioStreamPlayer] = [] -var next_audio_player := 0 -var last_click_sound := -1 -var last_chip_sound := -1 -var chip_count_tween: Tween -var reel_whir_player: AudioStreamPlayer -var reel_whir_tween: Tween -var win_effect_tween: Tween -var spin_in_progress := false -var stopped_icon_reels := 0 -var selected_payout := 0.0 -var selected_near_miss := false -var selected_early_session_boost := false -var session_spins_started := 0 -var early_stack_bonus_consumed := false -var rng := RandomNumberGenerator.new() -var lever_tween: Tween -var lever_foley_tween: Tween -var lever_animating := false - -@onready var spin_result_label: Label = $SpinResultLabel -@onready var lever_pivot: Node2D = $LeverPivot -@onready var lever_sprite: AnimatedSprite2D = $LeverPivot/LeverSprite -@onready var lever_button: Button = $LeverButton - - -func _ready() -> void: - rng.randomize() - reel_whir_player = AudioStreamPlayer.new() - reel_whir_player.name = "ReelWhirPlayer" - reel_whir_player.stream = REEL_WHIR - add_child(reel_whir_player) - # A small voice pool lets nearby reel clicks overlap without cutting each other off. - for i in AUDIO_POOL_SIZE: - var player := AudioStreamPlayer.new() - player.name = "ReelClickVoice%d" % (i + 1) - player.volume_db = click_volume_db - add_child(player) - audio_pool.append(player) - _apply_number_immediately(number_value) - - -func spin() -> void: - if spin_in_progress: - return - - var configuration_error := _get_slot_math_error() - if not configuration_error.is_empty(): - push_error(configuration_error) - spin_result_label.text = "CONFIG ERROR" - return - if number_value <= 0: - spin_result_label.text = "NO CREDITS" - return - - _reset_win_effect() - - for active_tween in reel_tweens: - if active_tween and active_tween.is_valid(): - active_tween.kill() - reel_tweens.clear() - var early_session_eligible := ( - not early_stack_bonus_consumed - and session_spins_started < early_boost_spin_count - ) - var outcome := _select_spin_outcome(early_session_eligible) - session_spins_started += 1 - values = outcome.symbols - if ( - values[0] == BLUE_COIN_STACK_SYMBOL - and values[0] == values[1] - and values[1] == values[2] - ): - early_stack_bonus_consumed = true - selected_payout = outcome.payout - selected_near_miss = outcome.is_near_miss - selected_early_session_boost = outcome.early_session_boost - stopped_icon_reels = 0 - spin_in_progress = true - lever_button.disabled = true - spin_result_label.text = "Spinning..." - add_to_number(-1) - _play_spin_start() - _play_short_reel_whir() - - for i in icon_reels.size(): - var spinner := icon_reels[i] - var n_rows := int(spinner.material.get_shader_parameter("n_rows")) - var result := values[i] - - var step := 1.0 / float(n_rows) - var start := float(spinner.material.get_shader_parameter("y_offset")) - - # Several full downward rotations plus the predetermined final result. - # Negative texture offset moves this vertical strip downward on screen. - var rotations := randi_range(4, 7) - var target := floorf(start) - rotations + result * step - - # Later reels stop later, with slight randomness. - var duration := 1.8 + i * 0.55 + randf_range(0.1, 0.45) - # Open up the spacing between the three prominent icon-reel stops without - # changing reel 1 or the timing of the smaller number reels. - if i < 3: - duration += i * extra_icon_reel_stop_delay - var tick_state := { - "last_row": floori(start * n_rows), - "start": start, - "distance": target - start, - "final_row": floori(target * n_rows), - } - - var reel_tween := create_tween() - reel_tweens.append(reel_tween) - reel_tween.tween_method( - func(value: float) -> void: - spinner.material.set_shader_parameter("y_offset", value) - var current_row := floori(value * n_rows) - if current_row != tick_state.last_row: - tick_state.last_row = current_row - # The final detent is scheduled separately to compensate for - # audio-device latency; do not also play it at the endpoint. - if current_row != tick_state.final_row: - var progress := clampf( - (value - tick_state.start) / tick_state.distance, - 0.0, - 1.0 - ) - _play_reel_click(progress, i), - start, - target, - duration - ).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT) - - reel_tween.tween_callback(func() -> void: - spinner.material.set_shader_parameter("y_offset", fmod(target, 1.0)) - stopped_icon_reels += 1 - if stopped_icon_reels == icon_reels.size(): - _complete_spin() - ) - - if i < 3: - # Audio reaches the speakers after the engine submits it. Start the stop - # sound early by the latency reported for the active audio device so its - # transient reaches the listener at the visual tween endpoint. - var audio_latency := AudioServer.get_output_latency() - audio_latency += AudioServer.get_time_to_next_mix() - var stop_click_tween := create_tween() - reel_tweens.append(stop_click_tween) - stop_click_tween.tween_interval(maxf(duration - audio_latency, 0.0)) - stop_click_tween.tween_callback(_play_stop_click) - - -func _select_spin_outcome(allow_early_session_boost: bool = false) -> Dictionary: - if allow_early_session_boost and rng.randf() < early_blue_stack_chance: - return { - "symbols": [ - BLUE_COIN_STACK_SYMBOL, - BLUE_COIN_STACK_SYMBOL, - BLUE_COIN_STACK_SYMBOL, - ] as Array[int], - "payout": _roll_symbol_payout(BLUE_COIN_STACK_SYMBOL), - "is_near_miss": false, - "early_session_boost": true, - } - - var roll := rng.randf() - var cumulative_probability := 0.0 - var share_total := _sum_positive(symbol_rtp_shares) - - for symbol_index in SYMBOL_COUNT: - var normalized_share := maxf(symbol_rtp_shares[symbol_index], 0.0) / share_total - var win_probability := target_rtp * normalized_share / _get_symbol_model_value(symbol_index) - cumulative_probability += win_probability - if roll < cumulative_probability: - return { - "symbols": [symbol_index, symbol_index, symbol_index] as Array[int], - "payout": _roll_symbol_payout(symbol_index), - "is_near_miss": false, - "early_session_boost": false, - } - - if rng.randf() < near_miss_rate: - var near_miss_symbol := _pick_near_miss_symbol() - # With the current downward travel, the preceding symbol on the cyclic - # strip stops one position beyond the matching symbol. - var adjacent_symbol := posmod(near_miss_symbol - 1, SYMBOL_COUNT) - return { - "symbols": [near_miss_symbol, near_miss_symbol, adjacent_symbol] as Array[int], - "payout": 0.0, - "is_near_miss": true, - "early_session_boost": false, - } - - var losing_symbols: Array[int] = [] - while true: - losing_symbols = [ - _pick_weighted_symbol(loss_symbol_weights), - _pick_weighted_symbol(loss_symbol_weights), - _pick_weighted_symbol(loss_symbol_weights), - ] - # First-two matches are reserved for the explicit near-miss outcome so - # its configured rate remains exact and measurable. - if losing_symbols[0] != losing_symbols[1]: - break - - return { - "symbols": losing_symbols, - "payout": 0.0, - "is_near_miss": false, - "early_session_boost": false, - } - - -func reset_early_session_study() -> void: - session_spins_started = 0 - early_stack_bonus_consumed = false - - -func _pick_weighted_symbol(weights: PackedFloat32Array) -> int: - var total := _sum_positive(weights) - var roll := rng.randf() * total - var cumulative := 0.0 - for i in SYMBOL_COUNT: - cumulative += maxf(weights[i], 0.0) - if roll < cumulative: - return i - return SYMBOL_COUNT - 1 - - -func _pick_near_miss_symbol() -> int: - var total := 0.0 - for i in range(1, SYMBOL_COUNT): - total += maxf(loss_symbol_weights[i], 0.0) - var roll := rng.randf() * total - var cumulative := 0.0 - for i in range(1, SYMBOL_COUNT): - cumulative += maxf(loss_symbol_weights[i], 0.0) - if roll < cumulative: - return i - return SYMBOL_COUNT - 1 - - -func _complete_spin() -> void: - if values[0] == PRESENT_SYMBOL and values[0] == values[1] and values[1] == values[2]: - spin_result_label.text = "PRESENT — no award" - elif selected_payout > 0.0: - var symbol_name := symbol_names[values[0]] - spin_result_label.text = "WIN %sx — %s" % [_format_multiplier(selected_payout), symbol_name.to_upper()] - _play_win_celebration() - return - else: - spin_result_label.text = "No win" - _finish_spin() - - -func _play_win_celebration() -> void: - _reset_win_effect() - win_effect_tween = create_tween() - win_effect_tween.tween_interval(0.10) - win_effect_tween.tween_method(_set_win_intensity, 0.0, 1.0, 0.10).set_trans( - Tween.TRANS_QUAD - ).set_ease(Tween.EASE_OUT) - win_effect_tween.tween_method(_set_win_intensity, 1.0, 0.35, 0.13).set_trans( - Tween.TRANS_QUAD - ).set_ease(Tween.EASE_IN) - win_effect_tween.tween_method(_set_win_intensity, 0.35, 0.85, 0.14).set_trans( - Tween.TRANS_SINE - ).set_ease(Tween.EASE_OUT) - win_effect_tween.tween_callback(_award_selected_win) - win_effect_tween.tween_method(_set_win_intensity, 0.85, 0.0, 0.30).set_trans( - Tween.TRANS_SINE - ).set_ease(Tween.EASE_IN_OUT) - win_effect_tween.tween_callback(_finish_spin) - - -func _award_selected_win() -> void: - if values[0] == BLUE_COIN_STACK_SYMBOL: - _play_chip_count(int(roundf(selected_payout))) - _award_counter_for_symbol(values[0], selected_payout) - - -func _set_win_intensity(intensity: float) -> void: - for reel in icon_reels: - reel.material.set_shader_parameter("win_intensity", intensity) - - -func _reset_win_effect() -> void: - if win_effect_tween and win_effect_tween.is_valid(): - win_effect_tween.kill() - win_effect_tween = null - _set_win_intensity(0.0) - - -func _finish_spin() -> void: - _set_win_intensity(0.0) - spin_in_progress = false - if not lever_animating: - lever_button.disabled = false - spin_finished.emit(values.duplicate(), selected_payout) - - -func pull_lever() -> void: - if lever_animating or spin_in_progress: - return - - lever_animating = true - lever_button.disabled = true - if lever_tween and lever_tween.is_valid(): - lever_tween.kill() - if lever_foley_tween and lever_foley_tween.is_valid(): - lever_foley_tween.kill() - var audio_latency := AudioServer.get_output_latency() - audio_latency += AudioServer.get_time_to_next_mix() - lever_foley_tween = create_tween() - lever_foley_tween.tween_interval(maxf(0.28 - audio_latency, 0.0)) - lever_foley_tween.tween_callback(_play_lever_thwap) - lever_tween = create_tween() - lever_tween.tween_method(_set_lever_pull_progress, 0.0, 1.0, 0.28).set_trans( - Tween.TRANS_CUBIC - ).set_ease(Tween.EASE_IN) - lever_tween.tween_callback(spin) - lever_tween.tween_interval(0.08) - lever_tween.tween_method(_set_lever_pull_progress, 1.0, 0.0, 0.46).set_trans( - Tween.TRANS_BACK - ).set_ease(Tween.EASE_OUT) - lever_tween.tween_callback(func() -> void: - lever_animating = false - if not spin_in_progress: - lever_button.disabled = false - ) - - -func _play_lever_thwap() -> void: - var player := audio_pool[next_audio_player] - next_audio_player = (next_audio_player + 1) % audio_pool.size() - player.stream = LEVER_THWAP - player.pitch_scale = 1.0 + randf_range(-pitch_variation * 0.3, pitch_variation * 0.3) - player.volume_db = click_volume_db + 1.5 - player.play(LEVER_THWAP_START_OFFSET) - - -func _play_chip_count(point_count: int) -> void: - if chip_count_tween and chip_count_tween.is_valid(): - chip_count_tween.kill() - chip_count_tween = create_tween() - for point_index in point_count: - chip_count_tween.tween_callback( - _play_chip_point.bind(point_index, point_count) - ) - if point_index < point_count - 1: - var progress := float(point_index) / maxf(float(point_count - 1), 1.0) - chip_count_tween.tween_interval(lerpf(0.105, 0.072, progress)) - - -func _play_chip_point(point_index: int, point_count: int) -> void: - var sound_index := rng.randi_range(0, CHIP_SOUNDS.size() - 2) - if last_chip_sound >= 0 and sound_index >= last_chip_sound: - sound_index += 1 - last_chip_sound = sound_index - var player := audio_pool[next_audio_player] - next_audio_player = (next_audio_player + 1) % audio_pool.size() - player.stream = CHIP_SOUNDS[sound_index] - var count_progress := float(point_index) / maxf(float(point_count - 1), 1.0) - player.pitch_scale = lerpf(0.96, 1.08, count_progress) + randf_range(-0.012, 0.012) - # Individual recordings have long tails, so keep each voice restrained as - # the sequence builds into the familiar overlapping chip-count texture. - player.volume_db = click_volume_db - 3.0 + randf_range(-0.6, 0.4) - player.play(CHIP_START_OFFSETS[sound_index]) - - -func _play_short_reel_whir() -> void: - if reel_whir_tween and reel_whir_tween.is_valid(): - reel_whir_tween.kill() - reel_whir_player.stop() - reel_whir_player.volume_db = reel_whir_volume_db - reel_whir_player.pitch_scale = 0.92 + randf_range(-0.01, 0.01) - # Use only the recording's naturally decelerating tail, then fade it before - # it can compete with the individual reel clicks. - reel_whir_player.play(REEL_WHIR_START_OFFSET) - reel_whir_tween = create_tween() - reel_whir_tween.tween_interval(0.6) - reel_whir_tween.tween_property(reel_whir_player, "volume_db", -60.0, 0.35) - reel_whir_tween.tween_callback(reel_whir_player.stop) - - -func _set_lever_pull_progress(progress: float) -> void: - # The generated poses contain real perspective changes. Per-frame offsets keep - # their slightly different mounting sockets anchored to the cabinet pivot. - lever_pivot.rotation = 0.0 - var frame_index := clampi(roundi(progress * 4.0), 0, 4) - lever_sprite.frame = frame_index - lever_sprite.position = LEVER_FRAME_POSITIONS[frame_index] - - -func _award_counter_for_symbol(symbol_index: int, payout: float) -> void: - match symbol_index: - SINGLE_COIN_SYMBOL: - add_to_number(int(roundf(payout))) - BLUE_COIN_STACK_SYMBOL: - add_to_number(int(roundf(payout))) - - -func _roll_symbol_payout(symbol_index: int) -> float: - if symbol_index == PRESENT_SYMBOL: - return 0.0 - return float(rng.randi_range(symbol_payout_min[symbol_index], symbol_payout_max[symbol_index])) - - -func _get_symbol_model_value(symbol_index: int) -> float: - if symbol_index == PRESENT_SYMBOL: - var other_symbol_total := 0.0 - for i in PRESENT_SYMBOL: - other_symbol_total += _get_symbol_expected_payout(i) - return other_symbol_total / float(PRESENT_SYMBOL) - return _get_symbol_expected_payout(symbol_index) - - -func _get_symbol_expected_payout(symbol_index: int) -> float: - return (float(symbol_payout_min[symbol_index]) + float(symbol_payout_max[symbol_index])) * 0.5 - - -func _format_multiplier(multiplier: float) -> String: - if is_equal_approx(multiplier, roundf(multiplier)): - return str(int(roundf(multiplier))) - return "%.2f" % multiplier - - -func get_theoretical_rtp() -> float: - if not _get_slot_math_error().is_empty(): - return 0.0 - var share_total := _sum_positive(symbol_rtp_shares) - var theoretical_rtp := 0.0 - for i in SYMBOL_COUNT: - var normalized_share := maxf(symbol_rtp_shares[i], 0.0) / share_total - var model_value := _get_symbol_model_value(i) - var probability := target_rtp * normalized_share / model_value - theoretical_rtp += probability * model_value - return theoretical_rtp - - -func get_theoretical_credited_rtp() -> float: - if not _get_slot_math_error().is_empty(): - return 0.0 - var share_total := _sum_positive(symbol_rtp_shares) - var credited_rtp := 0.0 - for i in [SINGLE_COIN_SYMBOL, BLUE_COIN_STACK_SYMBOL]: - var normalized_share := maxf(symbol_rtp_shares[i], 0.0) / share_total - var model_value := _get_symbol_model_value(i) - var probability := target_rtp * normalized_share / model_value - credited_rtp += probability * _get_symbol_expected_payout(i) - return credited_rtp - - -func get_theoretical_hit_rate() -> float: - if not _get_slot_math_error().is_empty(): - return 0.0 - var share_total := _sum_positive(symbol_rtp_shares) - var hit_rate := 0.0 - for i in SYMBOL_COUNT: - var normalized_share := maxf(symbol_rtp_shares[i], 0.0) / share_total - hit_rate += target_rtp * normalized_share / _get_symbol_model_value(i) - return hit_rate - - -func _get_slot_math_error() -> String: - if icon_reels.size() != 3: - return "Slot math requires exactly three icon reels." - if symbol_names.size() != SYMBOL_COUNT: - return "Symbol names must contain exactly six entries." - if symbol_payout_min.size() != SYMBOL_COUNT or symbol_payout_max.size() != SYMBOL_COUNT: - return "Symbol payout minimums and maximums must contain exactly six entries." - if symbol_rtp_shares.size() != SYMBOL_COUNT or loss_symbol_weights.size() != SYMBOL_COUNT: - return "RTP shares and loss display weights must contain exactly six entries." - for i in SYMBOL_COUNT: - if symbol_payout_min[i] < 0 or symbol_payout_max[i] < symbol_payout_min[i]: - return "Symbol payout ranges must be nonnegative and minimum cannot exceed maximum." - if i != PRESENT_SYMBOL and _get_symbol_expected_payout(i) <= 0.0: - return "Every non-present symbol must have a positive expected payout." - if _sum_positive(symbol_rtp_shares) <= 0.0: - return "At least one RTP share must be positive." - if _sum_positive(loss_symbol_weights) <= 0.0: - return "At least one loss display weight must be positive." - var near_miss_weight_total := 0.0 - for i in range(1, SYMBOL_COUNT): - near_miss_weight_total += maxf(loss_symbol_weights[i], 0.0) - if near_miss_rate > 0.0 and near_miss_weight_total <= 0.0: - return "Near misses require a positive display weight for a non-coin symbol." - if near_miss_rate < 0.0 or near_miss_rate > 1.0: - return "Near-miss rate must be between zero and one." - - var share_total := _sum_positive(symbol_rtp_shares) - var total_win_probability := 0.0 - for i in SYMBOL_COUNT: - var normalized_share := maxf(symbol_rtp_shares[i], 0.0) / share_total - total_win_probability += target_rtp * normalized_share / _get_symbol_model_value(i) - if total_win_probability > 1.0: - return "Configured payouts and RTP produce a win probability above 100%." - return "" - - -func _sum_positive(numbers: PackedFloat32Array) -> float: - var total := 0.0 - for number in numbers: - total += maxf(number, 0.0) - return total - - -func _play_reel_click(spin_progress: float, _reel_index: int) -> void: - if audio_pool.is_empty(): - return - - # Avoid the artificial sound of choosing the same sample twice in a row. - var sound_index := randi_range(0, CLICK_SOUNDS.size() - 2) - if last_click_sound >= 0 and sound_index >= last_click_sound: - sound_index += 1 - last_click_sound = sound_index - - var player := audio_pool[next_audio_player] - next_audio_player = (next_audio_player + 1) % audio_pool.size() - player.stream = CLICK_SOUNDS[sound_index] - # The mechanism loses a little energy as it coasts to a stop. Small random - # variation keeps simultaneous reels from sounding cloned. - player.pitch_scale = lerpf(1.08, 0.91, spin_progress) + randf_range( - -pitch_variation, - pitch_variation - ) - player.volume_db = click_volume_db + randf_range(-1.5, 0.8) - player.play(CLICK_START_OFFSETS[sound_index]) - - -func _play_stop_click() -> void: - if audio_pool.is_empty(): - return - - var stop_pitch := 0.97 + randf_range(-pitch_variation * 0.5, pitch_variation * 0.5) - var player := audio_pool[next_audio_player] - next_audio_player = (next_audio_player + 1) % audio_pool.size() - player.stream = STOP_CLICK - player.pitch_scale = stop_pitch - # The source is substantially louder than the four running clicks, so tame it - # slightly while retaining a distinct, weighty reel-lock sound. - player.volume_db = click_volume_db - 2.0 + randf_range(-0.5, 0.5) - player.play(STOP_CLICK_START_OFFSET) - - # Layer the quieter low flap under the detent for mechanical body. Matching - # pitch variation makes both recordings read as one physical impact. - var flap_player := audio_pool[next_audio_player] - next_audio_player = (next_audio_player + 1) % audio_pool.size() - flap_player.stream = STOP_FLAP - flap_player.pitch_scale = stop_pitch - flap_player.volume_db = click_volume_db + 4.0 + randf_range(-0.5, 0.5) - flap_player.play(STOP_FLAP_START_OFFSET) - - -func _play_spin_start() -> void: - if audio_pool.is_empty(): - return - - var player := audio_pool[next_audio_player] - next_audio_player = (next_audio_player + 1) % audio_pool.size() - player.stream = SPIN_START_THUMP - player.pitch_scale = 0.94 + randf_range(-pitch_variation * 0.35, pitch_variation * 0.35) - player.volume_db = click_volume_db + 2.0 + randf_range(-0.4, 0.4) - player.play() - - -func set_number(value: int, animate: bool = true) -> void: - var clamped_value := clampi(value, 0, 9999) - if not animate: - _cancel_number_animation() - number_value = clamped_value - _apply_number_immediately(number_value) - number_change_finished.emit(number_value) - return - - if clamped_value == number_value and not number_animation_active: - number_change_finished.emit(number_value) - return - - var previous_target := number_value - number_value = clamped_value - _animate_number_to(number_value, previous_target, true) - - -func add_to_number(amount: int, animate: bool = true) -> void: - var previous_target := number_value - var new_value := clampi(number_value + amount, 0, 9999) - if not animate: - set_number(new_value, false) - return - - if new_value == previous_target and not number_animation_active: - number_change_finished.emit(number_value) - return - - number_value = new_value - _animate_number_to(number_value, previous_target, true) - - -func get_number() -> int: - return number_value - - -func is_number_animating() -> bool: - return number_animation_active - - -func test_counter_setting() -> void: - set_number(randi_range(0, 9999)) - - -func go_to_doctor_scene() -> void: - continue_requested.emit() - - -func _animate_number_to(target_value: int, previous_target: int, is_addition: bool) -> void: - _cancel_number_animation() - if number_reels.is_empty(): - number_change_finished.emit(number_value) - return - - number_animation_active = true - var amount := target_value - previous_target - var direction := signi(amount) - var duration := number_roll_duration - if is_addition: - duration += minf(float(absi(amount)) / 1000.0, 1.0) * 0.35 - - for i in number_reels.size(): - var reel := number_reels[i] - var start := float(reel.material.get_shader_parameter("y_offset")) - var target_digit := _digit_at(target_value, i) - var current_digit_position := start * 10.0 - var current_digit_phase := fposmod(current_digit_position, 10.0) - var digit_steps: float - - if is_addition and direction != 0: - var place := _place_for_index(i) - var transition_count := floori(float(target_value) / place) - transition_count -= floori(float(previous_target) / place) - var extra_turns := mini(floori(float(absi(transition_count)) / 10.0), 3) - if direction > 0: - digit_steps = fposmod(float(target_digit) - current_digit_phase, 10.0) - digit_steps += extra_turns * 10.0 - else: - digit_steps = -fposmod(current_digit_phase - float(target_digit), 10.0) - digit_steps -= extra_turns * 10.0 - else: - # This is only reached when retargeting to the same value from a - # fractional position; settle directly without choosing a spin direction. - digit_steps = fposmod(float(target_digit) - current_digit_phase + 5.0, 10.0) - 5.0 - - var target_offset := start + digit_steps / 10.0 - var digit_tween := create_tween() - number_tweens.append(digit_tween) - digit_tween.tween_method( - func(offset: float) -> void: - reel.material.set_shader_parameter("y_offset", offset), - start, - target_offset, - duration - ).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT) - digit_tween.tween_callback(func() -> void: - reel.material.set_shader_parameter("y_offset", float(target_digit) / 10.0) - ) - - var completion_tween := create_tween() - number_tweens.append(completion_tween) - completion_tween.tween_interval(duration) - completion_tween.tween_callback(func() -> void: - number_animation_active = false - number_tweens.clear() - number_change_finished.emit(number_value) - ) - - -func _cancel_number_animation() -> void: - for active_tween in number_tweens: - if active_tween and active_tween.is_valid(): - active_tween.kill() - number_tweens.clear() - number_animation_active = false - - -func _apply_number_immediately(value: int) -> void: - for i in mini(number_reels.size(), 4): - var digit := _digit_at(value, i) - number_reels[i].material.set_shader_parameter("y_offset", float(digit) / 10.0) - - -func _digit_at(value: int, index: int) -> int: - return floori(float(value) / _place_for_index(index)) % 10 - - -func _place_for_index(index: int) -> int: - return int(pow(10, 3 - index)) diff --git a/scripts/ui/ccs_cases_2/slot_machine.gd.uid b/scripts/ui/ccs_cases_2/slot_machine.gd.uid deleted file mode 100644 index c66a3d9..0000000 --- a/scripts/ui/ccs_cases_2/slot_machine.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://dv7jjfmghs0rg diff --git a/scripts/ui/ccs_cases_2_screen.gd b/scripts/ui/ccs_cases_2_screen.gd index aa11a20..ab516f2 100644 --- a/scripts/ui/ccs_cases_2_screen.gd +++ b/scripts/ui/ccs_cases_2_screen.gd @@ -1,6 +1,5 @@ extends Control -const SLOT_SCENE := preload("res://scenes/ccs_cases_2/slot_machine.tscn") const DOCTOR_SCENE := preload("res://scenes/ccs_cases_2/doctor_office.tscn") const DESIGN_SIZE := Vector2(1500.0, 800.0) @@ -21,19 +20,13 @@ func _ready() -> void: func on_show(_payload: Variant = null) -> void: - _show_slot_machine() + _show_doctor_office() func on_hide() -> void: _clear_active_scene() -func _show_slot_machine() -> void: - _set_active_scene(SLOT_SCENE.instantiate(), "slot_machine") - if active_scene.has_signal("continue_requested"): - active_scene.continue_requested.connect(_show_doctor_office) - - func _show_doctor_office() -> void: _set_active_scene(DOCTOR_SCENE.instantiate(), "doctor_office") diff --git a/shaders/ccs_cases_2/reel_spin.gdshader b/shaders/ccs_cases_2/reel_spin.gdshader deleted file mode 100644 index 06a7796..0000000 --- a/shaders/ccs_cases_2/reel_spin.gdshader +++ /dev/null @@ -1,42 +0,0 @@ -shader_type canvas_item; - -uniform sampler2D tex : repeat_enable; -uniform float n_rows = 6.0; -uniform float y_offset = 0.0; -uniform float x_offset = 0.0; -uniform float win_intensity : hint_range(0.0, 1.0) = 0.0; -uniform vec4 win_glow_color : source_color = vec4(1.0, 0.62, 0.08, 1.0); - -void fragment() { - vec2 uv = UV; - uv.x += x_offset; - uv.y /= n_rows; - uv.y += y_offset; - - vec4 base = texture(tex, uv); - if (win_intensity <= 0.001) { - COLOR = base; - } else { - // Derive a compact halo from the existing symbol alpha so no replacement - // sprite or second texture is needed. - vec2 pixel = 1.0 / vec2(textureSize(tex, 0)); - vec2 radius = pixel * 5.0; - float nearby_alpha = 0.0; - nearby_alpha = max(nearby_alpha, texture(tex, uv + vec2(radius.x, 0.0)).a); - nearby_alpha = max(nearby_alpha, texture(tex, uv - vec2(radius.x, 0.0)).a); - nearby_alpha = max(nearby_alpha, texture(tex, uv + vec2(0.0, radius.y)).a); - nearby_alpha = max(nearby_alpha, texture(tex, uv - vec2(0.0, radius.y)).a); - nearby_alpha = max(nearby_alpha, texture(tex, uv + radius).a); - nearby_alpha = max(nearby_alpha, texture(tex, uv - radius).a); - nearby_alpha = max(nearby_alpha, texture(tex, uv + vec2(radius.x, -radius.y)).a); - nearby_alpha = max(nearby_alpha, texture(tex, uv + vec2(-radius.x, radius.y)).a); - - float halo = max(nearby_alpha - base.a, 0.0) * win_intensity; - float flash = smoothstep(0.82, 1.0, win_intensity); - vec3 rich_color = min(base.rgb * 1.18 + win_glow_color.rgb * 0.12, vec3(1.0)); - vec3 symbol_color = mix(base.rgb, rich_color, win_intensity); - symbol_color = mix(symbol_color, vec3(1.0), flash * 0.34 * base.a); - vec3 final_rgb = symbol_color * base.a + win_glow_color.rgb * halo; - COLOR = vec4(final_rgb, max(base.a, halo * 0.9)); - } -} diff --git a/shaders/ccs_cases_2/reel_spin.gdshader.uid b/shaders/ccs_cases_2/reel_spin.gdshader.uid deleted file mode 100644 index 944c7e4..0000000 --- a/shaders/ccs_cases_2/reel_spin.gdshader.uid +++ /dev/null @@ -1 +0,0 @@ -uid://l6j3wkyf1ygq diff --git a/tests/ccs_cases_2_ui_test.gd b/tests/ccs_cases_2_ui_test.gd index bc361ae..1a587bd 100644 --- a/tests/ccs_cases_2_ui_test.gd +++ b/tests/ccs_cases_2_ui_test.gd @@ -28,12 +28,9 @@ func _run() -> void: await process_frame screen.on_show() await process_frame - _assert(screen.current_view == "slot_machine", "CCS Cases 2 should open on the slot machine") - _assert(screen.active_scene != null and screen.active_scene.has_signal("continue_requested"), "slot machine should expose an embedded continue signal") + _assert(screen.current_view == "doctor_office", "CCS Cases 2 should open directly in the doctor office") + _assert(screen.active_scene != null, "CCS Cases 2 should instantiate the doctor-office scene") _assert(is_equal_approx(screen.stage_root.scale.x, screen.stage_root.scale.y), "the graphical stage should preserve its aspect ratio") - screen.active_scene.continue_requested.emit() - await process_frame - _assert(screen.current_view == "doctor_office", "Continue should open the doctor office without replacing the app scene") screen.on_hide() await process_frame _assert(screen.active_scene == null and screen.current_view.is_empty(), "hiding CCS Cases 2 should release the prototype scene")