Initial scaffold: Godot 4.3 scenes, systems, and placeholders.
Wire all twelve levels with billboard prefabs, autoload systems (inventory, achievements, mock shop, DE/EN/BY), and satire audio locks so the Title→End flow is playable with placeholder assets.
29
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Godot 4
|
||||
.godot/
|
||||
.import/
|
||||
export.cfg
|
||||
export_presets.cfg
|
||||
*.translation
|
||||
|
||||
# Build / OS
|
||||
*.apk
|
||||
*.aab
|
||||
*.ipa
|
||||
*.app
|
||||
*.dmg
|
||||
*.exe
|
||||
*.x86_64
|
||||
*.x86
|
||||
*.arm64
|
||||
*.arm32
|
||||
*.wasm
|
||||
*.pck
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
*~
|
||||
|
||||
# Editor / agent
|
||||
.cursor/
|
||||
*.swp
|
||||
*.tmp
|
||||
/tmp/
|
||||
65
README.md
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# Explosion der Spiele
|
||||
|
||||
Pay2Win – um reiche Leute anzulocken. Absichtlich chaotisches Meta-Comedy-Action-Adventure in Godot 4.3+ mit 2.5D-Billboard-Sprites.
|
||||
|
||||
**Forgejo:** https://forgejo.fsociety00.cc/copilot/Explosion_der_Spiele
|
||||
|
||||
## Start
|
||||
|
||||
1. Godot **4.3+** installieren (oder `~/.local/bin/godot` aus dem Scaffold-Setup)
|
||||
2. Projektordner in Godot öffnen
|
||||
3. F5 / Play — startet `scenes/title_screen.tscn`
|
||||
|
||||
### Steuerung
|
||||
|
||||
| Aktion | Taste |
|
||||
|--------|--------|
|
||||
| Bewegen | WASD / Pfeile |
|
||||
| Interagieren | E / Leertaste |
|
||||
| Angriff | Linksklick / J |
|
||||
| Pause (Shop/Inventar/Settings) | Esc |
|
||||
| Cutscene skippen | Enter |
|
||||
|
||||
Im Inventar (Pause): Item doppelklicken/aktivieren — **Milch** skippt zum Endboss.
|
||||
|
||||
## Scaffold-Inhalt
|
||||
|
||||
- 12 Szenen verdrahtet (Title → Intro → Village → … → Final → End + Death)
|
||||
- Autoloads: `GameState`, `Inventory`, `Achievements`, `Settings`, `Locale` (DE/EN/BY), `Shop` (Mock), `AudioDirector`, `UIRoot`
|
||||
- Billboard-Prefab (`PlaneMesh` + `billboard_mode`)
|
||||
- Pay-to-Win-Shop ohne echte Zahlungen (`1€ = 1 Dresslerpunkt` Mock-Button)
|
||||
- Musik-Lautstärke absichtlich gesperrt (bleibt laut)
|
||||
- Burger-Cham-Event alle 120s auf dem Title Screen
|
||||
- Save unter `user://save.json`
|
||||
|
||||
## Regenerieren von Platzhaltern
|
||||
|
||||
```bash
|
||||
python3 scripts/tools/generate_scaffold.py
|
||||
```
|
||||
|
||||
## Asset-TODOs (noch ersetzen)
|
||||
|
||||
### Grafik
|
||||
|
||||
- Titelbild: verpixeltes Mario + Sonic + Burger-Regen + verstörter Mensch
|
||||
- Burger-Cham-Bild (70-jähriger Mann mit Burger)
|
||||
- Intro Tisch/Konsole vor/nach Explosion
|
||||
- Dorf-Häuser & verstörte Dorfbewohner
|
||||
- Schuhmacher Reif, Eisbär + Schlangenmähdrescher, Schlange, Kuh-Masseur
|
||||
- Glitzos, dunkelgrauer Magier, bayerischer Farmer, Urhahn, Nutztiere
|
||||
- Mond: Käseverkäufer, Katapulte, Mondschwert, Fake Bowser
|
||||
- Dresslermeister (Riesenapfel), Hongkong/Glitschkönig, Quirxels
|
||||
- Todesbildschirm / UI-Icons (Zahn, Milch, Banane, Wartchen, …)
|
||||
|
||||
### Audio
|
||||
|
||||
- Laute Startmusik mit Gesang („Hey, das hier ist so eine laute Musik extra…“)
|
||||
- Sprecher Intro / Hongkong / Dorf / Bayerisch „Schulz“ / EN / DE-Snippets
|
||||
- Burger-Cham, Explosion, Kämpfe, Massage, Käsekatapult, …
|
||||
|
||||
Aktuell liegen nur generierte Beep-WAVs unter `assets/audio/placeholders/`.
|
||||
|
||||
## Hinweis
|
||||
|
||||
Keine echten Zahlungen, keine lizenzierten Charakter-Assets — alles Satire/Platzhalter.
|
||||
BIN
assets/audio/placeholders/music_title.wav
Normal file
24
assets/audio/placeholders/music_title.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://nhwevpdjup3n"
|
||||
path="res://.godot/imported/music_title.wav-57b4e64507bbc8925e954e4e57e5851e.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/placeholders/music_title.wav"
|
||||
dest_files=["res://.godot/imported/music_title.wav-57b4e64507bbc8925e954e4e57e5851e.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=0
|
||||
BIN
assets/audio/placeholders/sfx_burger.wav
Normal file
24
assets/audio/placeholders/sfx_burger.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://c2npy2yl10fnk"
|
||||
path="res://.godot/imported/sfx_burger.wav-db0aa5a35f09b19628bcc5adb31f2f05.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/placeholders/sfx_burger.wav"
|
||||
dest_files=["res://.godot/imported/sfx_burger.wav-db0aa5a35f09b19628bcc5adb31f2f05.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=0
|
||||
BIN
assets/audio/placeholders/sfx_explosion.wav
Normal file
24
assets/audio/placeholders/sfx_explosion.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://co6y6u2bhy6h0"
|
||||
path="res://.godot/imported/sfx_explosion.wav-77982b105b7a7f0e48a5d77c7259ba4b.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/placeholders/sfx_explosion.wav"
|
||||
dest_files=["res://.godot/imported/sfx_explosion.wav-77982b105b7a7f0e48a5d77c7259ba4b.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=0
|
||||
BIN
assets/audio/placeholders/sfx_hit.wav
Normal file
24
assets/audio/placeholders/sfx_hit.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://cbh0wcso2lbc0"
|
||||
path="res://.godot/imported/sfx_hit.wav-d268f78f266f112d5872bff13bfabd54.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/placeholders/sfx_hit.wav"
|
||||
dest_files=["res://.godot/imported/sfx_hit.wav-d268f78f266f112d5872bff13bfabd54.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=0
|
||||
BIN
assets/audio/placeholders/voice_by.wav
Normal file
24
assets/audio/placeholders/voice_by.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://cim5abw2jutxg"
|
||||
path="res://.godot/imported/voice_by.wav-4a06e6c3862106da5c3ffb005bb73594.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/placeholders/voice_by.wav"
|
||||
dest_files=["res://.godot/imported/voice_by.wav-4a06e6c3862106da5c3ffb005bb73594.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=0
|
||||
BIN
assets/audio/placeholders/voice_de.wav
Normal file
24
assets/audio/placeholders/voice_de.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://dn0idcqha2dt3"
|
||||
path="res://.godot/imported/voice_de.wav-527db9c39a6a9179700a48588b5966b4.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/placeholders/voice_de.wav"
|
||||
dest_files=["res://.godot/imported/voice_de.wav-527db9c39a6a9179700a48588b5966b4.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=0
|
||||
BIN
assets/audio/placeholders/voice_en.wav
Normal file
24
assets/audio/placeholders/voice_en.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://dbgd6utbqexdl"
|
||||
path="res://.godot/imported/voice_en.wav-8421c4eefb2d6ff186d4f1843721b23e.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/placeholders/voice_en.wav"
|
||||
dest_files=["res://.godot/imported/voice_en.wav-8421c4eefb2d6ff186d4f1843721b23e.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=0
|
||||
BIN
assets/sprites/placeholders/apple.png
Normal file
|
After Width: | Height: | Size: 82 B |
34
assets/sprites/placeholders/apple.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b37uov28lxb2u"
|
||||
path="res://.godot/imported/apple.png-dde7f9d0b34ab9bfe7973a6edb4257ce.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/apple.png"
|
||||
dest_files=["res://.godot/imported/apple.png-dde7f9d0b34ab9bfe7973a6edb4257ce.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/bear.png
Normal file
|
After Width: | Height: | Size: 83 B |
34
assets/sprites/placeholders/bear.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dh5i54nbbbj6r"
|
||||
path="res://.godot/imported/bear.png-02b280fa351cad00e3ac7c302cee163d.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/bear.png"
|
||||
dest_files=["res://.godot/imported/bear.png-02b280fa351cad00e3ac7c302cee163d.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/bowser.png
Normal file
|
After Width: | Height: | Size: 82 B |
34
assets/sprites/placeholders/bowser.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://baruvthy65fu1"
|
||||
path="res://.godot/imported/bowser.png-c84ab30a63fce643c365f696605d01d2.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/bowser.png"
|
||||
dest_files=["res://.godot/imported/bowser.png-c84ab30a63fce643c365f696605d01d2.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/burger.png
Normal file
|
After Width: | Height: | Size: 82 B |
34
assets/sprites/placeholders/burger.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://uyn85tw36akw"
|
||||
path="res://.godot/imported/burger.png-3df913a40d4a086c06294c0a44a2fa1e.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/burger.png"
|
||||
dest_files=["res://.godot/imported/burger.png-3df913a40d4a086c06294c0a44a2fa1e.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/cheese.png
Normal file
|
After Width: | Height: | Size: 83 B |
34
assets/sprites/placeholders/cheese.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bluonhwj4bue2"
|
||||
path="res://.godot/imported/cheese.png-91a03b4c9a1a30165eb93db45ccb7f2c.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/cheese.png"
|
||||
dest_files=["res://.godot/imported/cheese.png-91a03b4c9a1a30165eb93db45ccb7f2c.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/cow.png
Normal file
|
After Width: | Height: | Size: 94 B |
34
assets/sprites/placeholders/cow.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bxbfjo6md4v2u"
|
||||
path="res://.godot/imported/cow.png-5af0a175ec8cb018d78c655e4e9d50ab.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/cow.png"
|
||||
dest_files=["res://.godot/imported/cow.png-5af0a175ec8cb018d78c655e4e9d50ab.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/disturbed.png
Normal file
|
After Width: | Height: | Size: 101 B |
34
assets/sprites/placeholders/disturbed.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://v2ptpx03awel"
|
||||
path="res://.godot/imported/disturbed.png-fdb7e57dbd8f4fd176e77131b1f9ae80.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/disturbed.png"
|
||||
dest_files=["res://.godot/imported/disturbed.png-fdb7e57dbd8f4fd176e77131b1f9ae80.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/enemy.png
Normal file
|
After Width: | Height: | Size: 104 B |
34
assets/sprites/placeholders/enemy.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bjo2jmg30dwlb"
|
||||
path="res://.godot/imported/enemy.png-2bc00d5222c6ad20d9fbc774f89ed042.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/enemy.png"
|
||||
dest_files=["res://.godot/imported/enemy.png-2bc00d5222c6ad20d9fbc774f89ed042.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/farmer.png
Normal file
|
After Width: | Height: | Size: 82 B |
34
assets/sprites/placeholders/farmer.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cnhxctf1imwsb"
|
||||
path="res://.godot/imported/farmer.png-35160a98f4d1ab8cce31fcf559333381.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/farmer.png"
|
||||
dest_files=["res://.godot/imported/farmer.png-35160a98f4d1ab8cce31fcf559333381.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/glitzo.png
Normal file
|
After Width: | Height: | Size: 96 B |
34
assets/sprites/placeholders/glitzo.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cadkrhb8eu8jq"
|
||||
path="res://.godot/imported/glitzo.png-e4c6cb631c224e6a8ab47dcff37802b0.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/glitzo.png"
|
||||
dest_files=["res://.godot/imported/glitzo.png-e4c6cb631c224e6a8ab47dcff37802b0.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/hongkong.png
Normal file
|
After Width: | Height: | Size: 90 B |
34
assets/sprites/placeholders/hongkong.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bwloqkk48cr1o"
|
||||
path="res://.godot/imported/hongkong.png-1b0e65f7ca46d69b86624e44d93f5178.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/hongkong.png"
|
||||
dest_files=["res://.godot/imported/hongkong.png-1b0e65f7ca46d69b86624e44d93f5178.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/house.png
Normal file
|
After Width: | Height: | Size: 82 B |
34
assets/sprites/placeholders/house.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b0ia7b1sjbxj2"
|
||||
path="res://.godot/imported/house.png-f12f204fc595e6df46c249db8b7216a0.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/house.png"
|
||||
dest_files=["res://.godot/imported/house.png-f12f204fc595e6df46c249db8b7216a0.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/icon.png
Normal file
|
After Width: | Height: | Size: 95 B |
34
assets/sprites/placeholders/icon.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://crnb86h5j70mg"
|
||||
path="res://.godot/imported/icon.png-8434f827a87e33b3fd72236835b6f111.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/icon.png"
|
||||
dest_files=["res://.godot/imported/icon.png-8434f827a87e33b3fd72236835b6f111.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/mage.png
Normal file
|
After Width: | Height: | Size: 82 B |
34
assets/sprites/placeholders/mage.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://fiud1rqkrsif"
|
||||
path="res://.godot/imported/mage.png-ee7edbc9dcd55175c02ebedf34804aa8.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/mage.png"
|
||||
dest_files=["res://.godot/imported/mage.png-ee7edbc9dcd55175c02ebedf34804aa8.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/mario.png
Normal file
|
After Width: | Height: | Size: 82 B |
34
assets/sprites/placeholders/mario.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c80pynhwy8fsk"
|
||||
path="res://.godot/imported/mario.png-973ed4c47ea1f2908c76904a3e7156bf.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/mario.png"
|
||||
dest_files=["res://.godot/imported/mario.png-973ed4c47ea1f2908c76904a3e7156bf.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/npc.png
Normal file
|
After Width: | Height: | Size: 101 B |
34
assets/sprites/placeholders/npc.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bf73lxk3qoj3x"
|
||||
path="res://.godot/imported/npc.png-c9f72d8cc600833078acd2b5de3e225c.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/npc.png"
|
||||
dest_files=["res://.godot/imported/npc.png-c9f72d8cc600833078acd2b5de3e225c.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/player.png
Normal file
|
After Width: | Height: | Size: 101 B |
34
assets/sprites/placeholders/player.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://maq6a015enut"
|
||||
path="res://.godot/imported/player.png-2b290dc7723bf72b037d787d1b30075d.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/player.png"
|
||||
dest_files=["res://.godot/imported/player.png-2b290dc7723bf72b037d787d1b30075d.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/quirxel.png
Normal file
|
After Width: | Height: | Size: 76 B |
34
assets/sprites/placeholders/quirxel.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://u1hyriw1ibin"
|
||||
path="res://.godot/imported/quirxel.png-fcf13717d2eb4da0c9997e65d430ccd1.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/quirxel.png"
|
||||
dest_files=["res://.godot/imported/quirxel.png-fcf13717d2eb4da0c9997e65d430ccd1.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/rooster.png
Normal file
|
After Width: | Height: | Size: 82 B |
34
assets/sprites/placeholders/rooster.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://daxjrieeu120x"
|
||||
path="res://.godot/imported/rooster.png-9a1e1d11af73a69166984766ee65babc.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/rooster.png"
|
||||
dest_files=["res://.godot/imported/rooster.png-9a1e1d11af73a69166984766ee65babc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/shoe.png
Normal file
|
After Width: | Height: | Size: 82 B |
34
assets/sprites/placeholders/shoe.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://i5qx8kyrhbxb"
|
||||
path="res://.godot/imported/shoe.png-29f3e83b74b5ec37f2dbe3ba2ab6702e.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/shoe.png"
|
||||
dest_files=["res://.godot/imported/shoe.png-29f3e83b74b5ec37f2dbe3ba2ab6702e.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/skull.png
Normal file
|
After Width: | Height: | Size: 83 B |
34
assets/sprites/placeholders/skull.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://ccl8j0eef53by"
|
||||
path="res://.godot/imported/skull.png-8a0473e644f92d1307336c1250a35ad4.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/skull.png"
|
||||
dest_files=["res://.godot/imported/skull.png-8a0473e644f92d1307336c1250a35ad4.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/snake.png
Normal file
|
After Width: | Height: | Size: 82 B |
34
assets/sprites/placeholders/snake.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://1ajf0vlua0uu"
|
||||
path="res://.godot/imported/snake.png-b61c1accf854736987940264d77b0800.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/snake.png"
|
||||
dest_files=["res://.godot/imported/snake.png-b61c1accf854736987940264d77b0800.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
BIN
assets/sprites/placeholders/sonic.png
Normal file
|
After Width: | Height: | Size: 82 B |
34
assets/sprites/placeholders/sonic.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://db7yx7878cuor"
|
||||
path="res://.godot/imported/sonic.png-76fdb2575572fa769f6910819c2f27ea.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/placeholders/sonic.png"
|
||||
dest_files=["res://.godot/imported/sonic.png-76fdb2575572fa769f6910819c2f27ea.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
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/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
|
||||
72
data/achievements.json
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
[
|
||||
{
|
||||
"id": "died_100",
|
||||
"title_key": "ach_died_100_title",
|
||||
"desc_key": "ach_died_100_desc"
|
||||
},
|
||||
{
|
||||
"id": "tiramisu_tonne",
|
||||
"title_key": "ach_tiramisu_title",
|
||||
"desc_key": "ach_tiramisu_desc"
|
||||
},
|
||||
{
|
||||
"id": "snake_massage",
|
||||
"title_key": "ach_snake_massage_title",
|
||||
"desc_key": "ach_snake_massage_desc"
|
||||
},
|
||||
{
|
||||
"id": "milk_skip",
|
||||
"title_key": "ach_milk_skip_title",
|
||||
"desc_key": "ach_milk_skip_desc"
|
||||
},
|
||||
{
|
||||
"id": "first_glitzo",
|
||||
"title_key": "ach_first_glitzo_title",
|
||||
"desc_key": "ach_first_glitzo_desc"
|
||||
},
|
||||
{
|
||||
"id": "moon_cheese",
|
||||
"title_key": "ach_moon_cheese_title",
|
||||
"desc_key": "ach_moon_cheese_desc"
|
||||
},
|
||||
{
|
||||
"id": "eaten_to_death",
|
||||
"title_key": "ach_eaten_title",
|
||||
"desc_key": "ach_eaten_desc"
|
||||
},
|
||||
{
|
||||
"id": "played_hour",
|
||||
"title_key": "ach_hour_title",
|
||||
"desc_key": "ach_hour_desc"
|
||||
},
|
||||
{
|
||||
"id": "cool_sunglasses",
|
||||
"title_key": "ach_sunglasses_title",
|
||||
"desc_key": "ach_sunglasses_desc"
|
||||
},
|
||||
{
|
||||
"id": "dressler_apples",
|
||||
"title_key": "ach_dressler_title",
|
||||
"desc_key": "ach_dressler_desc"
|
||||
},
|
||||
{
|
||||
"id": "beat_bowser",
|
||||
"title_key": "ach_bowser_title",
|
||||
"desc_key": "ach_bowser_desc"
|
||||
},
|
||||
{
|
||||
"id": "beat_hongkong",
|
||||
"title_key": "ach_hongkong_title",
|
||||
"desc_key": "ach_hongkong_desc"
|
||||
},
|
||||
{
|
||||
"id": "tooth_millionaire",
|
||||
"title_key": "ach_tooth_title",
|
||||
"desc_key": "ach_tooth_desc"
|
||||
},
|
||||
{
|
||||
"id": "all_burgers",
|
||||
"title_key": "ach_all_title",
|
||||
"desc_key": "ach_all_desc"
|
||||
}
|
||||
]
|
||||
13
data/items.json
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
[
|
||||
{"id": "tooth", "name_key": "item_tooth", "stackable": true},
|
||||
{"id": "snake", "name_key": "item_snake", "stackable": false},
|
||||
{"id": "milk", "name_key": "item_milk", "stackable": true, "usable": true},
|
||||
{"id": "banana", "name_key": "item_banana", "stackable": true},
|
||||
{"id": "wartchen", "name_key": "item_wartchen", "stackable": true},
|
||||
{"id": "sunglasses", "name_key": "item_sunglasses", "stackable": false},
|
||||
{"id": "death_ticket", "name_key": "item_death_ticket", "stackable": true, "usable": true},
|
||||
{"id": "moon_sword", "name_key": "item_moon_sword", "stackable": false},
|
||||
{"id": "chicken", "name_key": "item_chicken", "stackable": true},
|
||||
{"id": "cheese", "name_key": "item_cheese", "stackable": true},
|
||||
{"id": "tiramisu", "name_key": "item_tiramisu", "stackable": true, "usable": true}
|
||||
]
|
||||
88
data/locales/by.json
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
{
|
||||
"menu_start": "Losgeh!",
|
||||
"menu_continue": "Weidermacha",
|
||||
"menu_settings": "Einstellunga",
|
||||
"menu_shop": "Pay-to-Win-Gschäft",
|
||||
"menu_inventory": "Rucksack",
|
||||
"menu_language": "Sproch",
|
||||
"menu_sfx": "SFX-Lautstärkn",
|
||||
"menu_music": "Musikk (bleibt laut)",
|
||||
"menu_quit": "Aufhören",
|
||||
"menu_resume": "Zruck",
|
||||
"menu_buy_point": "1€ = 1 Dresslerpunkt (Mock)",
|
||||
"menu_points": "Dresslerpunkte: %s",
|
||||
"title_subtitle": "Pay2Win – damit de Reichen kommen",
|
||||
"title_bubble": "Oi mei, des wird so verrückt. Hongkong is a weiser Mo.",
|
||||
"death_title": "DU BIST DAHI",
|
||||
"death_continue": "No amoi sterbn?",
|
||||
"interact_hint": "[E] Redn",
|
||||
"exit_hint": "Level verlassn",
|
||||
"lang_voice_de": "Am deutschen Wesen soll die Welt genesen",
|
||||
"lang_voice_en": "I drink my garden in the cinema",
|
||||
"lang_voice_by": "Schulz",
|
||||
"dialog_reif": "Wennst no ned reif bist, muaß i da an Schuah schenken!",
|
||||
"dialog_snake": "I bin ganz verspannt, oi tut des weh",
|
||||
"dialog_bear": "Hongkong hot den Rasenmäher zu Schlangen gmochd",
|
||||
"dialog_hongkong_npc": "Hongkong, Hongkong is er!",
|
||||
"dialog_cow": "Massage: Schlang / Spieler / Quadrat-Emoji",
|
||||
"dialog_farmer": "Servus! De Schweine brauchn Quests und der Urhahn pickt.",
|
||||
"dialog_mage": "Rechts gehts zum Hof. Links is Fake-Open-World.",
|
||||
"dialog_cheese": "Der Mond is aus Kas. Willst a Sonnenbrille?",
|
||||
"dialog_bowser": "I halt a Hendl gfangn! (Fake Bowser)",
|
||||
"dialog_hongkong_boss": "I kimm wieder!",
|
||||
"dialog_bear_end": "Guad dassd unsere Welt grettet host. Aber Zahnarzt kostet immer no.",
|
||||
"dialog_dressler": "Dresslauf die Eins!",
|
||||
"dialog_intro_1": "Du sitzt an deim Tisch…",
|
||||
"dialog_intro_2": "Du muasst es schaffn, sonst kommt der Hongkong",
|
||||
"death_shoe": "Schuah gschenkt kriagt",
|
||||
"death_mower": "Mähdrescher-Biss",
|
||||
"death_rooster": "Vom Urhahn totpickt",
|
||||
"death_quirxel": "Vom Quirxel gquadratet",
|
||||
"death_default": "Z'Tode gstorbn",
|
||||
"item_tooth": "Zahn",
|
||||
"item_snake": "Schlang",
|
||||
"item_milk": "Selbergmelkte Milch",
|
||||
"item_banana": "Banane",
|
||||
"item_wartchen": "Wartchen",
|
||||
"item_sunglasses": "Coole Sonnenbrille",
|
||||
"item_death_ticket": "Ticket: Z'Tode gessen",
|
||||
"item_moon_sword": "Mondschwert",
|
||||
"item_chicken": "Hendl",
|
||||
"item_cheese": "Verschimmelta Kas",
|
||||
"item_tiramisu": "Tiramisu (kg)",
|
||||
"shop_sunglasses": "Sonnenbrille (5 Punkte)",
|
||||
"shop_ticket": "Z'Tode-gessen-Ticket (3 Punkte)",
|
||||
"shop_milk": "Milch-Skip (10 Punkte)",
|
||||
"shop_tiramisu": "1kg Tiramisu (1 Punkt)",
|
||||
"toast_achievement": "Achievement: %s",
|
||||
"build_house": "Haus baua",
|
||||
"ach_died_100_title": "Z'Tode gstorbn",
|
||||
"ach_died_100_desc": "100x sterbn",
|
||||
"ach_tiramisu_title": "Jetzt is Abnehma ogfragt",
|
||||
"ach_tiramisu_desc": "1 Tonne Tiramisu essn",
|
||||
"ach_snake_massage_title": "Schlangenmassage",
|
||||
"ach_snake_massage_desc": "Schlang zum Masseur bringa",
|
||||
"ach_milk_skip_title": "Selbergmelkte Milch",
|
||||
"ach_milk_skip_desc": "Milch trinkn und zum Endboss skippen",
|
||||
"ach_first_glitzo_title": "So pixelig dass i scho a Pixel war",
|
||||
"ach_first_glitzo_desc": "Ersten Glitzo tötn",
|
||||
"ach_moon_cheese_title": "Jetzt woaß i dass der Mond aus Kas is",
|
||||
"ach_moon_cheese_desc": "Mond-Level betretn",
|
||||
"ach_eaten_title": "Z'Tode gessen",
|
||||
"ach_eaten_desc": "Z'Tode-gessen-Ticket essn",
|
||||
"ach_hour_title": "Überlegt",
|
||||
"ach_hour_desc": "1 Stund spuin",
|
||||
"ach_sunglasses_title": "Coole Sonnenbrille",
|
||||
"ach_sunglasses_desc": "Sonnenbrille am Mond kaafn",
|
||||
"ach_dressler_title": "De Äpfel san heit guat dresselt worn",
|
||||
"ach_dressler_desc": "Dresslermeister bsiegn",
|
||||
"ach_bowser_title": "Du host einfach den Bowser bsiegt",
|
||||
"ach_bowser_desc": "Bowser bsiegn",
|
||||
"ach_hongkong_title": "Du host des endgültig geglitched",
|
||||
"ach_hongkong_desc": "Hongkong bsiegn",
|
||||
"ach_tooth_title": "Du bist jetzt Zahnionär",
|
||||
"ach_tooth_desc": "Zähne beim Zahnarzt klauen",
|
||||
"ach_all_title": "Burger, Burger, Burger. Heit ess i alle Quests",
|
||||
"ach_all_desc": "Alle Achievements freischaltn",
|
||||
"burger_cham": "Burger! Beste Qualität von der Explosion der Spiele"
|
||||
}
|
||||
88
data/locales/de.json
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
{
|
||||
"menu_start": "Starten",
|
||||
"menu_continue": "Weiter",
|
||||
"menu_settings": "Einstellungen",
|
||||
"menu_shop": "Pay-to-Win-Shop",
|
||||
"menu_inventory": "Inventar",
|
||||
"menu_language": "Sprache",
|
||||
"menu_sfx": "SFX-Lautstärke",
|
||||
"menu_music": "Musik (gesperrt laut)",
|
||||
"menu_quit": "Beenden",
|
||||
"menu_resume": "Zurück",
|
||||
"menu_buy_point": "1€ = 1 Dresslerpunkt (Mock)",
|
||||
"menu_points": "Dresslerpunkte: %s",
|
||||
"title_subtitle": "Pay2Win – um reiche Leute anzulocken",
|
||||
"title_bubble": "Oh mein Gott, es wird so verrückt. Hongkong ist ein weiser Mann.",
|
||||
"death_title": "DU BIST GESTORBEN",
|
||||
"death_continue": "Nochmal sterben wollen?",
|
||||
"interact_hint": "[E] Interagieren",
|
||||
"exit_hint": "Level verlassen",
|
||||
"lang_voice_de": "Am deutschen Wesen soll die Welt genesen",
|
||||
"lang_voice_en": "I drink my garden in the cinema",
|
||||
"lang_voice_by": "Schulz",
|
||||
"dialog_reif": "Wenn du noch nicht reif bist, muss ich dir einen Schuh schenken!",
|
||||
"dialog_snake": "Ich bin sehr verspannt, oh, mir tut alles so weh",
|
||||
"dialog_bear": "Hongkong hat den Rasenmäher zu Schlangen verwandelt",
|
||||
"dialog_hongkong_npc": "Hongkong, Hongkong ist er!",
|
||||
"dialog_cow": "Massageoptionen: Schlange / Spieler / Quadrat-Emoji",
|
||||
"dialog_farmer": "Servus! Die Schweine brauchen Quests und der Urhahn pickt.",
|
||||
"dialog_mage": "Der Weg nach rechts führt zum Bauernhof. Links ist Fake-Open-World.",
|
||||
"dialog_cheese": "Der Mond ist aus Käse. Willst du eine Sonnenbrille?",
|
||||
"dialog_bowser": "Ich halte ein Huhn gefangen! (Fake Bowser)",
|
||||
"dialog_hongkong_boss": "Ich werde wiederkommen!",
|
||||
"dialog_bear_end": "Gut, dass du unsere Welt gerettet hast. Aber die Zahnarztkosten sind immer noch teuer.",
|
||||
"dialog_dressler": "Dresslauf die Eins!",
|
||||
"dialog_intro_1": "Du sitzt an deinem Tisch…",
|
||||
"dialog_intro_2": "Du musst es schaffen, sonst kommt der Hongkong",
|
||||
"death_shoe": "Schuh geschenkt",
|
||||
"death_mower": "Mähdrescher-Biss",
|
||||
"death_rooster": "Vom Urhahn totgepickt",
|
||||
"death_quirxel": "Von einem Quirxel gequadratet",
|
||||
"death_default": "Zu Tode gestorben",
|
||||
"item_tooth": "Zahn",
|
||||
"item_snake": "Schlange",
|
||||
"item_milk": "Selbst gemelkte Milch",
|
||||
"item_banana": "Banane",
|
||||
"item_wartchen": "Wartchen",
|
||||
"item_sunglasses": "Coole Sonnenbrille",
|
||||
"item_death_ticket": "Ticket: Zu Tode gegessen",
|
||||
"item_moon_sword": "Mondschwert",
|
||||
"item_chicken": "Huhn",
|
||||
"item_cheese": "Verschimmelter Käse",
|
||||
"item_tiramisu": "Tiramisu (kg)",
|
||||
"shop_sunglasses": "Sonnenbrille (5 Punkte)",
|
||||
"shop_ticket": "Zu-Tode-gegessen-Ticket (3 Punkte)",
|
||||
"shop_milk": "Milch-Skip (10 Punkte)",
|
||||
"shop_tiramisu": "1kg Tiramisu (1 Punkt)",
|
||||
"toast_achievement": "Achievement: %s",
|
||||
"build_house": "Haus bauen",
|
||||
"ach_died_100_title": "Zu Tode gestorben",
|
||||
"ach_died_100_desc": "100x sterben",
|
||||
"ach_tiramisu_title": "Jetzt ist Abnehmen angesagt",
|
||||
"ach_tiramisu_desc": "1 Tonne Tiramisu essen",
|
||||
"ach_snake_massage_title": "Schlangenmassage",
|
||||
"ach_snake_massage_desc": "Schlange zum Masseur bringen",
|
||||
"ach_milk_skip_title": "Selbst gemelkte Milch",
|
||||
"ach_milk_skip_desc": "Milch trinken und zum Endboss skippen",
|
||||
"ach_first_glitzo_title": "Das ist ja so pixelig, dass ich schon ein Pixel würde",
|
||||
"ach_first_glitzo_desc": "Ersten Glitzo töten",
|
||||
"ach_moon_cheese_title": "Jetzt weiß ich, dass der Mond aus Käse ist",
|
||||
"ach_moon_cheese_desc": "Mond-Level betreten",
|
||||
"ach_eaten_title": "Zu Tode gegessen",
|
||||
"ach_eaten_desc": "Zu-Tode-gegessen-Ticket essen",
|
||||
"ach_hour_title": "Überlegt",
|
||||
"ach_hour_desc": "1 Stunde spielen",
|
||||
"ach_sunglasses_title": "Coole Sonnenbrille",
|
||||
"ach_sunglasses_desc": "Sonnenbrille auf dem Mond kaufen",
|
||||
"ach_dressler_title": "Die Äpfel wurden heute echt gut gedresselt",
|
||||
"ach_dressler_desc": "Dresslermeister besiegen",
|
||||
"ach_bowser_title": "Du hast einfach den Bowser besiegt",
|
||||
"ach_bowser_desc": "Bowser besiegen",
|
||||
"ach_hongkong_title": "Du hast das endgültig geglitched",
|
||||
"ach_hongkong_desc": "Hongkong besiegen",
|
||||
"ach_tooth_title": "Du bist jetzt Zahnionär",
|
||||
"ach_tooth_desc": "Zähne beim Zahnarzt klauen",
|
||||
"ach_all_title": "Burger, Burger, Burger. Heute ess ich alle Quests",
|
||||
"ach_all_desc": "Alle Achievements freischalten",
|
||||
"burger_cham": "Burger! Beste Qualität von der Explosion der Spiele"
|
||||
}
|
||||
88
data/locales/en.json
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
{
|
||||
"menu_start": "Start",
|
||||
"menu_continue": "Continue",
|
||||
"menu_settings": "Settings",
|
||||
"menu_shop": "Pay-to-Win Shop",
|
||||
"menu_inventory": "Inventory",
|
||||
"menu_language": "Language",
|
||||
"menu_sfx": "SFX Volume",
|
||||
"menu_music": "Music (locked loud)",
|
||||
"menu_quit": "Quit",
|
||||
"menu_resume": "Resume",
|
||||
"menu_buy_point": "1€ = 1 Dressler Point (Mock)",
|
||||
"menu_points": "Dressler Points: %s",
|
||||
"title_subtitle": "Pay2Win – to attract rich people",
|
||||
"title_bubble": "Oh my god, it will get so crazy. Hongkong is a wise man.",
|
||||
"death_title": "YOU DIED",
|
||||
"death_continue": "Want to die again?",
|
||||
"interact_hint": "[E] Interact",
|
||||
"exit_hint": "Leave level",
|
||||
"lang_voice_de": "Am deutschen Wesen soll die Welt genesen",
|
||||
"lang_voice_en": "I drink my garden in the cinema",
|
||||
"lang_voice_by": "Schulz",
|
||||
"dialog_reif": "If you are not ripe yet, I must gift you a shoe!",
|
||||
"dialog_snake": "I am very tense, oh everything hurts",
|
||||
"dialog_bear": "Hongkong turned the lawnmower into snakes",
|
||||
"dialog_hongkong_npc": "Hongkong, Hongkong is he!",
|
||||
"dialog_cow": "Massage options: Snake / Player / Square Emoji",
|
||||
"dialog_farmer": "Howdy! Pigs need quests and the Ur-rooster pecks.",
|
||||
"dialog_mage": "Right path leads to the farm. Left is fake open world.",
|
||||
"dialog_cheese": "The moon is made of cheese. Want sunglasses?",
|
||||
"dialog_bowser": "I am holding a chicken hostage! (Fake Bowser)",
|
||||
"dialog_hongkong_boss": "I will return!",
|
||||
"dialog_bear_end": "Good that you saved our world. But dental costs are still expensive.",
|
||||
"dialog_dressler": "Dress run the one!",
|
||||
"dialog_intro_1": "You sit at your desk…",
|
||||
"dialog_intro_2": "You must succeed, or Hongkong comes",
|
||||
"death_shoe": "Gifted a shoe",
|
||||
"death_mower": "Combine-harvester bite",
|
||||
"death_rooster": "Pecked to death by Ur-rooster",
|
||||
"death_quirxel": "Squared by a Quirxel",
|
||||
"death_default": "Died to death",
|
||||
"item_tooth": "Tooth",
|
||||
"item_snake": "Snake",
|
||||
"item_milk": "Self-reported milk",
|
||||
"item_banana": "Banana",
|
||||
"item_wartchen": "Wartchen",
|
||||
"item_sunglasses": "Cool sunglasses",
|
||||
"item_death_ticket": "Ticket: Eaten to death",
|
||||
"item_moon_sword": "Moon sword",
|
||||
"item_chicken": "Chicken",
|
||||
"item_cheese": "Moldy cheese",
|
||||
"item_tiramisu": "Tiramisu (kg)",
|
||||
"shop_sunglasses": "Sunglasses (5 points)",
|
||||
"shop_ticket": "Eaten-to-death ticket (3 points)",
|
||||
"shop_milk": "Milk skip (10 points)",
|
||||
"shop_tiramisu": "1kg tiramisu (1 point)",
|
||||
"toast_achievement": "Achievement: %s",
|
||||
"build_house": "Build house",
|
||||
"ach_died_100_title": "Died to death",
|
||||
"ach_died_100_desc": "Die 100 times",
|
||||
"ach_tiramisu_title": "Time to lose weight",
|
||||
"ach_tiramisu_desc": "Eat 1 ton of tiramisu",
|
||||
"ach_snake_massage_title": "Snake massage",
|
||||
"ach_snake_massage_desc": "Bring the snake to the masseur",
|
||||
"ach_milk_skip_title": "Self-reported milk",
|
||||
"ach_milk_skip_desc": "Drink milk and skip to final boss",
|
||||
"ach_first_glitzo_title": "So pixelly I might become a pixel",
|
||||
"ach_first_glitzo_desc": "Kill the first Glitzo",
|
||||
"ach_moon_cheese_title": "Now I know the moon is cheese",
|
||||
"ach_moon_cheese_desc": "Enter the moon level",
|
||||
"ach_eaten_title": "Eaten to death",
|
||||
"ach_eaten_desc": "Eat the eaten-to-death ticket",
|
||||
"ach_hour_title": "Thoughtful",
|
||||
"ach_hour_desc": "Play for 1 hour",
|
||||
"ach_sunglasses_title": "Cool sunglasses",
|
||||
"ach_sunglasses_desc": "Buy sunglasses on the moon",
|
||||
"ach_dressler_title": "The apples were dressed well today",
|
||||
"ach_dressler_desc": "Defeat Dresslermeister",
|
||||
"ach_bowser_title": "You simply beat Bowser",
|
||||
"ach_bowser_desc": "Defeat Bowser",
|
||||
"ach_hongkong_title": "You finally glitched it",
|
||||
"ach_hongkong_desc": "Defeat Hongkong",
|
||||
"ach_tooth_title": "You are now a toothionaire",
|
||||
"ach_tooth_desc": "Steal teeth at the dentist",
|
||||
"ach_all_title": "Burger, Burger, Burger. Today I eat all quests",
|
||||
"ach_all_desc": "Unlock all achievements",
|
||||
"burger_cham": "Burger! Best quality from Explosion der Spiele"
|
||||
}
|
||||
94
project.godot
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
; Engine configuration file.
|
||||
; Explosion der Spiele — Pay2Win Chaos Scaffold (Godot 4.3+)
|
||||
|
||||
config_version=5
|
||||
|
||||
[application]
|
||||
|
||||
config/name="Explosion der Spiele"
|
||||
config/description="Pay2Win – um reiche Leute anzulocken. Absichtlich chaotisches Meta-Comedy-Spiel."
|
||||
config/version="0.1.0-scaffold"
|
||||
run/main_scene="res://scenes/title_screen.tscn"
|
||||
config/features=PackedStringArray("4.3", "Forward Plus")
|
||||
config/icon="res://assets/sprites/placeholders/icon.png"
|
||||
|
||||
[autoload]
|
||||
|
||||
Settings="*res://scripts/autoload/settings.gd"
|
||||
Locale="*res://scripts/autoload/locale.gd"
|
||||
Inventory="*res://scripts/autoload/inventory.gd"
|
||||
Achievements="*res://scripts/autoload/achievements.gd"
|
||||
Shop="*res://scripts/autoload/shop.gd"
|
||||
AudioDirector="*res://scripts/autoload/audio_director.gd"
|
||||
GameState="*res://scripts/autoload/game_state.gd"
|
||||
UIRoot="*res://scenes/ui/ui_root.tscn"
|
||||
|
||||
[display]
|
||||
|
||||
window/size/viewport_width=1280
|
||||
window/size/viewport_height=720
|
||||
window/stretch/mode="canvas_items"
|
||||
window/stretch/aspect="expand"
|
||||
|
||||
[input]
|
||||
|
||||
move_left={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194319,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_right={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_up={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_down={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194322,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
interact={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
attack={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":74,"key_label":0,"unicode":106,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
pause_menu={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
skip_cutscene={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194309,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
[layer_names]
|
||||
|
||||
3d_physics/layer_1="world"
|
||||
3d_physics/layer_2="player"
|
||||
3d_physics/layer_3="enemy"
|
||||
3d_physics/layer_4="interact"
|
||||
3d_physics/layer_5="hazard"
|
||||
3d_physics/layer_6="exit"
|
||||
|
||||
[rendering]
|
||||
|
||||
textures/canvas_textures/default_texture_filter=0
|
||||
anti_aliasing/quality/msaa_3d=0
|
||||
73
scenes/death_screen.tscn
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
[gd_scene load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/levels/death_screen.gd" id="1"]
|
||||
|
||||
[node name="DeathScreen" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="Bg" type="ColorRect" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
color = Color(0.7, 0.1, 0.5, 1)
|
||||
|
||||
[node name="Title" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 5
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
offset_left = -300.0
|
||||
offset_top = 120.0
|
||||
offset_right = 300.0
|
||||
offset_bottom = 180.0
|
||||
theme_override_font_sizes/font_size = 36
|
||||
horizontal_alignment = 1
|
||||
text = "DU BIST GESTORBEN"
|
||||
|
||||
[node name="Cause" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 5
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
offset_left = -300.0
|
||||
offset_top = 200.0
|
||||
offset_right = 300.0
|
||||
offset_bottom = 250.0
|
||||
horizontal_alignment = 1
|
||||
text = "..."
|
||||
|
||||
[node name="Skull" type="ColorRect" parent="."]
|
||||
visible = false
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -40.0
|
||||
offset_top = -40.0
|
||||
offset_right = 40.0
|
||||
offset_bottom = 40.0
|
||||
color = Color(1, 1, 1, 1)
|
||||
|
||||
[node name="ContinueButton" type="Button" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 7
|
||||
anchor_left = 0.5
|
||||
anchor_top = 1.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 1.0
|
||||
offset_left = -160.0
|
||||
offset_top = -120.0
|
||||
offset_right = 160.0
|
||||
offset_bottom = -70.0
|
||||
text = "Continue"
|
||||
|
||||
[connection signal="pressed" from="ContinueButton" to="." method="_on_continue_pressed"]
|
||||
58
scenes/end_screen.tscn
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
[gd_scene load_steps=8 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/levels/end_screen.gd" id="1"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/player.tscn" id="2"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/exit_trigger.tscn" id="3"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/npc.tscn" id="4"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/enemy.tscn" id="5"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/hazard.tscn" id="6"]
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_ground"]
|
||||
size = Vector3(40, 0.2, 40)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="Mat_ground"]
|
||||
albedo_color = Color(0.4, 0.7, 0.45, 1)
|
||||
shading_mode = 0
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape_ground"]
|
||||
size = Vector3(40, 0.2, 40)
|
||||
|
||||
[node name="end_screen" type="Node3D"]
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(0.866, -0.354, 0.354, 0, 0.707, 0.707, -0.5, -0.612, 0.612, 0, 8, 0)
|
||||
shadow_enabled = false
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.707, 0.707, 0, -0.707, 0.707, 0, 12, 12)
|
||||
current = true
|
||||
fov = 50.0
|
||||
|
||||
[node name="Ground" type="StaticBody3D" parent="."]
|
||||
collision_layer = 1
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="Ground"]
|
||||
mesh = SubResource("BoxMesh_ground")
|
||||
surface_material_override/0 = SubResource("Mat_ground")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Ground"]
|
||||
shape = SubResource("BoxShape_ground")
|
||||
|
||||
[node name="Player" parent="." instance=ExtResource("2")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 4)
|
||||
|
||||
|
||||
[node name="BearEnd" parent="." instance=ExtResource("4")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 0.1, 0)
|
||||
dialog_key = "dialog_bear_end"
|
||||
texture_path = "res://assets/sprites/placeholders/bear.png"
|
||||
|
||||
[node name="HouseSpot" parent="." instance=ExtResource("4")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0.1, -2)
|
||||
dialog_key = "build_house"
|
||||
texture_path = "res://assets/sprites/placeholders/house.png"
|
||||
quest_flag = "house_built"
|
||||
|
||||
75
scenes/farm.tscn
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
[gd_scene load_steps=8 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/levels/farm.gd" id="1"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/player.tscn" id="2"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/exit_trigger.tscn" id="3"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/npc.tscn" id="4"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/enemy.tscn" id="5"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/hazard.tscn" id="6"]
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_ground"]
|
||||
size = Vector3(40, 0.2, 40)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="Mat_ground"]
|
||||
albedo_color = Color(0.45, 0.35, 0.2, 1)
|
||||
shading_mode = 0
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape_ground"]
|
||||
size = Vector3(40, 0.2, 40)
|
||||
|
||||
[node name="farm" type="Node3D"]
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(0.866, -0.354, 0.354, 0, 0.707, 0.707, -0.5, -0.612, 0.612, 0, 8, 0)
|
||||
shadow_enabled = false
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.707, 0.707, 0, -0.707, 0.707, 0, 12, 12)
|
||||
current = true
|
||||
fov = 50.0
|
||||
|
||||
[node name="Ground" type="StaticBody3D" parent="."]
|
||||
collision_layer = 1
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="Ground"]
|
||||
mesh = SubResource("BoxMesh_ground")
|
||||
surface_material_override/0 = SubResource("Mat_ground")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Ground"]
|
||||
shape = SubResource("BoxShape_ground")
|
||||
|
||||
[node name="Player" parent="." instance=ExtResource("2")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 4)
|
||||
|
||||
|
||||
[node name="Farmer" parent="." instance=ExtResource("4")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 0.1, 0)
|
||||
dialog_key = "dialog_farmer"
|
||||
texture_path = "res://assets/sprites/placeholders/farmer.png"
|
||||
give_item_id = "chicken"
|
||||
|
||||
[node name="Urhahn" parent="." instance=ExtResource("5")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 0.1, -2)
|
||||
max_hp = 6
|
||||
texture_path = "res://assets/sprites/placeholders/rooster.png"
|
||||
defeat_flag = "urhahn_defeated"
|
||||
|
||||
[node name="RoosterHazard" parent="." instance=ExtResource("6")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 0.1, -4)
|
||||
death_cause_key = "death_rooster"
|
||||
|
||||
|
||||
[node name="Dressler" parent="." instance=ExtResource("5")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4, 0.1, -4)
|
||||
max_hp = 5
|
||||
texture_path = "res://assets/sprites/placeholders/apple.png"
|
||||
defeat_flag = "dressler_defeated"
|
||||
achievement_on_defeat = "dressler_apples"
|
||||
|
||||
[node name="Exit" parent="." instance=ExtResource("3")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, -12)
|
||||
require_flag = "urhahn_defeated"
|
||||
|
||||
57
scenes/farm_path.tscn
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
[gd_scene load_steps=8 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/levels/farm_path.gd" id="1"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/player.tscn" id="2"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/exit_trigger.tscn" id="3"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/npc.tscn" id="4"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/enemy.tscn" id="5"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/hazard.tscn" id="6"]
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_ground"]
|
||||
size = Vector3(40, 0.2, 40)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="Mat_ground"]
|
||||
albedo_color = Color(0.55, 0.5, 0.3, 1)
|
||||
shading_mode = 0
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape_ground"]
|
||||
size = Vector3(40, 0.2, 40)
|
||||
|
||||
[node name="farm_path" type="Node3D"]
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(0.866, -0.354, 0.354, 0, 0.707, 0.707, -0.5, -0.612, 0.612, 0, 8, 0)
|
||||
shadow_enabled = false
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.707, 0.707, 0, -0.707, 0.707, 0, 12, 12)
|
||||
current = true
|
||||
fov = 50.0
|
||||
|
||||
[node name="Ground" type="StaticBody3D" parent="."]
|
||||
collision_layer = 1
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="Ground"]
|
||||
mesh = SubResource("BoxMesh_ground")
|
||||
surface_material_override/0 = SubResource("Mat_ground")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Ground"]
|
||||
shape = SubResource("BoxShape_ground")
|
||||
|
||||
[node name="Player" parent="." instance=ExtResource("2")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 4)
|
||||
|
||||
|
||||
[node name="Mage" parent="." instance=ExtResource("4")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, -3)
|
||||
dialog_key = "dialog_mage"
|
||||
texture_path = "res://assets/sprites/placeholders/mage.png"
|
||||
quest_flag = "mage_talked"
|
||||
|
||||
[node name="Exit" parent="." instance=ExtResource("3")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4, 0.1, -10)
|
||||
require_flag = "mage_talked"
|
||||
|
||||
62
scenes/final_boss.tscn
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
[gd_scene load_steps=8 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/levels/final_boss.gd" id="1"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/player.tscn" id="2"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/exit_trigger.tscn" id="3"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/npc.tscn" id="4"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/enemy.tscn" id="5"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/hazard.tscn" id="6"]
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_ground"]
|
||||
size = Vector3(40, 0.2, 40)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="Mat_ground"]
|
||||
albedo_color = Color(0.15, 0.05, 0.2, 1)
|
||||
shading_mode = 0
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape_ground"]
|
||||
size = Vector3(40, 0.2, 40)
|
||||
|
||||
[node name="final_boss" type="Node3D"]
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(0.866, -0.354, 0.354, 0, 0.707, 0.707, -0.5, -0.612, 0.612, 0, 8, 0)
|
||||
shadow_enabled = false
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.707, 0.707, 0, -0.707, 0.707, 0, 12, 12)
|
||||
current = true
|
||||
fov = 50.0
|
||||
|
||||
[node name="Ground" type="StaticBody3D" parent="."]
|
||||
collision_layer = 1
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="Ground"]
|
||||
mesh = SubResource("BoxMesh_ground")
|
||||
surface_material_override/0 = SubResource("Mat_ground")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Ground"]
|
||||
shape = SubResource("BoxShape_ground")
|
||||
|
||||
[node name="Player" parent="." instance=ExtResource("2")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 4)
|
||||
|
||||
|
||||
[node name="Hongkong" parent="." instance=ExtResource("5")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, -3)
|
||||
max_hp = 12
|
||||
texture_path = "res://assets/sprites/placeholders/hongkong.png"
|
||||
defeat_flag = "hongkong_defeated"
|
||||
achievement_on_defeat = "beat_hongkong"
|
||||
|
||||
[node name="QuirxelHazard" parent="." instance=ExtResource("6")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0.1, -2)
|
||||
death_cause_key = "death_quirxel"
|
||||
|
||||
[node name="Exit" parent="." instance=ExtResource("3")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, -12)
|
||||
require_flag = "hongkong_defeated"
|
||||
|
||||
73
scenes/intro_cutscene.tscn
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
[gd_scene load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/levels/intro_cutscene.gd" id="1"]
|
||||
|
||||
[node name="IntroCutscene" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="Bg" type="ColorRect" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
color = Color(0.12, 0.1, 0.08, 1)
|
||||
|
||||
[node name="Desk" type="ColorRect" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -200.0
|
||||
offset_top = -40.0
|
||||
offset_right = 200.0
|
||||
offset_bottom = 80.0
|
||||
color = Color(0.45, 0.28, 0.12, 1)
|
||||
|
||||
[node name="Console" type="ColorRect" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -60.0
|
||||
offset_top = -100.0
|
||||
offset_right = 60.0
|
||||
offset_bottom = -40.0
|
||||
color = Color(0.2, 0.2, 0.25, 1)
|
||||
|
||||
[node name="Label" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 5
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
offset_left = -400.0
|
||||
offset_top = 40.0
|
||||
offset_right = 400.0
|
||||
offset_bottom = 120.0
|
||||
horizontal_alignment = 1
|
||||
autowrap_mode = 3
|
||||
text = "..."
|
||||
|
||||
[node name="SkipButton" type="Button" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 7
|
||||
anchor_left = 0.5
|
||||
anchor_top = 1.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 1.0
|
||||
offset_left = -80.0
|
||||
offset_top = -80.0
|
||||
offset_right = 80.0
|
||||
offset_bottom = -40.0
|
||||
text = "Skip / Weiter"
|
||||
|
||||
[connection signal="pressed" from="SkipButton" to="." method="_on_skip_pressed"]
|
||||
59
scenes/massage_studio.tscn
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
[gd_scene load_steps=8 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/levels/massage_studio.gd" id="1"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/player.tscn" id="2"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/exit_trigger.tscn" id="3"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/npc.tscn" id="4"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/enemy.tscn" id="5"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/hazard.tscn" id="6"]
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_ground"]
|
||||
size = Vector3(40, 0.2, 40)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="Mat_ground"]
|
||||
albedo_color = Color(0.7, 0.55, 0.5, 1)
|
||||
shading_mode = 0
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape_ground"]
|
||||
size = Vector3(40, 0.2, 40)
|
||||
|
||||
[node name="massage_studio" type="Node3D"]
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(0.866, -0.354, 0.354, 0, 0.707, 0.707, -0.5, -0.612, 0.612, 0, 8, 0)
|
||||
shadow_enabled = false
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.707, 0.707, 0, -0.707, 0.707, 0, 12, 12)
|
||||
current = true
|
||||
fov = 50.0
|
||||
|
||||
[node name="Ground" type="StaticBody3D" parent="."]
|
||||
collision_layer = 1
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="Ground"]
|
||||
mesh = SubResource("BoxMesh_ground")
|
||||
surface_material_override/0 = SubResource("Mat_ground")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Ground"]
|
||||
shape = SubResource("BoxShape_ground")
|
||||
|
||||
[node name="Player" parent="." instance=ExtResource("2")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 4)
|
||||
|
||||
|
||||
[node name="CowMasseur" parent="." instance=ExtResource("4")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, -2)
|
||||
dialog_key = "dialog_cow"
|
||||
texture_path = "res://assets/sprites/placeholders/cow.png"
|
||||
require_item_id = "snake"
|
||||
consume_required = true
|
||||
quest_flag = "snake_massaged"
|
||||
achievement_id = "snake_massage"
|
||||
|
||||
[node name="Exit" parent="." instance=ExtResource("3")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, -10)
|
||||
|
||||
65
scenes/meadow.tscn
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
[gd_scene load_steps=8 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/levels/meadow.gd" id="1"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/player.tscn" id="2"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/exit_trigger.tscn" id="3"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/npc.tscn" id="4"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/enemy.tscn" id="5"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/hazard.tscn" id="6"]
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_ground"]
|
||||
size = Vector3(40, 0.2, 40)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="Mat_ground"]
|
||||
albedo_color = Color(0.4, 0.75, 0.3, 1)
|
||||
shading_mode = 0
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape_ground"]
|
||||
size = Vector3(40, 0.2, 40)
|
||||
|
||||
[node name="meadow" type="Node3D"]
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(0.866, -0.354, 0.354, 0, 0.707, 0.707, -0.5, -0.612, 0.612, 0, 8, 0)
|
||||
shadow_enabled = false
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.707, 0.707, 0, -0.707, 0.707, 0, 12, 12)
|
||||
current = true
|
||||
fov = 50.0
|
||||
|
||||
[node name="Ground" type="StaticBody3D" parent="."]
|
||||
collision_layer = 1
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="Ground"]
|
||||
mesh = SubResource("BoxMesh_ground")
|
||||
surface_material_override/0 = SubResource("Mat_ground")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Ground"]
|
||||
shape = SubResource("BoxShape_ground")
|
||||
|
||||
[node name="Player" parent="." instance=ExtResource("2")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 4)
|
||||
|
||||
|
||||
[node name="Glitzo" parent="." instance=ExtResource("5")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 0.1, -1)
|
||||
max_hp = 4
|
||||
texture_path = "res://assets/sprites/placeholders/glitzo.png"
|
||||
achievement_on_defeat = "first_glitzo"
|
||||
|
||||
[node name="Bear" parent="." instance=ExtResource("4")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0.1, -3)
|
||||
dialog_key = "dialog_bear"
|
||||
texture_path = "res://assets/sprites/placeholders/bear.png"
|
||||
|
||||
[node name="MowerHazard" parent="." instance=ExtResource("6")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, -5)
|
||||
death_cause_key = "death_mower"
|
||||
|
||||
[node name="Exit" parent="." instance=ExtResource("3")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, -12)
|
||||
|
||||
70
scenes/moon.tscn
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
[gd_scene load_steps=8 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/levels/moon.gd" id="1"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/player.tscn" id="2"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/exit_trigger.tscn" id="3"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/npc.tscn" id="4"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/enemy.tscn" id="5"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/hazard.tscn" id="6"]
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_ground"]
|
||||
size = Vector3(40, 0.2, 40)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="Mat_ground"]
|
||||
albedo_color = Color(0.75, 0.75, 0.7, 1)
|
||||
shading_mode = 0
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape_ground"]
|
||||
size = Vector3(40, 0.2, 40)
|
||||
|
||||
[node name="moon" type="Node3D"]
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(0.866, -0.354, 0.354, 0, 0.707, 0.707, -0.5, -0.612, 0.612, 0, 8, 0)
|
||||
shadow_enabled = false
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.707, 0.707, 0, -0.707, 0.707, 0, 12, 12)
|
||||
current = true
|
||||
fov = 50.0
|
||||
|
||||
[node name="Ground" type="StaticBody3D" parent="."]
|
||||
collision_layer = 1
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="Ground"]
|
||||
mesh = SubResource("BoxMesh_ground")
|
||||
surface_material_override/0 = SubResource("Mat_ground")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Ground"]
|
||||
shape = SubResource("BoxShape_ground")
|
||||
|
||||
[node name="Player" parent="." instance=ExtResource("2")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 4)
|
||||
|
||||
|
||||
[node name="CheeseSeller" parent="." instance=ExtResource("4")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 0.1, -1)
|
||||
dialog_key = "dialog_cheese"
|
||||
texture_path = "res://assets/sprites/placeholders/cheese.png"
|
||||
give_item_id = "cheese"
|
||||
|
||||
[node name="SwordStone" parent="." instance=ExtResource("4")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0.1, -1)
|
||||
dialog_key = "dialog_cheese"
|
||||
texture_path = "res://assets/sprites/placeholders/apple.png"
|
||||
give_item_id = "moon_sword"
|
||||
|
||||
[node name="FakeBowser" parent="." instance=ExtResource("5")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, -4)
|
||||
max_hp = 8
|
||||
texture_path = "res://assets/sprites/placeholders/bowser.png"
|
||||
defeat_flag = "bowser_defeated"
|
||||
achievement_on_defeat = "beat_bowser"
|
||||
|
||||
[node name="Exit" parent="." instance=ExtResource("3")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, -12)
|
||||
require_flag = "bowser_defeated"
|
||||
|
||||
8
scenes/prefabs/billboard_sprite.tscn
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
[gd_scene load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/billboard/billboard_sprite.gd" id="1"]
|
||||
|
||||
[node name="BillboardSprite" type="Node3D"]
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
||||
11
scenes/prefabs/enemy.tscn
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
[gd_scene load_steps=3 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/combat/hittable.gd" id="1"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/billboard_sprite.tscn" id="2"]
|
||||
|
||||
[node name="Enemy" type="Node3D"]
|
||||
script = ExtResource("1")
|
||||
max_hp = 4
|
||||
|
||||
[node name="BillboardSprite" parent="." instance=ExtResource("2")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.6, 0)
|
||||
15
scenes/prefabs/exit_trigger.tscn
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[gd_scene load_steps=3 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/combat/exit_trigger.gd" id="1"]
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape3D_1"]
|
||||
size = Vector3(2.5, 2, 2.5)
|
||||
|
||||
[node name="ExitTrigger" type="Area3D"]
|
||||
collision_layer = 0
|
||||
collision_mask = 2
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
|
||||
shape = SubResource("BoxShape3D_1")
|
||||
15
scenes/prefabs/hazard.tscn
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[gd_scene load_steps=3 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/combat/hazard_zone.gd" id="1"]
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape3D_1"]
|
||||
size = Vector3(2.0, 2, 2.0)
|
||||
|
||||
[node name="HazardZone" type="Area3D"]
|
||||
collision_layer = 0
|
||||
collision_mask = 2
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
|
||||
shape = SubResource("BoxShape3D_1")
|
||||
10
scenes/prefabs/npc.tscn
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[gd_scene load_steps=3 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/combat/interactable_npc.gd" id="1"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/billboard_sprite.tscn" id="2"]
|
||||
|
||||
[node name="NPC" type="Node3D"]
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="BillboardSprite" parent="." instance=ExtResource("2")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.6, 0)
|
||||
20
scenes/prefabs/player.tscn
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
[gd_scene load_steps=4 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/player/player_controller.gd" id="1"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/billboard_sprite.tscn" id="2"]
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_1"]
|
||||
radius = 0.35
|
||||
height = 1.0
|
||||
|
||||
[node name="Player" type="CharacterBody3D"]
|
||||
collision_layer = 2
|
||||
collision_mask = 1
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0)
|
||||
shape = SubResource("CapsuleShape3D_1")
|
||||
|
||||
[node name="BillboardSprite" parent="." instance=ExtResource("2")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.6, 0)
|
||||
57
scenes/shoe_boss.tscn
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
[gd_scene load_steps=8 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/levels/shoe_boss.gd" id="1"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/player.tscn" id="2"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/exit_trigger.tscn" id="3"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/npc.tscn" id="4"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/enemy.tscn" id="5"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/hazard.tscn" id="6"]
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_ground"]
|
||||
size = Vector3(40, 0.2, 40)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="Mat_ground"]
|
||||
albedo_color = Color(0.25, 0.2, 0.15, 1)
|
||||
shading_mode = 0
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape_ground"]
|
||||
size = Vector3(40, 0.2, 40)
|
||||
|
||||
[node name="shoe_boss" type="Node3D"]
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(0.866, -0.354, 0.354, 0, 0.707, 0.707, -0.5, -0.612, 0.612, 0, 8, 0)
|
||||
shadow_enabled = false
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.707, 0.707, 0, -0.707, 0.707, 0, 12, 12)
|
||||
current = true
|
||||
fov = 50.0
|
||||
|
||||
[node name="Ground" type="StaticBody3D" parent="."]
|
||||
collision_layer = 1
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="Ground"]
|
||||
mesh = SubResource("BoxMesh_ground")
|
||||
surface_material_override/0 = SubResource("Mat_ground")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Ground"]
|
||||
shape = SubResource("BoxShape_ground")
|
||||
|
||||
[node name="Player" parent="." instance=ExtResource("2")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 4)
|
||||
|
||||
|
||||
[node name="Reif" parent="." instance=ExtResource("5")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, -2)
|
||||
max_hp = 5
|
||||
texture_path = "res://assets/sprites/placeholders/shoe.png"
|
||||
defeat_flag = "reif_defeated"
|
||||
|
||||
[node name="Exit" parent="." instance=ExtResource("3")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, -12)
|
||||
require_flag = "reif_defeated"
|
||||
|
||||
84
scenes/title_screen.tscn
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
[gd_scene load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/levels/title_screen.gd" id="1"]
|
||||
|
||||
[node name="TitleScreen" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="Bg" type="ColorRect" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
color = Color(0.08, 0.05, 0.12, 1)
|
||||
|
||||
[node name="Rain" type="Node2D" parent="."]
|
||||
|
||||
[node name="Title" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 5
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
offset_left = -360.0
|
||||
offset_top = 80.0
|
||||
offset_right = 360.0
|
||||
offset_bottom = 140.0
|
||||
grow_horizontal = 2
|
||||
theme_override_font_sizes/font_size = 40
|
||||
horizontal_alignment = 1
|
||||
text = "Explosion der Spiele"
|
||||
|
||||
[node name="Subtitle" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 5
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
offset_left = -360.0
|
||||
offset_top = 140.0
|
||||
offset_right = 360.0
|
||||
offset_bottom = 180.0
|
||||
grow_horizontal = 2
|
||||
horizontal_alignment = 1
|
||||
text = "Pay2Win"
|
||||
|
||||
[node name="Bubble" type="Label" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 40.0
|
||||
offset_top = 500.0
|
||||
offset_right = 420.0
|
||||
offset_bottom = 620.0
|
||||
autowrap_mode = 3
|
||||
text = "..."
|
||||
|
||||
[node name="Disturbed" type="ColorRect" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 40.0
|
||||
offset_top = 620.0
|
||||
offset_right = 120.0
|
||||
offset_bottom = 700.0
|
||||
color = Color(0.7, 0.7, 0.7, 1)
|
||||
|
||||
[node name="StartButton" type="Button" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 7
|
||||
anchor_left = 0.5
|
||||
anchor_top = 1.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 1.0
|
||||
offset_left = -120.0
|
||||
offset_top = -120.0
|
||||
offset_right = 120.0
|
||||
offset_bottom = -70.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 0
|
||||
text = "Starten"
|
||||
|
||||
[connection signal="pressed" from="StartButton" to="." method="_on_start_pressed"]
|
||||
197
scenes/ui/ui_root.tscn
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
[gd_scene load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/ui/ui_root.gd" id="1"]
|
||||
|
||||
[node name="UIRoot" type="CanvasLayer"]
|
||||
process_mode = 3
|
||||
layer = 100
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="HUD" type="Control" parent="."]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="HpLabel" type="Label" parent="HUD"]
|
||||
layout_mode = 0
|
||||
offset_left = 16.0
|
||||
offset_top = 12.0
|
||||
offset_right = 200.0
|
||||
offset_bottom = 40.0
|
||||
text = "HP 5/5"
|
||||
|
||||
[node name="ToastLabel" type="Label" parent="."]
|
||||
visible = false
|
||||
anchors_preset = 5
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
offset_left = -280.0
|
||||
offset_top = 48.0
|
||||
offset_right = 280.0
|
||||
offset_bottom = 88.0
|
||||
grow_horizontal = 2
|
||||
horizontal_alignment = 1
|
||||
text = "Achievement"
|
||||
|
||||
[node name="DialogPanel" type="PanelContainer" parent="."]
|
||||
visible = false
|
||||
anchors_preset = 7
|
||||
anchor_left = 0.5
|
||||
anchor_top = 1.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 1.0
|
||||
offset_left = -420.0
|
||||
offset_top = -140.0
|
||||
offset_right = 420.0
|
||||
offset_bottom = -24.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 0
|
||||
|
||||
[node name="Margin" type="MarginContainer" parent="DialogPanel"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 16
|
||||
theme_override_constants/margin_top = 12
|
||||
theme_override_constants/margin_right = 16
|
||||
theme_override_constants/margin_bottom = 12
|
||||
|
||||
[node name="DialogLabel" type="Label" parent="DialogPanel/Margin"]
|
||||
layout_mode = 2
|
||||
autowrap_mode = 3
|
||||
text = "..."
|
||||
|
||||
[node name="BurgerOverlay" type="ColorRect" parent="."]
|
||||
visible = false
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
color = Color(0.05, 0.02, 0.02, 0.85)
|
||||
|
||||
[node name="BurgerLabel" type="Label" parent="BurgerOverlay"]
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -320.0
|
||||
offset_top = -40.0
|
||||
offset_right = 320.0
|
||||
offset_bottom = 40.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
text = "Burger!"
|
||||
|
||||
[node name="PausePanel" type="PanelContainer" parent="."]
|
||||
process_mode = 3
|
||||
visible = false
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -280.0
|
||||
offset_top = -300.0
|
||||
offset_right = 280.0
|
||||
offset_bottom = 300.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="Margin" type="MarginContainer" parent="PausePanel"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 16
|
||||
theme_override_constants/margin_top = 12
|
||||
theme_override_constants/margin_right = 16
|
||||
theme_override_constants/margin_bottom = 12
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="PausePanel/Margin"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 6
|
||||
|
||||
[node name="TitleLabel" type="Label" parent="PausePanel/Margin/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Einstellungen"
|
||||
|
||||
[node name="ResumeButton" type="Button" parent="PausePanel/Margin/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Zurück"
|
||||
|
||||
[node name="PointsLabel" type="Label" parent="PausePanel/Margin/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Dresslerpunkte: 0"
|
||||
|
||||
[node name="ShopTitle" type="Label" parent="PausePanel/Margin/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Shop"
|
||||
|
||||
[node name="BuyPointButton" type="Button" parent="PausePanel/Margin/VBox"]
|
||||
layout_mode = 2
|
||||
text = "1€"
|
||||
|
||||
[node name="BuySunglassesButton" type="Button" parent="PausePanel/Margin/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Sunglasses"
|
||||
|
||||
[node name="BuyTicketButton" type="Button" parent="PausePanel/Margin/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Ticket"
|
||||
|
||||
[node name="BuyMilkButton" type="Button" parent="PausePanel/Margin/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Milk"
|
||||
|
||||
[node name="BuyTiramisuButton" type="Button" parent="PausePanel/Margin/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Tiramisu"
|
||||
|
||||
[node name="SfxLabel" type="Label" parent="PausePanel/Margin/VBox"]
|
||||
layout_mode = 2
|
||||
text = "SFX"
|
||||
|
||||
[node name="SfxSlider" type="HSlider" parent="PausePanel/Margin/VBox"]
|
||||
layout_mode = 2
|
||||
max_value = 1.0
|
||||
step = 0.05
|
||||
value = 1.0
|
||||
|
||||
[node name="MusicLabel" type="Label" parent="PausePanel/Margin/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Music locked"
|
||||
|
||||
[node name="MusicSlider" type="HSlider" parent="PausePanel/Margin/VBox"]
|
||||
layout_mode = 2
|
||||
editable = false
|
||||
max_value = 1.0
|
||||
value = 1.0
|
||||
|
||||
[node name="LangLabel" type="Label" parent="PausePanel/Margin/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Language"
|
||||
|
||||
[node name="LangOption" type="OptionButton" parent="PausePanel/Margin/VBox"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="InventoryLabel" type="Label" parent="PausePanel/Margin/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Inventar"
|
||||
|
||||
[node name="InventoryList" type="ItemList" parent="PausePanel/Margin/VBox"]
|
||||
custom_minimum_size = Vector2(0, 100)
|
||||
layout_mode = 2
|
||||
|
||||
[connection signal="pressed" from="PausePanel/Margin/VBox/ResumeButton" to="." method="_on_resume_pressed"]
|
||||
[connection signal="pressed" from="PausePanel/Margin/VBox/BuyPointButton" to="." method="_on_buy_point"]
|
||||
[connection signal="pressed" from="PausePanel/Margin/VBox/BuySunglassesButton" to="." method="_on_buy_sunglasses"]
|
||||
[connection signal="pressed" from="PausePanel/Margin/VBox/BuyTicketButton" to="." method="_on_buy_ticket"]
|
||||
[connection signal="pressed" from="PausePanel/Margin/VBox/BuyMilkButton" to="." method="_on_buy_milk"]
|
||||
[connection signal="pressed" from="PausePanel/Margin/VBox/BuyTiramisuButton" to="." method="_on_buy_tiramisu"]
|
||||
[connection signal="value_changed" from="PausePanel/Margin/VBox/SfxSlider" to="." method="_on_sfx_changed"]
|
||||
[connection signal="value_changed" from="PausePanel/Margin/VBox/MusicSlider" to="." method="_on_music_changed"]
|
||||
[connection signal="item_selected" from="PausePanel/Margin/VBox/LangOption" to="." method="_on_lang_selected"]
|
||||
[connection signal="item_activated" from="PausePanel/Margin/VBox/InventoryList" to="." method="_on_inventory_activated"]
|
||||
70
scenes/village.tscn
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
[gd_scene load_steps=8 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/levels/village.gd" id="1"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/player.tscn" id="2"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/exit_trigger.tscn" id="3"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/npc.tscn" id="4"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/enemy.tscn" id="5"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/hazard.tscn" id="6"]
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_ground"]
|
||||
size = Vector3(40, 0.2, 40)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="Mat_ground"]
|
||||
albedo_color = Color(0.35, 0.7, 0.35, 1)
|
||||
shading_mode = 0
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape_ground"]
|
||||
size = Vector3(40, 0.2, 40)
|
||||
|
||||
[node name="village" type="Node3D"]
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(0.866, -0.354, 0.354, 0, 0.707, 0.707, -0.5, -0.612, 0.612, 0, 8, 0)
|
||||
shadow_enabled = false
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.707, 0.707, 0, -0.707, 0.707, 0, 12, 12)
|
||||
current = true
|
||||
fov = 50.0
|
||||
|
||||
[node name="Ground" type="StaticBody3D" parent="."]
|
||||
collision_layer = 1
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="Ground"]
|
||||
mesh = SubResource("BoxMesh_ground")
|
||||
surface_material_override/0 = SubResource("Mat_ground")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Ground"]
|
||||
shape = SubResource("BoxShape_ground")
|
||||
|
||||
[node name="Player" parent="." instance=ExtResource("2")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 4)
|
||||
|
||||
|
||||
[node name="NPC_HongkongFan" parent="." instance=ExtResource("4")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 0.1, 0)
|
||||
dialog_key = "dialog_hongkong_npc"
|
||||
texture_path = "res://assets/sprites/placeholders/npc.png"
|
||||
give_item_id = "snake"
|
||||
|
||||
[node name="House" parent="." instance=ExtResource("4")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0.1, -2)
|
||||
dialog_key = "dialog_hongkong_npc"
|
||||
texture_path = "res://assets/sprites/placeholders/house.png"
|
||||
|
||||
|
||||
[node name="Dentist" parent="." instance=ExtResource("4")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5, 0.1, 2)
|
||||
dialog_key = "dialog_hongkong_npc"
|
||||
texture_path = "res://assets/sprites/placeholders/npc.png"
|
||||
give_item_id = "tooth"
|
||||
quest_flag = "teeth_stolen"
|
||||
achievement_id = "tooth_millionaire"
|
||||
|
||||
[node name="Exit" parent="." instance=ExtResource("3")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, -10)
|
||||
|
||||
57
scripts/autoload/achievements.gd
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
extends Node
|
||||
## Achievement unlock + persistence.
|
||||
|
||||
signal unlocked(achievement_id: String, title: String)
|
||||
|
||||
var _defs: Array = []
|
||||
var _unlocked: Dictionary = {} # id -> true
|
||||
|
||||
func _ready() -> void:
|
||||
_load_defs()
|
||||
|
||||
func _load_defs() -> void:
|
||||
var file := FileAccess.open("res://data/achievements.json", FileAccess.READ)
|
||||
if file == null:
|
||||
push_error("Missing achievements.json")
|
||||
return
|
||||
var parsed: Variant = JSON.parse_string(file.get_as_text())
|
||||
if typeof(parsed) == TYPE_ARRAY:
|
||||
_defs = parsed
|
||||
|
||||
func unlock(achievement_id: String) -> void:
|
||||
if _unlocked.get(achievement_id, false):
|
||||
return
|
||||
_unlocked[achievement_id] = true
|
||||
var title := achievement_id
|
||||
for entry in _defs:
|
||||
if str(entry.get("id", "")) == achievement_id:
|
||||
title = Locale.tr_key(str(entry.get("title_key", achievement_id)))
|
||||
break
|
||||
unlocked.emit(achievement_id, title)
|
||||
_check_all()
|
||||
GameState.save_game()
|
||||
|
||||
func is_unlocked(achievement_id: String) -> bool:
|
||||
return bool(_unlocked.get(achievement_id, false))
|
||||
|
||||
func get_defs() -> Array:
|
||||
return _defs
|
||||
|
||||
func _check_all() -> void:
|
||||
if _unlocked.get("all_burgers", false):
|
||||
return
|
||||
for entry in _defs:
|
||||
var id := str(entry.get("id", ""))
|
||||
if id == "all_burgers":
|
||||
continue
|
||||
if not _unlocked.get(id, false):
|
||||
return
|
||||
_unlocked["all_burgers"] = true
|
||||
var title := Locale.tr_key("ach_all_title")
|
||||
unlocked.emit("all_burgers", title)
|
||||
|
||||
func serialize() -> Dictionary:
|
||||
return {"unlocked": _unlocked.duplicate()}
|
||||
|
||||
func deserialize(data: Dictionary) -> void:
|
||||
_unlocked = data.get("unlocked", {}).duplicate()
|
||||
91
scripts/autoload/audio_director.gd
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
extends Node
|
||||
## Music / SFX / Voice + Burger-Cham every 120s on title/loading.
|
||||
|
||||
signal burger_cham_triggered
|
||||
|
||||
const BURGER_INTERVAL := 120.0
|
||||
|
||||
# TODO: Replace placeholder streams with real takes (see README asset list).
|
||||
const MUSIC_TITLE := "res://assets/audio/placeholders/music_title.wav"
|
||||
const SFX_EXPLOSION := "res://assets/audio/placeholders/sfx_explosion.wav"
|
||||
const SFX_HIT := "res://assets/audio/placeholders/sfx_hit.wav"
|
||||
const SFX_BURGER := "res://assets/audio/placeholders/sfx_burger.wav"
|
||||
const VOICE_DE := "res://assets/audio/placeholders/voice_de.wav"
|
||||
const VOICE_EN := "res://assets/audio/placeholders/voice_en.wav"
|
||||
const VOICE_BY := "res://assets/audio/placeholders/voice_by.wav"
|
||||
|
||||
var _music: AudioStreamPlayer
|
||||
var _sfx: AudioStreamPlayer
|
||||
var _voice: AudioStreamPlayer
|
||||
var _burger_timer: float = 0.0
|
||||
var burger_cham_enabled: bool = true
|
||||
|
||||
func _ready() -> void:
|
||||
process_mode = Node.PROCESS_MODE_ALWAYS
|
||||
_music = AudioStreamPlayer.new()
|
||||
_music.bus = "Music"
|
||||
_music.volume_db = 6.0 # intentionally loud
|
||||
add_child(_music)
|
||||
_sfx = AudioStreamPlayer.new()
|
||||
_sfx.bus = "SFX"
|
||||
add_child(_sfx)
|
||||
_voice = AudioStreamPlayer.new()
|
||||
_voice.bus = "Voice"
|
||||
add_child(_voice)
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if not burger_cham_enabled:
|
||||
return
|
||||
if GameState.current_scene_id != "title_screen":
|
||||
return
|
||||
_burger_timer += delta
|
||||
if _burger_timer >= BURGER_INTERVAL:
|
||||
_burger_timer = 0.0
|
||||
trigger_burger_cham()
|
||||
|
||||
func play_title_music() -> void:
|
||||
var stream := _load_stream(MUSIC_TITLE)
|
||||
if stream == null:
|
||||
return
|
||||
_music.stream = stream
|
||||
_music.volume_db = 6.0
|
||||
if not _music.playing:
|
||||
_music.play()
|
||||
|
||||
func stop_music() -> void:
|
||||
_music.stop()
|
||||
|
||||
func play_sfx(path: String) -> void:
|
||||
var stream := _load_stream(path)
|
||||
if stream == null:
|
||||
return
|
||||
_sfx.stream = stream
|
||||
_sfx.play()
|
||||
|
||||
func play_explosion() -> void:
|
||||
play_sfx(SFX_EXPLOSION)
|
||||
|
||||
func play_hit() -> void:
|
||||
play_sfx(SFX_HIT)
|
||||
|
||||
func play_language_voice(lang: String) -> void:
|
||||
var path := VOICE_DE
|
||||
match lang:
|
||||
"en":
|
||||
path = VOICE_EN
|
||||
"by":
|
||||
path = VOICE_BY
|
||||
var stream := _load_stream(path)
|
||||
if stream == null:
|
||||
return
|
||||
_voice.stream = stream
|
||||
_voice.play()
|
||||
|
||||
func trigger_burger_cham() -> void:
|
||||
play_sfx(SFX_BURGER)
|
||||
burger_cham_triggered.emit()
|
||||
|
||||
func _load_stream(path: String) -> AudioStream:
|
||||
if ResourceLoader.exists(path):
|
||||
return load(path)
|
||||
return null
|
||||
161
scripts/autoload/game_state.gd
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
extends Node
|
||||
## Global game flow, HP, death, playtime, save/load.
|
||||
## TODO: Expand save schema when real progression exists.
|
||||
|
||||
signal hp_changed(hp: int, max_hp: int)
|
||||
signal died(cause_key: String)
|
||||
signal scene_changed(scene_id: String)
|
||||
|
||||
const SAVE_PATH := "user://save.json"
|
||||
const SCENE_ORDER: Array[String] = [
|
||||
"title_screen",
|
||||
"intro_cutscene",
|
||||
"village",
|
||||
"shoe_boss",
|
||||
"meadow",
|
||||
"massage_studio",
|
||||
"farm_path",
|
||||
"farm",
|
||||
"moon",
|
||||
"final_boss",
|
||||
"end_screen",
|
||||
]
|
||||
|
||||
const SCENE_PATHS := {
|
||||
"title_screen": "res://scenes/title_screen.tscn",
|
||||
"intro_cutscene": "res://scenes/intro_cutscene.tscn",
|
||||
"village": "res://scenes/village.tscn",
|
||||
"shoe_boss": "res://scenes/shoe_boss.tscn",
|
||||
"meadow": "res://scenes/meadow.tscn",
|
||||
"massage_studio": "res://scenes/massage_studio.tscn",
|
||||
"farm_path": "res://scenes/farm_path.tscn",
|
||||
"farm": "res://scenes/farm.tscn",
|
||||
"moon": "res://scenes/moon.tscn",
|
||||
"final_boss": "res://scenes/final_boss.tscn",
|
||||
"end_screen": "res://scenes/end_screen.tscn",
|
||||
"death_screen": "res://scenes/death_screen.tscn",
|
||||
}
|
||||
|
||||
var current_scene_id: String = "title_screen"
|
||||
var max_hp: int = 5
|
||||
var hp: int = 5
|
||||
var death_count: int = 0
|
||||
var last_death_cause_key: String = "death_default"
|
||||
var playtime_seconds: float = 0.0
|
||||
var house_built: bool = false
|
||||
var flags: Dictionary = {}
|
||||
|
||||
func _ready() -> void:
|
||||
process_mode = Node.PROCESS_MODE_ALWAYS
|
||||
load_game()
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if get_tree().paused:
|
||||
return
|
||||
if current_scene_id in ["title_screen", "death_screen"]:
|
||||
return
|
||||
playtime_seconds += delta
|
||||
if playtime_seconds >= 3600.0:
|
||||
Achievements.unlock("played_hour")
|
||||
|
||||
func goto_scene(scene_id: String) -> void:
|
||||
if not SCENE_PATHS.has(scene_id):
|
||||
push_error("Unknown scene: %s" % scene_id)
|
||||
return
|
||||
current_scene_id = scene_id
|
||||
scene_changed.emit(scene_id)
|
||||
if scene_id == "moon":
|
||||
Achievements.unlock("moon_cheese")
|
||||
save_game()
|
||||
get_tree().change_scene_to_file(SCENE_PATHS[scene_id])
|
||||
|
||||
func goto_next() -> void:
|
||||
var idx := SCENE_ORDER.find(current_scene_id)
|
||||
if idx < 0:
|
||||
goto_scene("village")
|
||||
return
|
||||
if idx >= SCENE_ORDER.size() - 1:
|
||||
goto_scene("end_screen")
|
||||
return
|
||||
goto_scene(SCENE_ORDER[idx + 1])
|
||||
|
||||
func skip_to_final_boss() -> void:
|
||||
Achievements.unlock("milk_skip")
|
||||
flags["milk_skip_used"] = true
|
||||
goto_scene("final_boss")
|
||||
|
||||
func start_new_game() -> void:
|
||||
hp = max_hp
|
||||
flags.clear()
|
||||
house_built = false
|
||||
goto_scene("intro_cutscene")
|
||||
|
||||
func heal_full() -> void:
|
||||
hp = max_hp
|
||||
hp_changed.emit(hp, max_hp)
|
||||
|
||||
func take_damage(amount: int = 1, cause_key: String = "death_default") -> void:
|
||||
hp = max(0, hp - amount)
|
||||
hp_changed.emit(hp, max_hp)
|
||||
if hp <= 0:
|
||||
die(cause_key)
|
||||
|
||||
func die(cause_key: String = "death_default") -> void:
|
||||
last_death_cause_key = cause_key
|
||||
death_count += 1
|
||||
died.emit(cause_key)
|
||||
if death_count >= 100:
|
||||
Achievements.unlock("died_100")
|
||||
save_game()
|
||||
goto_scene("death_screen")
|
||||
|
||||
func set_flag(key: String, value: Variant = true) -> void:
|
||||
flags[key] = value
|
||||
save_game()
|
||||
|
||||
func get_flag(key: String, default_value: Variant = false) -> Variant:
|
||||
return flags.get(key, default_value)
|
||||
|
||||
func save_game() -> void:
|
||||
var data := {
|
||||
"hp": hp,
|
||||
"max_hp": max_hp,
|
||||
"death_count": death_count,
|
||||
"last_death_cause_key": last_death_cause_key,
|
||||
"playtime_seconds": playtime_seconds,
|
||||
"current_scene_id": current_scene_id,
|
||||
"house_built": house_built,
|
||||
"flags": flags,
|
||||
"inventory": Inventory.serialize(),
|
||||
"achievements": Achievements.serialize(),
|
||||
"shop": Shop.serialize(),
|
||||
"settings": Settings.serialize(),
|
||||
}
|
||||
var file := FileAccess.open(SAVE_PATH, FileAccess.WRITE)
|
||||
if file == null:
|
||||
push_warning("Could not write save file")
|
||||
return
|
||||
file.store_string(JSON.stringify(data, "\t"))
|
||||
|
||||
func load_game() -> void:
|
||||
if not FileAccess.file_exists(SAVE_PATH):
|
||||
return
|
||||
var file := FileAccess.open(SAVE_PATH, FileAccess.READ)
|
||||
if file == null:
|
||||
return
|
||||
var parsed: Variant = JSON.parse_string(file.get_as_text())
|
||||
if typeof(parsed) != TYPE_DICTIONARY:
|
||||
return
|
||||
var data: Dictionary = parsed
|
||||
hp = int(data.get("hp", max_hp))
|
||||
max_hp = int(data.get("max_hp", max_hp))
|
||||
death_count = int(data.get("death_count", 0))
|
||||
last_death_cause_key = str(data.get("last_death_cause_key", "death_default"))
|
||||
playtime_seconds = float(data.get("playtime_seconds", 0.0))
|
||||
current_scene_id = str(data.get("current_scene_id", "title_screen"))
|
||||
house_built = bool(data.get("house_built", false))
|
||||
flags = data.get("flags", {})
|
||||
Inventory.deserialize(data.get("inventory", {}))
|
||||
Achievements.deserialize(data.get("achievements", {}))
|
||||
Shop.deserialize(data.get("shop", {}))
|
||||
Settings.deserialize(data.get("settings", {}))
|
||||
84
scripts/autoload/inventory.gd
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
extends Node
|
||||
## Array-based inventory with item IDs from data/items.json.
|
||||
|
||||
signal inventory_changed
|
||||
signal item_used(item_id: String)
|
||||
|
||||
var _items: Dictionary = {} # id -> count
|
||||
var _defs: Dictionary = {}
|
||||
|
||||
func _ready() -> void:
|
||||
_load_defs()
|
||||
|
||||
func _load_defs() -> void:
|
||||
var file := FileAccess.open("res://data/items.json", FileAccess.READ)
|
||||
if file == null:
|
||||
push_error("Missing items.json")
|
||||
return
|
||||
var parsed: Variant = JSON.parse_string(file.get_as_text())
|
||||
if typeof(parsed) != TYPE_ARRAY:
|
||||
return
|
||||
for entry in parsed:
|
||||
if typeof(entry) == TYPE_DICTIONARY and entry.has("id"):
|
||||
_defs[str(entry["id"])] = entry
|
||||
|
||||
func add_item(item_id: String, amount: int = 1) -> void:
|
||||
if amount <= 0:
|
||||
return
|
||||
_items[item_id] = int(_items.get(item_id, 0)) + amount
|
||||
inventory_changed.emit()
|
||||
GameState.save_game()
|
||||
|
||||
func remove_item(item_id: String, amount: int = 1) -> bool:
|
||||
var have := int(_items.get(item_id, 0))
|
||||
if have < amount:
|
||||
return false
|
||||
have -= amount
|
||||
if have <= 0:
|
||||
_items.erase(item_id)
|
||||
else:
|
||||
_items[item_id] = have
|
||||
inventory_changed.emit()
|
||||
GameState.save_game()
|
||||
return true
|
||||
|
||||
func has_item(item_id: String, amount: int = 1) -> bool:
|
||||
return int(_items.get(item_id, 0)) >= amount
|
||||
|
||||
func get_count(item_id: String) -> int:
|
||||
return int(_items.get(item_id, 0))
|
||||
|
||||
func get_all() -> Dictionary:
|
||||
return _items.duplicate()
|
||||
|
||||
func use_item(item_id: String) -> bool:
|
||||
if not has_item(item_id):
|
||||
return false
|
||||
match item_id:
|
||||
"milk":
|
||||
remove_item("milk", 1)
|
||||
item_used.emit(item_id)
|
||||
GameState.skip_to_final_boss()
|
||||
return true
|
||||
"death_ticket":
|
||||
remove_item("death_ticket", 1)
|
||||
Achievements.unlock("eaten_to_death")
|
||||
item_used.emit(item_id)
|
||||
return true
|
||||
"tiramisu":
|
||||
remove_item("tiramisu", 1)
|
||||
var eaten := int(GameState.get_flag("tiramisu_kg", 0)) + 1
|
||||
GameState.set_flag("tiramisu_kg", eaten)
|
||||
if eaten >= 1000:
|
||||
Achievements.unlock("tiramisu_tonne")
|
||||
item_used.emit(item_id)
|
||||
return true
|
||||
_:
|
||||
return false
|
||||
|
||||
func serialize() -> Dictionary:
|
||||
return {"items": _items.duplicate()}
|
||||
|
||||
func deserialize(data: Dictionary) -> void:
|
||||
_items = data.get("items", {}).duplicate()
|
||||
inventory_changed.emit()
|
||||
35
scripts/autoload/locale.gd
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
extends Node
|
||||
## Multilingual strings DE/EN/BY with DE fallback.
|
||||
|
||||
signal locale_changed
|
||||
|
||||
var _strings: Dictionary = {}
|
||||
|
||||
func _ready() -> void:
|
||||
reload()
|
||||
|
||||
func reload() -> void:
|
||||
_strings = _load_lang("de")
|
||||
var lang := Settings.language if Settings else "de"
|
||||
if lang != "de":
|
||||
var overlay := _load_lang(lang)
|
||||
for key in overlay.keys():
|
||||
_strings[key] = overlay[key]
|
||||
locale_changed.emit()
|
||||
|
||||
func _load_lang(lang: String) -> Dictionary:
|
||||
var path := "res://data/locales/%s.json" % lang
|
||||
var file := FileAccess.open(path, FileAccess.READ)
|
||||
if file == null:
|
||||
push_warning("Missing locale: %s" % path)
|
||||
return {}
|
||||
var parsed: Variant = JSON.parse_string(file.get_as_text())
|
||||
if typeof(parsed) == TYPE_DICTIONARY:
|
||||
return parsed
|
||||
return {}
|
||||
|
||||
func tr_key(key: String, args: Array = []) -> String:
|
||||
var text := str(_strings.get(key, key))
|
||||
if args.is_empty():
|
||||
return text
|
||||
return text % args
|
||||
79
scripts/autoload/settings.gd
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
extends Node
|
||||
## Persistent settings. Music cannot be turned down (satire).
|
||||
|
||||
signal settings_changed
|
||||
|
||||
const MUSIC_BUS := "Music"
|
||||
const SFX_BUS := "SFX"
|
||||
const VOICE_BUS := "Voice"
|
||||
|
||||
var language: String = "de"
|
||||
var sfx_volume: float = 1.0
|
||||
## Intentionally locked loud — slider is UI-disabled.
|
||||
var music_volume: float = 1.0
|
||||
|
||||
func _ready() -> void:
|
||||
_ensure_buses()
|
||||
apply_audio()
|
||||
# Locale reloads after both Settings + Locale exist (Locale._ready / deserialize).
|
||||
|
||||
func _ensure_buses() -> void:
|
||||
_ensure_bus(MUSIC_BUS)
|
||||
_ensure_bus(SFX_BUS)
|
||||
_ensure_bus(VOICE_BUS)
|
||||
|
||||
func _ensure_bus(bus_name: String) -> void:
|
||||
if AudioServer.get_bus_index(bus_name) != -1:
|
||||
return
|
||||
AudioServer.add_bus()
|
||||
var idx := AudioServer.bus_count - 1
|
||||
AudioServer.set_bus_name(idx, bus_name)
|
||||
AudioServer.set_bus_send(idx, "Master")
|
||||
|
||||
func set_language(lang: String) -> void:
|
||||
if lang not in ["de", "en", "by"]:
|
||||
return
|
||||
language = lang
|
||||
Locale.reload()
|
||||
AudioDirector.play_language_voice(lang)
|
||||
settings_changed.emit()
|
||||
GameState.save_game()
|
||||
|
||||
func set_sfx_volume(value: float) -> void:
|
||||
sfx_volume = clampf(value, 0.0, 1.0)
|
||||
apply_audio()
|
||||
settings_changed.emit()
|
||||
GameState.save_game()
|
||||
|
||||
func set_music_volume(_value: float) -> void:
|
||||
## Satire lock: music stays maxed.
|
||||
music_volume = 1.0
|
||||
apply_audio()
|
||||
settings_changed.emit()
|
||||
|
||||
func apply_audio() -> void:
|
||||
_set_bus_linear(MUSIC_BUS, music_volume)
|
||||
_set_bus_linear(SFX_BUS, sfx_volume)
|
||||
_set_bus_linear(VOICE_BUS, sfx_volume)
|
||||
|
||||
func _set_bus_linear(bus_name: String, linear: float) -> void:
|
||||
var idx := AudioServer.get_bus_index(bus_name)
|
||||
if idx == -1:
|
||||
return
|
||||
var db := -80.0 if linear <= 0.0001 else 20.0 * log(linear) / log(10.0)
|
||||
AudioServer.set_bus_volume_db(idx, db)
|
||||
|
||||
func serialize() -> Dictionary:
|
||||
return {
|
||||
"language": language,
|
||||
"sfx_volume": sfx_volume,
|
||||
"music_volume": 1.0,
|
||||
}
|
||||
|
||||
func deserialize(data: Dictionary) -> void:
|
||||
language = str(data.get("language", "de"))
|
||||
sfx_volume = float(data.get("sfx_volume", 1.0))
|
||||
music_volume = 1.0
|
||||
Locale.reload()
|
||||
apply_audio()
|
||||
settings_changed.emit()
|
||||
50
scripts/autoload/shop.gd
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
extends Node
|
||||
## Mock Pay-to-Win shop. 1€ = 1 Dresslerpunkt (no real payments).
|
||||
|
||||
signal points_changed(points: int)
|
||||
signal purchase_made(item_id: String)
|
||||
|
||||
var dressler_points: int = 0
|
||||
|
||||
const CATALOG := [
|
||||
{"id": "buy_point", "cost": 0, "mock_euro": true},
|
||||
{"id": "sunglasses", "cost": 5, "gives": "sunglasses"},
|
||||
{"id": "death_ticket", "cost": 3, "gives": "death_ticket"},
|
||||
{"id": "milk", "cost": 10, "gives": "milk"},
|
||||
{"id": "tiramisu", "cost": 1, "gives": "tiramisu"},
|
||||
]
|
||||
|
||||
func buy_mock_euro_point() -> void:
|
||||
## Satire: pretend the user paid 1€.
|
||||
dressler_points += 1
|
||||
points_changed.emit(dressler_points)
|
||||
GameState.save_game()
|
||||
|
||||
func purchase(entry_id: String) -> bool:
|
||||
if entry_id == "buy_point":
|
||||
buy_mock_euro_point()
|
||||
return true
|
||||
for entry in CATALOG:
|
||||
if str(entry["id"]) != entry_id:
|
||||
continue
|
||||
var cost := int(entry.get("cost", 0))
|
||||
if dressler_points < cost:
|
||||
return false
|
||||
dressler_points -= cost
|
||||
var gives := str(entry.get("gives", ""))
|
||||
if gives != "":
|
||||
Inventory.add_item(gives, 1)
|
||||
if gives == "sunglasses":
|
||||
Achievements.unlock("cool_sunglasses")
|
||||
points_changed.emit(dressler_points)
|
||||
purchase_made.emit(entry_id)
|
||||
GameState.save_game()
|
||||
return true
|
||||
return false
|
||||
|
||||
func serialize() -> Dictionary:
|
||||
return {"dressler_points": dressler_points}
|
||||
|
||||
func deserialize(data: Dictionary) -> void:
|
||||
dressler_points = int(data.get("dressler_points", 0))
|
||||
points_changed.emit(dressler_points)
|
||||
37
scripts/billboard/billboard_sprite.gd
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
extends Node3D
|
||||
class_name BillboardSprite
|
||||
## 2D sprite on a 3D plane that always faces the camera (Mario-tree style).
|
||||
## TODO: Swap placeholder textures for real pixel art.
|
||||
|
||||
@export var texture: Texture2D
|
||||
@export var pixel_size: float = 0.05
|
||||
@export var modulate_color: Color = Color.WHITE
|
||||
|
||||
@onready var _mesh_instance: MeshInstance3D = $MeshInstance3D
|
||||
|
||||
func _ready() -> void:
|
||||
_apply()
|
||||
|
||||
func set_texture(tex: Texture2D) -> void:
|
||||
texture = tex
|
||||
_apply()
|
||||
|
||||
func _apply() -> void:
|
||||
if _mesh_instance == null:
|
||||
return
|
||||
var plane := PlaneMesh.new()
|
||||
plane.size = Vector2(1.0, 1.0)
|
||||
_mesh_instance.mesh = plane
|
||||
var mat := StandardMaterial3D.new()
|
||||
mat.billboard_mode = BaseMaterial3D.BILLBOARD_ENABLED
|
||||
mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
|
||||
mat.texture_filter = BaseMaterial3D.TEXTURE_FILTER_NEAREST
|
||||
mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA_SCISSOR
|
||||
mat.alpha_scissor_threshold = 0.1
|
||||
mat.albedo_color = modulate_color
|
||||
if texture != null:
|
||||
mat.albedo_texture = texture
|
||||
var w := float(texture.get_width()) * pixel_size
|
||||
var h := float(texture.get_height()) * pixel_size
|
||||
plane.size = Vector2(w, h)
|
||||
_mesh_instance.material_override = mat
|
||||
25
scripts/combat/exit_trigger.gd
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
extends Area3D
|
||||
class_name ExitTrigger
|
||||
## Walk into this volume to advance or jump to a scene.
|
||||
|
||||
@export var next_scene_id: String = ""
|
||||
@export var use_goto_next: bool = true
|
||||
@export var require_flag: String = ""
|
||||
|
||||
func _ready() -> void:
|
||||
body_entered.connect(_on_body_entered)
|
||||
collision_layer = 0
|
||||
collision_mask = 2 # player layer
|
||||
|
||||
func _on_body_entered(body: Node3D) -> void:
|
||||
if not body.is_in_group("player"):
|
||||
return
|
||||
if require_flag != "" and not GameState.get_flag(require_flag, false):
|
||||
var ui := get_node_or_null("/root/UIRoot")
|
||||
if ui and ui.has_method("show_dialog"):
|
||||
ui.show_dialog(Locale.tr_key("exit_hint") + " (?)")
|
||||
return
|
||||
if use_goto_next and next_scene_id == "":
|
||||
GameState.goto_next()
|
||||
elif next_scene_id != "":
|
||||
GameState.goto_scene(next_scene_id)
|
||||
24
scripts/combat/hazard_zone.gd
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
extends Area3D
|
||||
class_name HazardZone
|
||||
## Damages the player on enter.
|
||||
|
||||
@export var damage: int = 1
|
||||
@export var death_cause_key: String = "death_default"
|
||||
@export var cooldown: float = 1.0
|
||||
|
||||
var _ready_to_hurt: bool = true
|
||||
|
||||
func _ready() -> void:
|
||||
body_entered.connect(_on_body_entered)
|
||||
collision_layer = 0
|
||||
collision_mask = 2
|
||||
|
||||
func _on_body_entered(body: Node3D) -> void:
|
||||
if not _ready_to_hurt:
|
||||
return
|
||||
if not body.is_in_group("player"):
|
||||
return
|
||||
_ready_to_hurt = false
|
||||
GameState.take_damage(damage, death_cause_key)
|
||||
await get_tree().create_timer(cooldown).timeout
|
||||
_ready_to_hurt = true
|
||||
43
scripts/combat/hittable.gd
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
extends Node3D
|
||||
class_name HittableEntity
|
||||
## Generic enemy / boss stub with hit points.
|
||||
|
||||
signal defeated
|
||||
signal hit(remaining_hp: int)
|
||||
|
||||
@export var max_hp: int = 4
|
||||
@export var texture_path: String = "res://assets/sprites/placeholders/enemy.png"
|
||||
@export var defeat_flag: String = ""
|
||||
@export var achievement_on_defeat: String = ""
|
||||
|
||||
var hp: int = 4
|
||||
var _alive: bool = true
|
||||
|
||||
@onready var _billboard: BillboardSprite = $BillboardSprite
|
||||
|
||||
func _ready() -> void:
|
||||
hp = max_hp
|
||||
add_to_group("enemy")
|
||||
add_to_group("interactable")
|
||||
if _billboard:
|
||||
var tex: Texture2D = load(texture_path)
|
||||
if tex:
|
||||
_billboard.set_texture(tex)
|
||||
|
||||
func take_hit(amount: int = 1) -> void:
|
||||
if not _alive:
|
||||
return
|
||||
hp = max(0, hp - amount)
|
||||
hit.emit(hp)
|
||||
AudioDirector.play_hit()
|
||||
if hp <= 0:
|
||||
_alive = false
|
||||
if defeat_flag != "":
|
||||
GameState.set_flag(defeat_flag, true)
|
||||
if achievement_on_defeat != "":
|
||||
Achievements.unlock(achievement_on_defeat)
|
||||
defeated.emit()
|
||||
queue_free()
|
||||
|
||||
func on_interact(_player: Node) -> void:
|
||||
take_hit(1)
|
||||
43
scripts/combat/interactable_npc.gd
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
extends Node3D
|
||||
class_name InteractableNPC
|
||||
## Billboard NPC with dialog key and optional quest hook.
|
||||
|
||||
signal interacted(npc: InteractableNPC)
|
||||
|
||||
@export var dialog_key: String = "dialog_hongkong_npc"
|
||||
@export var texture_path: String = "res://assets/sprites/placeholders/npc.png"
|
||||
@export var give_item_id: String = ""
|
||||
@export var require_item_id: String = ""
|
||||
@export var consume_required: bool = false
|
||||
@export var quest_flag: String = ""
|
||||
@export var achievement_id: String = ""
|
||||
@export var on_success_goto: String = ""
|
||||
|
||||
@onready var _billboard: BillboardSprite = $BillboardSprite
|
||||
|
||||
func _ready() -> void:
|
||||
add_to_group("interactable")
|
||||
if _billboard:
|
||||
var tex: Texture2D = load(texture_path)
|
||||
if tex:
|
||||
_billboard.set_texture(tex)
|
||||
|
||||
func on_interact(_player: Node) -> void:
|
||||
interacted.emit(self)
|
||||
var ui := get_node_or_null("/root/UIRoot")
|
||||
if ui and ui.has_method("show_dialog"):
|
||||
ui.show_dialog(Locale.tr_key(dialog_key))
|
||||
if require_item_id != "" and not Inventory.has_item(require_item_id):
|
||||
return
|
||||
if require_item_id != "" and consume_required:
|
||||
Inventory.remove_item(require_item_id, 1)
|
||||
if give_item_id != "":
|
||||
Inventory.add_item(give_item_id, 1)
|
||||
if quest_flag != "":
|
||||
GameState.set_flag(quest_flag, true)
|
||||
if quest_flag == "house_built":
|
||||
GameState.house_built = true
|
||||
if achievement_id != "":
|
||||
Achievements.unlock(achievement_id)
|
||||
if on_success_goto != "":
|
||||
GameState.goto_scene(on_success_goto)
|
||||
36
scripts/levels/death_screen.gd
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
extends Control
|
||||
## Blinky death screen with cause text + skull every 10s.
|
||||
## TODO: Final flashy death art.
|
||||
|
||||
@onready var title: Label = $Title
|
||||
@onready var cause: Label = $Cause
|
||||
@onready var cont: Button = $ContinueButton
|
||||
@onready var skull: ColorRect = $Skull
|
||||
|
||||
var _blink: float = 0.0
|
||||
var _skull_timer: float = 0.0
|
||||
|
||||
func _ready() -> void:
|
||||
GameState.current_scene_id = "death_screen"
|
||||
_refresh()
|
||||
Locale.locale_changed.connect(_refresh)
|
||||
skull.visible = false
|
||||
|
||||
func _refresh() -> void:
|
||||
title.text = Locale.tr_key("death_title")
|
||||
cause.text = Locale.tr_key(GameState.last_death_cause_key)
|
||||
cont.text = Locale.tr_key("death_continue")
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
_blink += delta
|
||||
modulate = Color(1, 0.4 + 0.6 * abs(sin(_blink * 6.0)), 0.4 + 0.6 * abs(sin(_blink * 4.0)))
|
||||
_skull_timer += delta
|
||||
if _skull_timer >= 10.0:
|
||||
_skull_timer = 0.0
|
||||
skull.visible = true
|
||||
await get_tree().create_timer(1.0).timeout
|
||||
skull.visible = false
|
||||
|
||||
func _on_continue_pressed() -> void:
|
||||
GameState.heal_full()
|
||||
GameState.goto_scene("title_screen")
|
||||