Repository: GDquest/make-pro-2d-games-with-godot Branch: master Commit: 7290681309ff Files: 304 Total size: 399.0 KB Directory structure: gitextract_59bn93hr/ ├── .github/ │ └── CONTRIBUTING.md ├── .gitignore ├── Demo.tscn ├── LICENSE ├── README.md ├── actors/ │ ├── Actor.gd │ ├── Actor.tscn │ ├── CoinsAttractor.tscn │ ├── CoinsCollector.gd │ ├── CoinsCollector.tscn │ ├── CoinsFountain.gd │ ├── CoinsFountain.tscn │ ├── DamageSource.gd │ ├── DamageSource.tscn │ ├── body.png.import │ ├── camera/ │ │ ├── ShakingCamera.gd │ │ └── ShakingCamera.tscn │ ├── characters/ │ │ └── seller/ │ │ ├── Seller.gd │ │ └── Seller.tscn │ ├── health/ │ │ ├── Stats.gd │ │ ├── Stats.tscn │ │ └── Status.gd │ ├── hit_box/ │ │ ├── HitBox.gd │ │ ├── HitBox.tscn │ │ └── hitbox_default.tres │ ├── player/ │ │ ├── Player.tscn │ │ ├── PlayerController.gd │ │ ├── PlayerStateMachine.gd │ │ ├── body.png.import │ │ ├── shadow.png.import │ │ └── states/ │ │ ├── Die.gd │ │ ├── Fall.gd │ │ ├── combat/ │ │ │ ├── Attack.gd │ │ │ └── Stagger.gd │ │ ├── debug/ │ │ │ └── StateNameDisplayer.gd │ │ └── motion/ │ │ ├── Motion.gd │ │ ├── in_air/ │ │ │ └── Jump.gd │ │ └── on_ground/ │ │ ├── BumpPlayer.gd │ │ ├── Idle.gd │ │ ├── Move.gd │ │ └── OnGround.gd │ ├── shadow.png.import │ └── weapons/ │ ├── bullet/ │ │ ├── Bullet.tscn │ │ ├── BulletSpawner.gd │ │ └── bullet.gd │ └── sword/ │ ├── Sword.gd │ ├── Sword.tscn │ ├── WeaponPivot.gd │ └── sword.png.import ├── audio/ │ ├── AudioShuffleStepSounds.gd │ ├── AudioStreamPlayer.tscn │ ├── MusicPlayer.gd │ ├── MusicPlayer.tscn │ ├── music/ │ │ ├── birdy_pong.ogg │ │ └── birdy_pong.ogg.import │ └── sfx/ │ ├── menu_confirm.wav.import │ ├── menu_navigate_01.wav.import │ ├── menu_navigate_02.wav.import │ ├── menu_popup_open.wav.import │ ├── step_01.wav.import │ └── step_02.wav.import ├── core/ │ ├── Game.gd │ ├── LevelLoader.gd │ ├── inventory/ │ │ ├── Inventory.gd │ │ ├── Inventory.tscn │ │ ├── ItemDatabase.gd │ │ ├── ItemDatabase.tscn │ │ └── items/ │ │ ├── Coins.gd │ │ ├── Coins.tscn │ │ ├── Item.gd │ │ ├── Item.tscn │ │ ├── coins/ │ │ │ ├── coin_single.png.import │ │ │ ├── coins_stack.png.import │ │ │ └── coins_three.png.import │ │ ├── equipment/ │ │ │ ├── Equipment.gd │ │ │ ├── Equipment.tscn │ │ │ └── sword/ │ │ │ └── Sword.tscn │ │ └── usable/ │ │ ├── potions/ │ │ │ ├── BaseHealthPotion.tscn │ │ │ ├── HealthPotion.gd │ │ │ └── restore_health/ │ │ │ ├── MinorHealthPotion.tscn │ │ │ └── StrongHealthPotion.tscn │ │ └── scroll_fireball/ │ │ ├── FireballScroll.gd │ │ ├── FireballScroll.tscn │ │ └── fireball/ │ │ ├── Fireball.gd │ │ ├── Fireball.tscn │ │ └── particles/ │ │ ├── FireballParticles.tscn │ │ ├── ParticlesToggle.gd │ │ ├── assets/ │ │ │ └── gradient_ramps/ │ │ │ ├── fire_to_black.tres │ │ │ ├── sparkles.tres │ │ │ └── sparkles_small.tres │ │ ├── explosions/ │ │ │ ├── Explosion.gd │ │ │ └── Explosion.tscn │ │ ├── fireball/ │ │ │ ├── fireball.material │ │ │ └── fireball_big.material │ │ └── sprites/ │ │ ├── circle.png.import │ │ └── smoke_clouds.png.import │ ├── save/ │ │ ├── SaveAndLoad.gd │ │ └── SaveAndLoad.tscn │ ├── shop/ │ │ ├── Shop.gd │ │ ├── Shop.tscn │ │ └── purse/ │ │ ├── Purse.gd │ │ └── Purse.tscn │ └── world/ │ ├── Door.gd │ ├── Door.tscn │ ├── Gap.gd │ ├── Gap.tscn │ ├── PlayerSpawningPoint.tscn │ ├── Rock.tscn │ ├── pit.png.import │ ├── rock.png.import │ ├── stairs.png.import │ └── tilesets/ │ ├── cave/ │ │ ├── cave.png.import │ │ ├── cave.tres │ │ └── cave_tileset_src.tscn │ └── outdoor/ │ ├── outdoor.png.import │ ├── outdoor.tres │ ├── outdoor.tscn │ └── pit.png.import ├── default_bus_layout.tres ├── default_env.tres ├── icon.png.import ├── interface/ │ ├── Interface.gd │ ├── TopLevelUi.gd │ ├── default.theme │ ├── fonts/ │ │ ├── montserrat_black_48.tres │ │ ├── source_code_pro_explanations.tres │ │ └── source_code_pro_explanations_bold.tres │ ├── gui/ │ │ ├── boss/ │ │ │ ├── BossLifebar.gd │ │ │ ├── BossLifebar.tscn │ │ │ ├── boss_bar_bg.png.import │ │ │ └── boss_bar_fill.png.import │ │ ├── lifebar/ │ │ │ ├── HookableLifeBar.tscn │ │ │ ├── InterfaceAnchor.tscn │ │ │ ├── Lifebar.gd │ │ │ ├── LifebarsBuilder.gd │ │ │ ├── LifebarsBuilder.tscn │ │ │ ├── background.png.import │ │ │ └── fill.png.import │ │ └── player/ │ │ ├── PlayerGUI.gd │ │ ├── PlayerGUI.tscn │ │ └── life_bar/ │ │ ├── LifeBar.tscn │ │ ├── Lifebar.gd │ │ ├── TextureProgress.gd │ │ ├── bg.png.import │ │ └── fill.png.import │ ├── items/ │ │ ├── ItemButton.gd │ │ ├── ItemButton.tscn │ │ ├── ItemGrid.gd │ │ ├── ItemsList.gd │ │ └── ItemsList.tscn │ ├── menus/ │ │ ├── Menu.gd │ │ ├── Menu.tscn │ │ ├── MenuSfx.tscn │ │ ├── MenuTitle.tscn │ │ ├── inventory/ │ │ │ ├── InventoryMenu.gd │ │ │ ├── InventoryMenu.tscn │ │ │ ├── ItemButton.gd │ │ │ ├── ItemButton.tscn │ │ │ ├── ItemGrid.gd │ │ │ ├── ItemsMenu.gd │ │ │ ├── ItemsMenu.tscn │ │ │ └── user_select/ │ │ │ ├── ActorButton.tscn │ │ │ ├── UserSelectMenu.gd │ │ │ └── UserSelectMenu.tscn │ │ ├── pause/ │ │ │ ├── OptionsMenu.gd │ │ │ ├── OptionsMenu.tscn │ │ │ ├── PauseMenu.gd │ │ │ ├── PauseMenu.tscn │ │ │ ├── SoundController.gd │ │ │ └── SoundController.tscn │ │ ├── save_and_load/ │ │ │ ├── SaveMenu.gd │ │ │ └── SaveMenu.tscn │ │ ├── shared/ │ │ │ ├── Button.gd │ │ │ └── Button.tscn │ │ └── shop/ │ │ ├── ShopMenu.gd │ │ ├── ShopMenu.tscn │ │ ├── menus/ │ │ │ ├── BuySubMenu.tscn │ │ │ ├── SellSubMenu.tscn │ │ │ ├── ShopSubMenu.gd │ │ │ └── ShopSubMenu.tscn │ │ ├── panels/ │ │ │ ├── DescriptionPanel.gd │ │ │ ├── DescriptionPanel.tscn │ │ │ ├── InfoPanel.gd │ │ │ ├── InfoPanel.tscn │ │ │ └── ShopItemsList.tscn │ │ └── popups/ │ │ ├── AmountLabel.gd │ │ ├── AmountPopup.gd │ │ ├── AmountPopup.tscn │ │ └── HSlider.gd │ └── theme/ │ ├── button/ │ │ ├── disabled.stylebox │ │ ├── focused.stylebox │ │ ├── hover.stylebox │ │ ├── normal.stylebox │ │ └── pressed.stylebox │ ├── empty.stylebox │ ├── fonts/ │ │ ├── comfortaa_tips.tres │ │ ├── default_font_comfortaa.tres │ │ └── source_code_pro_26.tres │ ├── icons/ │ │ ├── add.png.import │ │ ├── cancel.png.import │ │ ├── coins.png.import │ │ ├── fire_scroll.png.import │ │ ├── potion_health.png.import │ │ ├── potion_mana.png.import │ │ ├── purse.png.import │ │ ├── remove.png.import │ │ └── sword.png.import │ ├── panel/ │ │ └── panel.stylebox │ └── slider/ │ └── slider.stylebox ├── levels/ │ ├── Cave.tscn │ ├── Grasslands.tscn │ ├── Level.gd │ └── TestLevel.tscn ├── monsters/ │ ├── BossShakingCamera.gd │ ├── BossShakingCamera.tscn │ ├── Monster.gd │ ├── Monster.tscn │ ├── ObstacleDetector.gd │ ├── bosses/ │ │ └── wild_boar/ │ │ ├── WildBoar.gd │ │ ├── WildBoar.tscn │ │ ├── WildBoarFSM.gd │ │ ├── debug/ │ │ │ ├── BossStatesDisplayer.gd │ │ │ ├── StatesStackDiplayer.tscn │ │ │ ├── StatesStackDisplayer.gd │ │ │ └── fonts/ │ │ │ └── source-code-pro-bold.otf │ │ ├── sprites/ │ │ │ ├── front.png.import │ │ │ ├── wild_boar_stomp_1.png.import │ │ │ └── wild_boar_stomp_2.png.import │ │ └── states/ │ │ ├── Die.gd │ │ ├── Follow.gd │ │ ├── ReturnToCenter.gd │ │ ├── Spawn.gd │ │ ├── charge/ │ │ │ ├── BumpWildBoar.gd │ │ │ ├── Prepare.gd │ │ │ └── Sprint.gd │ │ ├── roam/ │ │ │ ├── MoveToRandomPosition.gd │ │ │ ├── RoamSequence.gd │ │ │ └── Wait.gd │ │ └── stomp/ │ │ ├── GroundExplosion.gd │ │ ├── GroundExplosion.tscn │ │ ├── Stomp.gd │ │ └── Stomp.tscn │ ├── exclamation-mark.png.import │ ├── exclamation-mark.svg.import │ ├── mosquito/ │ │ ├── Mosquito.gd │ │ ├── Mosquito.tscn │ │ ├── Nest.gd │ │ ├── Nest.tscn │ │ ├── mosquito.png.import │ │ └── nest.png.import │ └── porcupine/ │ ├── Porcupine.gd │ ├── Porcupine.tscn │ └── porcupine.png.import ├── project.godot ├── utils/ │ ├── autoload/ │ │ └── Steering.gd │ ├── debug/ │ │ ├── ControlsPanel.tscn │ │ ├── Explanations.tscn │ │ ├── StatesStackDiplayer.tscn │ │ ├── StatesStackDisplayer.gd │ │ └── TopLevelUI.gd │ └── state/ │ ├── Sequence.gd │ ├── Sequence.tscn │ ├── State.gd │ ├── StateMachine.gd │ └── StateMachine.tscn └── vfx/ ├── Fog.gd ├── TransitionColor.gd ├── TransitionColor.tscn ├── fog.shader ├── fog_background.material ├── fog_foreground.material ├── masks/ │ └── curtain.png.import ├── particles/ │ ├── SelfDestructingParticles.gd │ ├── assets/ │ │ └── gradient_ramps/ │ │ ├── fire_to_black.tres │ │ ├── sparkles.tres │ │ └── sparkles_small.tres │ ├── dust_charge/ │ │ ├── DustCharge.tscn │ │ ├── DustChargeLarge.tscn │ │ └── puffs.png.import │ ├── dust_puffs/ │ │ ├── DustPuffs.tscn │ │ ├── DustPuffsLarge.tscn │ │ ├── DustRun.tscn │ │ ├── DustWalk.tscn │ │ ├── dust_puffs_particle.tres │ │ ├── puff_stylized.png.import │ │ └── puffs.png.import │ ├── explosions/ │ │ ├── Explosion.gd │ │ ├── Explosion.tscn │ │ ├── ExplosionFlash.tscn │ │ └── circle.png.import │ ├── fiery_cloud/ │ │ ├── FieryCloud.tscn │ │ ├── Fireball.tscn │ │ └── FireryCloud.gd │ ├── rocks/ │ │ ├── DirectionalRock.tscn │ │ ├── crumbs.png.import │ │ ├── crumbs_particle.tres │ │ ├── rocks.png.import │ │ └── rocks_particle.tres │ └── smoke/ │ ├── EnemySmokeScreen.tscn │ ├── ParticlesPlayer.gd │ ├── smoke.png.import │ └── smoke_screen_particle.tres ├── transition.material └── transition.shader ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/CONTRIBUTING.md ================================================ # Contributing Guidelines Thank you very much for helping us make the project better! 😄 We appreciate every contribution, and you taking the time to give back to the community. 🙂 At the same time, there are a few guidelines we'd ask you to follow here to help bring everyone's work together as smoothly as possible. This guide explains how to report bugs, but how to suggest new features, where you can get support with the project as a user, and how to get in touch with other creators through the community channels. ## How Do I Submit A (Good) Bug Report? We track both bugs and improvements in the issues tab on GitHub. Writing a good bug report makes it a lot easier for maintainers and contributors to fix it. A good bug report: 1. Starts with a clear title that describes the issue 1. Includes a list of steps to reproduce the bug, an information about the version of the program and the platform you're working with 1. Contains the traceback or the error reported by the program in the output tab when the bug occurs You should also mention any steps you've taken to try and solve the issue or extra information you think would be valuable to help track down and fixed a bug. *Tips: take a quick screenshot and drag and drop it in the GitHub issue's body to help illustrate the problem! For Windows users, I recommend to use [ShareX](https://getsharex.com/) for that (open source). Ubuntu comes with a built-in tool, press Shift PrtScn by default to capture a rectangular area on your screen.* ### Bad and good bug report examples Here's an example of a *bad* bug report: ```md # X doesn't work I can't make feature X work ``` This report doesn't give any information about what the bug is, what triggers it, whether it can be reproduced, if it's platform-specific, if you' re using an unsupported platform... Here's an example of a good bug report, ```md ``` ## I want to submit a new feature or improve existing code That's great to hear! Be sure to let everyone know you're working on this by opening an issue or replying to an existing issue. ## I need help to use this project! ## Where can I chat with other contributors? Issues Join us on Discord! https://discord.gg/87NNb3Z #open-source channel If you would like to discuss an issue in private, you can find me on Twitter ================================================ FILE: .gitignore ================================================ .import .projectile ================================================ FILE: Demo.tscn ================================================ [gd_scene load_steps=14 format=2] [ext_resource path="res://core/Game.gd" type="Script" id=1] [ext_resource path="res://audio/MusicPlayer.tscn" type="PackedScene" id=2] [ext_resource path="res://vfx/fog_background.material" type="Material" id=3] [ext_resource path="res://vfx/Fog.gd" type="Script" id=4] [ext_resource path="res://core/LevelLoader.gd" type="Script" id=5] [ext_resource path="res://actors/player/Player.tscn" type="PackedScene" id=6] [ext_resource path="res://vfx/fog_foreground.material" type="Material" id=7] [ext_resource path="res://vfx/TransitionColor.tscn" type="PackedScene" id=8] [ext_resource path="res://interface/Interface.gd" type="Script" id=9] [ext_resource path="res://interface/gui/player/PlayerGUI.tscn" type="PackedScene" id=10] [ext_resource path="res://interface/menus/shop/ShopMenu.tscn" type="PackedScene" id=11] [ext_resource path="res://interface/menus/pause/PauseMenu.tscn" type="PackedScene" id=12] [ext_resource path="res://interface/gui/lifebar/LifebarsBuilder.tscn" type="PackedScene" id=13] [node name="Game" type="Node"] pause_mode = 1 script = ExtResource( 1 ) [node name="MusicPlayer" parent="." instance=ExtResource( 2 )] [node name="Background" type="CanvasLayer" parent="."] editor/display_folded = true layer = -100 [node name="ColorRect" type="ColorRect" parent="Background"] anchor_right = 1.0 anchor_bottom = 1.0 color = Color( 0.0625, 0.0549316, 0.0549316, 1 ) [node name="BackgroundFog" type="ColorRect" parent="Background"] visible = false material = ExtResource( 3 ) anchor_right = 1.0 anchor_bottom = 1.0 script = ExtResource( 4 ) [node name="LevelLoader" type="Node" parent="."] pause_mode = 1 script = ExtResource( 5 ) LEVEL_START = "res://levels/Grasslands.tscn" [node name="Player" parent="LevelLoader" instance=ExtResource( 6 )] [node name="Overlays" type="CanvasLayer" parent="."] pause_mode = 2 editor/display_folded = true layer = 50 [node name="ForegroundFog" type="ColorRect" parent="Overlays"] visible = false material = ExtResource( 7 ) anchor_right = 1.0 anchor_bottom = 1.0 script = ExtResource( 4 ) [node name="TransitionColor" parent="Overlays" instance=ExtResource( 8 )] [node name="Interface" type="CanvasLayer" parent="."] pause_mode = 2 layer = 100 script = ExtResource( 9 ) [node name="PlayerGUI" parent="Interface" instance=ExtResource( 10 )] [node name="ShopMenu" parent="Interface" instance=ExtResource( 11 )] pause_mode = 2 visible = false _sections_unfolded = [ "Pause", "Theme" ] [node name="PauseMenu" parent="Interface" instance=ExtResource( 12 )] visible = false _sections_unfolded = [ "Pause", "Theme" ] [node name="LifebarsBuilder" parent="Interface" instance=ExtResource( 13 )] [connection signal="loaded" from="LevelLoader" to="Interface" method="_on_Level_loaded"] [connection signal="loaded" from="LevelLoader" to="Background/BackgroundFog" method="_on_LevelLoader_loaded"] [connection signal="loaded" from="LevelLoader" to="Overlays/ForegroundFog" method="_on_LevelLoader_loaded"] ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2018 GDquest Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================

Make Pro 2d Games with Godot
Open Source A-RPG Demo

Banner for the project, showing the player facing the game's boss, the blue wild boar


This is the full source code with all the system produced for the [Make Professional 2d Games with Godot](https://gumroad.com/l/godot-tutorial-make-professional-2d-games) course. ![The game's boss, the Wild Boar](https://i.imgur.com/Bt57gQH.png) This game demo tries to show good Godot programming practices to support a growing game project. It has multiple interlocking systems, the core gameplay loop in place, a boss encounter, an inventory and shop systems, user interface with nested menus... ![Grasslands with the two monsters available in the game, the mosquito and the porcupine](https://i.imgur.com/OPg5QEn.png) ## LICENSE ## The entire source code is available under the MIT licence and everyone is welcome to [contribute](https://github.com/GDquest/make-pro-2d-games-with-godot/issues/)! Better art, gameplay improvements, code re-factoring, and more… All the techniques I used to build this project are in our [intermediate-level Godot course on Gumroad](https://gumroad.com/gdquest). If you're interested in getting it, be aware it's not 100% step-by-step. If you have requests for tutorials from elements of that game demo, please feel free to [ask on Twitter](https://twitter.com/NathanGDquest)! I will not redo what's in the course but I'll gladly make extra videos that would benefit everyone! 😄 This is our first open game on GDQuest. We are looking to build more Free games and game creation tools in the future. Be sure to [subscribe to our YouTube channel](http://youtube.com/c/gdquest) to know when that happens ☺ ## Dependencies ## The project runs in **Godot 3.1**. ## Features ## Here's a list of the gameplay features and a few of the systems you will find in the demo ### Gameplay ### - A player that can walk, jump, and do a three hit combo with a sword - Two monsters with steering based movement - Boss with 3 phases, drops random stacks of coins upon dying - Items, and inventory, and a shop that will cover your basics for an RPG game ### Core systems ### - LevelLoader, to load maps cleanly, keep the player's data around - Save and load system - Game node to handle pause and initialize the game at the start - Shader to animate the transition between levels ### User interface ### - An inventory menu and a shop menu where you can buy and sell items between two characters - A pause menu with sound options - A system to create life bars that hook onto monsters and follow them in the game world, but that are still managed by the UI system - The animated player life bar (tutorial) - Animated boss light bar that appears when the boss spans ### Visual effects ### - Layered particle systems like explosions, bursting fire, rock sparkles, dust - Beautiful noise-based fog thanks to [Gonkee](https://github.com/Gonkee/Gonkee-Fog-Shader) ### A few misc extras - Modular hit box and damage source system to create ranged and melee weapons - Stats node to manage the player and the monsters' health - Gaps the player can fall into ### Contributing You can find our contributor's guides here: - [Contributor's guide](https://www.gdquest.com/open-source/guidelines/contributing-to-gdquest-projects/) - [GDScript best practices](https://www.gdquest.com/open-source/guidelines/godot-gdscript/) - [Kind communication guidelines](https://www.gdquest.com/open-source/guidelines/kind-communication-guidelines/) ================================================ FILE: actors/Actor.gd ================================================ extends KinematicBody2D signal direction_changed(new_direction) signal position_changed(new_position) signal died() onready var health = $Health var look_direction = Vector2(1, 0) setget set_look_direction func take_damage_from(damage_source): health.take_damage(damage_source.damage) func set_dead(value): set_process_input(not value) set_physics_process(not value) $CollisionPolygon2D.disabled = value emit_signal('died') func set_look_direction(value): look_direction = value emit_signal("direction_changed", value) func reset(target_global_position): global_position = target_global_position ================================================ FILE: actors/Actor.tscn ================================================ [gd_scene load_steps=11 format=2] [ext_resource path="res://actors/health/Stats.tscn" type="PackedScene" id=1] [ext_resource path="res://actors/body.png" type="Texture" id=2] [ext_resource path="res://interface/theme/icons/add.png" type="Texture" id=3] [sub_resource type="Animation" id=1] resource_name = "SETUP" length = 0.01 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath("Skin/Body:scale") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 1, 1 ) ] } tracks/1/type = "value" tracks/1/path = NodePath("Skin/Body:rotation_degrees") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ 0.0 ] } tracks/2/type = "value" tracks/2/path = NodePath("Skin/Body:position") tracks/2/interp = 1 tracks/2/loop_wrap = true tracks/2/imported = false tracks/2/enabled = true tracks/2/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 0, -31.5144 ) ] } tracks/3/type = "value" tracks/3/path = NodePath("Skin/Body:modulate") tracks/3/interp = 1 tracks/3/loop_wrap = true tracks/3/imported = false tracks/3/enabled = true tracks/3/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ) ] } [sub_resource type="Animation" id=2] resource_name = "heal" length = 0.6 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath("Skin/Body:modulate") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.2, 0.6 ), "transitions": PoolRealArray( 1, 1, 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ), Color( 0, 1, 0.179688, 1 ), Color( 1, 1, 1, 1 ) ] } tracks/1/type = "value" tracks/1/path = NodePath("Skin/HealParticles:emitting") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0, 0.6 ), "transitions": PoolRealArray( 1, 1 ), "update": 2, "values": [ true, false ] } [sub_resource type="Gradient" id=3] offsets = PoolRealArray( 0, 0.111475, 0.872131, 1 ) colors = PoolColorArray( 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ) [sub_resource type="GradientTexture" id=4] flags = 4 gradient = SubResource( 3 ) width = 2048 [sub_resource type="Curve" id=5] min_value = 0.0 max_value = 1.0 bake_resolution = 100 _data = [ Vector2( 0, 0.693359 ), 0.0, 0.0, 0, 0, Vector2( 1, 1 ), 0.0, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=6] flags = 4 width = 2048 curve = SubResource( 5 ) [sub_resource type="ParticlesMaterial" id=7] render_priority = 0 trail_divisor = 1 emission_shape = 0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 20.0 flatness = 0.0 gravity = Vector3( 0, 0, 0 ) initial_velocity = 60.0 initial_velocity_random = 0.0 angular_velocity = 0.0 angular_velocity_random = 0.0 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = 0.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 0.0 tangential_accel_random = 0.0 damping = 1.0 damping_random = 0.0 angle = 0.0 angle_random = 0.0 scale = 1.0 scale_random = 0.0 scale_curve = SubResource( 6 ) color_ramp = SubResource( 4 ) hue_variation = 0.0 hue_variation_random = 0.0 anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 0.0 anim_offset_random = 0.0 anim_loop = false _sections_unfolded = [ "Color", "Damping" ] [node name="Actor" type="KinematicBody2D" groups=[ "actor", ]] input_pickable = false collision_layer = 1 collision_mask = 1 collision/safe_margin = 0.08 _sections_unfolded = [ "Transform", "Visibility" ] [node name="Health" parent="." index="0" instance=ExtResource( 1 )] max_health = 100 [node name="AnimationPlayer" type="AnimationPlayer" parent="." index="1"] root_node = NodePath("..") autoplay = "SETUP" playback_process_mode = 1 playback_default_blend_time = 0.0 playback_speed = 1.0 anims/SETUP = SubResource( 1 ) anims/heal = SubResource( 2 ) blend_times = [ ] _sections_unfolded = [ "Playback Options" ] [node name="Skin" type="Position2D" parent="." index="2"] _sections_unfolded = [ "Visibility" ] [node name="Body" type="Sprite" parent="Skin" index="0"] position = Vector2( 0, -31.5144 ) texture = ExtResource( 2 ) offset = Vector2( 1.40758, -3.05176e-005 ) _sections_unfolded = [ "Transform", "Visibility" ] [node name="HealParticles" type="Particles2D" parent="Skin" index="1"] position = Vector2( 37.3383, -68.3211 ) rotation = -1.19808 emitting = false amount = 3 lifetime = 0.6 one_shot = true preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.2 randomness = 0.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -100, -100, 200, 200 ) local_coords = false draw_order = 1 process_material = SubResource( 7 ) texture = ExtResource( 3 ) normal_map = null h_frames = 1 v_frames = 1 _sections_unfolded = [ "Drawing", "Process Material", "Textures", "Time" ] [node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="." index="3"] build_mode = 0 polygon = PoolVector2Array( -30, 0, -30, -40, 34, -40, 34, 0 ) _sections_unfolded = [ "Transform" ] ================================================ FILE: actors/CoinsAttractor.tscn ================================================ [gd_scene load_steps=2 format=2] [sub_resource type="CircleShape2D" id=2] custom_solver_bias = 0.0 radius = 41.2311 [node name="CoinsAttractor" type="Area2D"] input_pickable = true gravity_vec = Vector2( 0, 1 ) gravity = 98.0 linear_damp = 0.1 angular_damp = 1.0 collision_layer = 128 collision_mask = 64 audio_bus_override = false audio_bus_name = "Master" _sections_unfolded = [ "Collision" ] [node name="CollisionShape2D" type="CollisionShape2D" parent="." index="0"] shape = SubResource( 2 ) ================================================ FILE: actors/CoinsCollector.gd ================================================ extends Area2D signal coins_received(amount) const Coins = preload("res://core/inventory/items/Coins.gd") func _on_area_entered(area): print(area) if not area is Coins: return area.queue_free() emit_signal("coins_received", area.amount) ================================================ FILE: actors/CoinsCollector.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://actors/CoinsCollector.gd" type="Script" id=1] [sub_resource type="CircleShape2D" id=1] custom_solver_bias = 0.0 radius = 44.6727 [node name="CoinsCollector" type="Area2D" index="0"] input_pickable = true gravity_vec = Vector2( 0, 1 ) gravity = 98.0 linear_damp = 0.1 angular_damp = 1.0 monitorable = false collision_layer = 128 collision_mask = 64 audio_bus_override = false audio_bus_name = "Master" script = ExtResource( 1 ) _sections_unfolded = [ "Collision" ] [node name="CollisionShape2D" type="CollisionShape2D" parent="." index="0"] shape = SubResource( 1 ) [connection signal="area_entered" from="." to="." method="_on_area_entered"] ================================================ FILE: actors/CoinsFountain.gd ================================================ extends Position2D const Coins = preload("res://core/inventory/items/Coins.tscn") onready var timer = $Timer export(int) var MAX_SPAWN_COUNT = 12 var spawn_cycles = 0 func start(): timer.start() func _on_Timer_timeout(): spawn_random_coin_stack() func spawn_random_coin_stack(): var coins = Coins.instance() add_child(coins) coins.set_random_amount() coins.throw() spawn_cycles += 1 if spawn_cycles == MAX_SPAWN_COUNT: timer.stop() ================================================ FILE: actors/CoinsFountain.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://actors/CoinsFountain.gd" type="Script" id=1] [sub_resource type="GDScript" id=1] script/source = "extends Timer export(float) var MINIMUM_WAIT_TIME = 0.05 export(float) var MAXIMUM_WAIT_TIME = 0.1 func _init(): assert(MINIMUM_WAIT_TIME <= MAXIMUM_WAIT_TIME) func randomize_wait_time(): wait_time = rand_range(MINIMUM_WAIT_TIME, MAXIMUM_WAIT_TIME)" [node name="CoinsFountain" type="Position2D"] script = ExtResource( 1 ) _sections_unfolded = [ "Transform" ] MAX_SPAWN_COUNT = 20 [node name="Timer" type="Timer" parent="." index="0"] process_mode = 1 wait_time = 0.05 one_shot = false autostart = false script = SubResource( 1 ) MINIMUM_WAIT_TIME = 0.05 MAXIMUM_WAIT_TIME = 0.1 [connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"] [connection signal="timeout" from="Timer" to="Timer" method="randomize_wait_time"] ================================================ FILE: actors/DamageSource.gd ================================================ extends Area2D export(int) var damage = 2 var effect func set_active(value): $CollisionShape2D.disabled = not value ================================================ FILE: actors/DamageSource.tscn ================================================ [gd_scene load_steps=2 format=2] [ext_resource path="res://actors/DamageSource.gd" type="Script" id=1] [node name="DamageSource" type="Area2D" index="0"] input_pickable = true gravity_vec = Vector2( 0, 1 ) gravity = 98.0 linear_damp = 0.1 angular_damp = 1.0 monitoring = false collision_layer = 32 collision_mask = 4 audio_bus_override = false audio_bus_name = "Master" script = ExtResource( 1 ) _sections_unfolded = [ "Collision" ] damage = 2 ================================================ FILE: actors/body.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/body.png-e947538dbfd8a8c2e1335860c186fed8.stex" metadata={ "vram_texture": false } [deps] source_file="res://actors/body.png" dest_files=[ "res://.import/body.png-e947538dbfd8a8c2e1335860c186fed8.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: actors/camera/ShakingCamera.gd ================================================ tool extends Camera2D export(float) var amplitude = 6.0 export(float) var duration = 0.8 setget set_duration export(float, EASE) var DAMP_EASING = 1.0 export(bool) var shake = false setget set_shake onready var timer = $Timer enum States {IDLE, SHAKING} var state = States.IDLE func _ready(): self.duration = duration set_process(false) randomize() func set_duration(value): duration = value if not timer: return timer.wait_time = duration func set_shake(value): shake = value if shake: _change_state(States.SHAKING) else: _change_state(States.IDLE) func _change_state(new_state): match new_state: States.IDLE: offset = Vector2() set_process(false) States.SHAKING: set_process(true) timer.start() state = new_state func _process(delta): var damping = ease(timer.time_left / timer.wait_time, DAMP_EASING) offset = Vector2( rand_range(amplitude, -amplitude) * damping, rand_range(amplitude, -amplitude) * damping) func _on_ShakeTimer_timeout(): self.shake = false ================================================ FILE: actors/camera/ShakingCamera.tscn ================================================ [gd_scene load_steps=2 format=2] [ext_resource path="res://actors/camera/ShakingCamera.gd" type="Script" id=1] [node name="ShakingCamera" type="Camera2D" index="0"] anchor_mode = 1 rotating = false current = true zoom = Vector2( 1, 1 ) limit_left = -10000000 limit_top = -10000000 limit_right = 10000000 limit_bottom = 10000000 limit_smoothed = false drag_margin_h_enabled = true drag_margin_v_enabled = true smoothing_enabled = false smoothing_speed = 5.0 offset_v = 0.0 offset_h = 0.0 drag_margin_left = 0.2 drag_margin_top = 0.2 drag_margin_right = 0.2 drag_margin_bottom = 0.2 editor_draw_screen = true editor_draw_limits = false editor_draw_drag_margin = false script = ExtResource( 1 ) _sections_unfolded = [ "Drag Margin", "Smoothing", "Transform" ] amplitude = 8.0 duration = 0.8 DAMP_EASING = 1.0 shake = false [node name="Timer" type="Timer" parent="." index="0"] process_mode = 1 wait_time = 0.8 one_shot = true autostart = false [connection signal="timeout" from="Timer" to="." method="_on_ShakeTimer_timeout"] ================================================ FILE: actors/characters/seller/Seller.gd ================================================ extends Area2D signal shop_open_requested(shop, user) const Player = preload("res://actors/player/PlayerController.gd") func _unhandled_input(event): if not event.is_action_pressed("ui_accept"): return for body in get_overlapping_bodies(): if body is Player: emit_signal("shop_open_requested", $Shop, body) get_tree().set_input_as_handled() ================================================ FILE: actors/characters/seller/Seller.tscn ================================================ [gd_scene load_steps=5 format=2] [ext_resource path="res://actors/characters/seller/Seller.gd" type="Script" id=1] [ext_resource path="res://core/shop/Shop.tscn" type="PackedScene" id=2] [ext_resource path="res://actors/body.png" type="Texture" id=3] [sub_resource type="CircleShape2D" id=1] custom_solver_bias = 0.0 radius = 49.2988 [node name="Seller" type="Area2D" index="0" groups=[ "seller", ]] input_pickable = true gravity_vec = Vector2( 0, 1 ) gravity = 98.0 linear_damp = 0.1 angular_damp = 1.0 audio_bus_override = false audio_bus_name = "Master" script = ExtResource( 1 ) _sections_unfolded = [ "Transform" ] [node name="Shop" parent="." index="0" instance=ExtResource( 2 )] [node name="CollisionShape2D" type="CollisionShape2D" parent="." index="1"] shape = SubResource( 1 ) [node name="Body" type="Sprite" parent="." index="2"] position = Vector2( 0, -20 ) texture = ExtResource( 3 ) _sections_unfolded = [ "Transform" ] ================================================ FILE: actors/health/Stats.gd ================================================ extends Node signal health_changed(new_health) signal damage_taken(new_health) signal health_depleted() var modifiers = {} var health = 0 export(int) var max_health = 9 setget set_max_health export(int) var strength = 2 export(int) var defense = 0 func _ready(): health = max_health func set_max_health(value): max_health = max(0, value) func take_damage(amount): health -= amount health = max(0, health) emit_signal("health_changed", health) emit_signal("damage_taken", health) if health == 0: emit_signal("health_depleted") func heal(amount): health += amount health = max(health, max_health) emit_signal("health_changed", health) func add_modifier(id, modifier): modifiers[id] = modifier func remove_modifier(id): modifiers.erase(id) ================================================ FILE: actors/health/Stats.tscn ================================================ [gd_scene load_steps=2 format=2] [ext_resource path="res://actors/health/Stats.gd" type="Script" id=1] [node name="Stats" type="Node" index="0"] script = ExtResource( 1 ) health = 0 max_health = 9 strength = 2 defense = 0 ================================================ FILE: actors/health/Status.gd ================================================ extends Node signal added(status) signal removed(status) var statuses_active = {} # Example status const POISON = { 'name': "Poison", 'effect': { 'periodic_damage': { 'cycles': 5, 'stat': 'health', 'damage': 1, } } } const INVINCIBLE = { 'name': "Invincible", 'effect': { 'stat_modifier': { 'add': { 'defense': 1000, 'magic_defense': 1000 } } } } func add(id, status): statuses_active[id] = status func remove(id): statuses_active.erase(id) func as_string(): var string = "" for status in statuses_active.values(): string += "%s.%s: %s" % [status['id'], status['name'], status['effect']] return string ================================================ FILE: actors/hit_box/HitBox.gd ================================================ extends Area2D const DamageSource = preload("res://actors/DamageSource.gd") func _on_area_entered(area): if not area is DamageSource: return owner.take_damage_from(area) func set_active(value): $CollisionShape2D.disabled = not value ================================================ FILE: actors/hit_box/HitBox.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://actors/hit_box/HitBox.gd" type="Script" id=1] [ext_resource path="res://actors/hit_box/hitbox_default.tres" type="Shape2D" id=2] [node name="HitBox" type="Area2D" index="0"] input_pickable = true gravity_vec = Vector2( 0, 1 ) gravity = 98.0 linear_damp = 0.1 angular_damp = 1.0 monitorable = false collision_layer = 4 collision_mask = 32 audio_bus_override = false audio_bus_name = "Master" script = ExtResource( 1 ) _sections_unfolded = [ "Collision", "Transform" ] [node name="CollisionShape2D" type="CollisionShape2D" parent="." index="0"] position = Vector2( 0, -8.42273 ) shape = ExtResource( 2 ) [connection signal="area_entered" from="." to="." method="_on_area_entered"] ================================================ FILE: actors/hit_box/hitbox_default.tres ================================================ [gd_resource type="CircleShape2D" format=2] [resource] custom_solver_bias = 0.0 radius = 99.636 ================================================ FILE: actors/player/Player.tscn ================================================ [gd_scene load_steps=37 format=2] [ext_resource path="res://actors/player/PlayerController.gd" type="Script" id=1] [ext_resource path="res://actors/camera/ShakingCamera.tscn" type="PackedScene" id=2] [ext_resource path="res://actors/hit_box/HitBox.tscn" type="PackedScene" id=3] [ext_resource path="res://actors/player/PlayerStateMachine.gd" type="Script" id=4] [ext_resource path="res://actors/player/states/motion/on_ground/Idle.gd" type="Script" id=5] [ext_resource path="res://actors/player/states/motion/on_ground/Move.gd" type="Script" id=6] [ext_resource path="res://actors/player/states/motion/on_ground/BumpPlayer.gd" type="Script" id=7] [ext_resource path="res://actors/player/states/Fall.gd" type="Script" id=8] [ext_resource path="res://actors/player/states/motion/in_air/Jump.gd" type="Script" id=9] [ext_resource path="res://actors/player/states/combat/Stagger.gd" type="Script" id=10] [ext_resource path="res://actors/player/states/combat/Attack.gd" type="Script" id=11] [ext_resource path="res://actors/player/states/Die.gd" type="Script" id=12] [ext_resource path="res://actors/player/shadow.png" type="Texture" id=13] [ext_resource path="res://actors/weapons/sword/WeaponPivot.gd" type="Script" id=14] [ext_resource path="res://actors/weapons/sword/Sword.tscn" type="PackedScene" id=15] [ext_resource path="res://actors/player/body.png" type="Texture" id=16] [ext_resource path="res://interface/fonts/SourceCodePro-Bold.ttf" type="DynamicFontData" id=17] [ext_resource path="res://actors/player/states/debug/StateNameDisplayer.gd" type="Script" id=18] [ext_resource path="res://actors/health/Stats.tscn" type="PackedScene" id=19] [ext_resource path="res://core/shop/purse/Purse.tscn" type="PackedScene" id=20] [ext_resource path="res://core/inventory/Inventory.tscn" type="PackedScene" id=21] [ext_resource path="res://core/inventory/items/usable/potions/restore_health/MinorHealthPotion.tscn" type="PackedScene" id=22] [ext_resource path="res://core/inventory/items/usable/potions/restore_health/StrongHealthPotion.tscn" type="PackedScene" id=23] [ext_resource path="res://actors/weapons/bullet/BulletSpawner.gd" type="Script" id=24] [ext_resource path="res://audio/sfx/step_01.wav" type="AudioStream" id=25] [ext_resource path="res://audio/AudioShuffleStepSounds.gd" type="Script" id=26] [ext_resource path="res://actors/CoinsCollector.tscn" type="PackedScene" id=27] [sub_resource type="CircleShape2D" id=1] custom_solver_bias = 0.0 radius = 31.3139 [sub_resource type="Animation" id=2] resource_name = "SETUP" length = 0.01 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath("BodyPivot/Body:position") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 0, -58.8242 ) ] } tracks/1/type = "value" tracks/1/path = NodePath("BodyPivot/Body:rotation_degrees") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ 0.0 ] } tracks/2/type = "value" tracks/2/path = NodePath("BodyPivot/Body:scale") tracks/2/interp = 1 tracks/2/loop_wrap = true tracks/2/imported = false tracks/2/enabled = true tracks/2/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 1, 1 ) ] } tracks/3/type = "value" tracks/3/path = NodePath("Shadow:modulate") tracks/3/interp = 1 tracks/3/loop_wrap = true tracks/3/imported = false tracks/3/enabled = true tracks/3/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ) ] } tracks/4/type = "value" tracks/4/path = NodePath("Shadow:scale") tracks/4/interp = 1 tracks/4/loop_wrap = true tracks/4/imported = false tracks/4/enabled = true tracks/4/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 1, 1 ) ] } tracks/5/type = "value" tracks/5/path = NodePath("BodyPivot:scale") tracks/5/interp = 1 tracks/5/loop_wrap = true tracks/5/imported = false tracks/5/enabled = true tracks/5/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 1, 1 ) ] } tracks/6/type = "value" tracks/6/path = NodePath("BodyPivot:modulate") tracks/6/interp = 1 tracks/6/loop_wrap = true tracks/6/imported = false tracks/6/enabled = true tracks/6/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ) ] } [sub_resource type="Animation" id=3] resource_name = "bump" length = 0.2 loop = false step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath("BodyPivot/Body:position") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.1, 0.2 ), "transitions": PoolRealArray( 0.466516, 1, 0.466516 ), "update": 0, "values": [ Vector2( 0, -58.8242 ), Vector2( 0, -100 ), Vector2( 0, -58.8242 ) ] } [sub_resource type="Animation" id=4] resource_name = "die" length = 0.6 loop = false step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath("BodyPivot/Body:modulate") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.4 ), "transitions": PoolRealArray( 1, 1, 1, 1, 1, 1, 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ), Color( 1, 0, 0, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 0, 0, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 0, 0, 1 ), Color( 1, 1, 1, 1 ) ] } tracks/1/type = "value" tracks/1/path = NodePath("BodyPivot:scale") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0, 0.25, 0.5 ), "transitions": PoolRealArray( 0.326562, 0.326562, 1 ), "update": 0, "values": [ Vector2( 1, 1 ), Vector2( 1, 1 ), Vector2( 0, 0 ) ] } tracks/2/type = "value" tracks/2/path = NodePath("Shadow:scale") tracks/2/interp = 1 tracks/2/loop_wrap = true tracks/2/imported = false tracks/2/enabled = true tracks/2/keys = { "times": PoolRealArray( 0, 0.25, 0.5 ), "transitions": PoolRealArray( 0.27991, 0.27991, 1 ), "update": 0, "values": [ Vector2( 1, 1 ), Vector2( 1, 1 ), Vector2( 0.275362, 0.275362 ) ] } tracks/3/type = "value" tracks/3/path = NodePath("Shadow:modulate") tracks/3/interp = 1 tracks/3/loop_wrap = true tracks/3/imported = false tracks/3/enabled = true tracks/3/keys = { "times": PoolRealArray( 0, 0.25, 0.5 ), "transitions": PoolRealArray( 1, 1, 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ] } [sub_resource type="Animation" id=5] length = 1.1 loop = false step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath("BodyPivot/Body:position") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.3, 1.1 ), "transitions": PoolRealArray( 1, 0, 1 ), "update": 0, "values": [ Vector2( 0, -58.8242 ), Vector2( 0, 20 ), Vector2( 0, -58.8242 ) ] } tracks/1/type = "value" tracks/1/path = NodePath("BodyPivot/Body:scale") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0, 0.3, 1.1 ), "transitions": PoolRealArray( 1, 0, 1 ), "update": 0, "values": [ Vector2( 1, 1 ), Vector2( 0.0163307, 0.0163307 ), Vector2( 1, 1 ) ] } tracks/2/type = "value" tracks/2/path = NodePath("Shadow:modulate") tracks/2/interp = 1 tracks/2/loop_wrap = true tracks/2/imported = false tracks/2/enabled = true tracks/2/keys = { "times": PoolRealArray( 0, 0.15, 1.1 ), "transitions": PoolRealArray( 1, 0, 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ), Color( 1, 1, 1, 1 ) ] } tracks/3/type = "value" tracks/3/path = NodePath("BodyPivot/Body:modulate") tracks/3/interp = 1 tracks/3/loop_wrap = true tracks/3/imported = false tracks/3/enabled = true tracks/3/keys = { "times": PoolRealArray( 0, 0.3, 1.1 ), "transitions": PoolRealArray( 1, 0, 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ), Color( 0.175781, 0.175781, 0.175781, 1 ), Color( 1, 1, 1, 1 ) ] } [sub_resource type="Animation" id=6] length = 0.01 loop = true step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath("BodyPivot/Body:position") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 0.466516 ), "update": 0, "values": [ Vector2( 0, -58.8242 ) ] } [sub_resource type="Animation" id=7] length = 0.6 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath("BodyPivot/Body:modulate") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.4 ), "transitions": PoolRealArray( 1, 1, 1, 1, 1, 1, 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ), Color( 1, 0, 0, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 0, 0, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 0, 0, 1 ), Color( 1, 1, 1, 1 ) ] } [sub_resource type="Animation" id=8] length = 0.3 loop = true step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath("BodyPivot/Body:position") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.15 ), "transitions": PoolRealArray( 0.466516, 1.86089 ), "update": 0, "values": [ Vector2( 0, -58.8242 ), Vector2( 0, -75.549 ) ] } tracks/1/type = "method" tracks/1/path = NodePath("Sfx/Steps") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "values": [ { "args": [ ], "method": "play_random" } ] } tracks/2/type = "method" tracks/2/path = NodePath("StateMachine/Move") tracks/2/interp = 1 tracks/2/loop_wrap = true tracks/2/imported = false tracks/2/enabled = true tracks/2/keys = { "times": PoolRealArray( 0.3 ), "transitions": PoolRealArray( 1 ), "values": [ { "args": [ ], "method": "spawn_dust" } ] } [sub_resource type="DynamicFont" id=9] size = 20 use_mipmaps = false use_filter = true font_data = ExtResource( 17 ) _sections_unfolded = [ "Font", "Settings" ] [node name="Player" type="KinematicBody2D" index="0"] position = Vector2( 960, 550 ) input_pickable = false collision_layer = 1 collision_mask = 3 collision/safe_margin = 0.08 script = ExtResource( 1 ) _sections_unfolded = [ "Collision", "Transform", "Visibility" ] __meta__ = { "_edit_horizontal_guides_": [ ] } [node name="ShakingCamera" parent="." index="0" instance=ExtResource( 2 )] [node name="HitBox" parent="." index="1" instance=ExtResource( 3 )] monitorable = true [node name="CollisionShape2D" parent="HitBox" index="0"] shape = SubResource( 1 ) [node name="StateMachine" type="Node" parent="." index="2"] script = ExtResource( 4 ) active = false [node name="Idle" type="Node" parent="StateMachine" index="0"] script = ExtResource( 5 ) [node name="Move" type="Node" parent="StateMachine" index="1"] script = ExtResource( 6 ) MAX_WALK_SPEED = 450 MAX_RUN_SPEED = 700 [node name="Bump" type="Node" parent="StateMachine" index="2"] script = ExtResource( 7 ) SPEED = 240.0 [node name="Fall" type="Node" parent="StateMachine" index="3"] script = ExtResource( 8 ) [node name="Jump" type="Node" parent="StateMachine" index="4"] script = ExtResource( 9 ) BASE_MAX_HORIZONTAL_SPEED = 400.0 AIR_ACCELERATION = 1000.0 AIR_DECCELERATION = 2000.0 AIR_STEERING_POWER = 50.0 JUMP_HEIGHT = 120.0 JUMP_DURATION = 0.8 GRAVITY = 1600.0 [node name="Stagger" type="Node" parent="StateMachine" index="5"] script = ExtResource( 10 ) [node name="Attack" type="Node" parent="StateMachine" index="6"] script = ExtResource( 11 ) [node name="Die" type="Node" parent="StateMachine" index="7"] script = ExtResource( 12 ) [node name="AnimationPlayer" type="AnimationPlayer" parent="." index="3"] root_node = NodePath("..") autoplay = "" playback_process_mode = 1 playback_default_blend_time = 0.0 playback_speed = 1.0 anims/SETUP = SubResource( 2 ) anims/bump = SubResource( 3 ) anims/die = SubResource( 4 ) anims/fall = SubResource( 5 ) anims/idle = SubResource( 6 ) anims/stagger = SubResource( 7 ) anims/walk = SubResource( 8 ) blend_times = [ ] [node name="Shadow" type="Sprite" parent="." index="4"] self_modulate = Color( 1, 1, 1, 0.361098 ) position = Vector2( 0.362319, -4 ) texture = ExtResource( 13 ) _sections_unfolded = [ "Transform", "Visibility" ] [node name="BodyPivot" type="Position2D" parent="." index="5"] _sections_unfolded = [ "Material", "Transform", "Visibility" ] [node name="WeaponPivot" type="Position2D" parent="BodyPivot" index="0"] position = Vector2( 0, -62 ) script = ExtResource( 14 ) _sections_unfolded = [ "Transform", "Z Index" ] [node name="Offset" type="Position2D" parent="BodyPivot/WeaponPivot" index="0"] position = Vector2( 110, 0 ) [node name="Sword" parent="BodyPivot/WeaponPivot/Offset" index="0" instance=ExtResource( 15 )] [node name="Body" type="Sprite" parent="BodyPivot" index="1"] position = Vector2( 0, -58.8242 ) texture = ExtResource( 16 ) _sections_unfolded = [ "Visibility" ] [node name="StateNameDisplayer" type="Label" parent="BodyPivot" index="2"] editor/display_folded = true visible = false anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = -109.0 margin_top = -172.0 margin_right = 110.0 margin_bottom = -138.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 custom_fonts/font = SubResource( 9 ) text = "Test" align = 1 valign = 1 uppercase = true percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 script = ExtResource( 18 ) _sections_unfolded = [ "Rect", "custom_fonts" ] [node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="." index="6"] build_mode = 0 polygon = PoolVector2Array( -20, 0, -20, -20, 20, -20, 20, 0 ) [node name="Health" parent="." index="7" instance=ExtResource( 19 )] [node name="Purse" parent="." index="8" instance=ExtResource( 20 )] coins = 32 MAXIMUM = 1000000 [node name="Inventory" parent="." index="9" instance=ExtResource( 21 )] [node name="MinorHealthPotion" parent="Inventory" index="0" instance=ExtResource( 22 )] amount = 4 [node name="StrongHealthPotion" parent="Inventory" index="1" instance=ExtResource( 23 )] [node name="BulletSpawn" type="Node2D" parent="." index="10"] position = Vector2( 1.17401, -61.266 ) script = ExtResource( 24 ) _sections_unfolded = [ "Transform" ] [node name="CooldownTimer" type="Timer" parent="BulletSpawn" index="0"] process_mode = 1 wait_time = 0.2 one_shot = true autostart = false [node name="Sfx" type="Node" parent="." index="11"] [node name="Steps" type="AudioStreamPlayer" parent="Sfx" index="0"] stream = ExtResource( 25 ) volume_db = -16.0 pitch_scale = 1.0 autoplay = false mix_target = 0 bus = "Master" script = ExtResource( 26 ) [node name="CoinsCollector" parent="." index="12" instance=ExtResource( 27 )] [connection signal="direction_changed" from="." to="BodyPivot/WeaponPivot" method="_on_Player_direction_changed"] [connection signal="state_changed" from="StateMachine" to="BodyPivot/StateNameDisplayer" method="_on_StateMachine_state_changed"] [connection signal="last_moved" from="StateMachine/Move" to="StateMachine/Bump" method="_on_Move_last_moved"] [connection signal="finished" from="StateMachine/Die" to="." method="_on_Die_finished"] [connection signal="animation_finished" from="AnimationPlayer" to="StateMachine" method="_on_animation_finished"] [connection signal="combo_finished" from="BodyPivot/WeaponPivot/Offset/Sword" to="StateMachine/Attack" method="_on_Sword_combo_finished"] [connection signal="damage_taken" from="Health" to="StateMachine" method="_on_Health_damage_taken"] [connection signal="health_depleted" from="Health" to="StateMachine" method="_on_Health_health_depleted"] [connection signal="coins_received" from="CoinsCollector" to="Purse" method="add_coins"] [editable path="HitBox"] ================================================ FILE: actors/player/PlayerController.gd ================================================ extends "res://actors/Actor.gd" onready var weapon = $BodyPivot/WeaponPivot/Offset/Sword onready var camera = $ShakingCamera onready var state_machine = $StateMachine onready var anim_player = $AnimationPlayer onready var body = $BodyPivot/Body onready var purse = $Purse func _ready(): anim_player.play('SETUP') state_machine.start() func reset(target_global_position): .reset(target_global_position) anim_player.play('SETUP') camera.offset = Vector2() camera.current = true func get_body(): return body func take_damage_from(damage_source): if state_machine.current_state == $StateMachine/Stagger: return .take_damage_from(damage_source) $StateMachine/Stagger.knockback_direction = (damage_source.global_position - global_position).normalized() camera.shake = true func move(velocity): move_and_slide(velocity, Vector2(), 5, 2) emit_signal("position_changed", position) if get_slide_count() == 0: return return get_slide_collision(0) func fall(gap_size): """ Interrupts the state machine and goes to the Fall state """ state_machine._change_state('fall') yield(state_machine.current_state, 'finished') move_and_collide(-look_direction * gap_size * 1.5) $Health.take_damage(2) func _on_Die_finished(string): set_dead(true) func get_health_node(): return $Health func get_inventory(): return $Inventory func get_purse(): return purse ================================================ FILE: actors/player/PlayerStateMachine.gd ================================================ extends "res://utils/state/StateMachine.gd" func _ready(): states_map = { 'idle': $Idle, 'move': $Move, 'jump': $Jump, 'bump': $Bump, 'fall': $Fall, 'stagger': $Stagger, 'attack': $Attack, 'die': $Die, } for state in get_children(): state.connect('finished', self, '_change_state') func _change_state(state_name): if current_state == states_map['die']: set_active(false) return # Reset the player's jump height if transitioning away from jump to a state # that would stop jump's update method if current_state == states_map['jump'] and state_name in ['fall']: current_state.height = 0 if not active: return if state_name in ['stagger', 'jump', 'attack']: states_stack.push_front(states_map[state_name]) if state_name == 'jump' and current_state == $Move: $Jump.initialize($Move.speed, $Move.velocity) ._change_state(state_name) func _unhandled_input(event): if event.is_action_pressed('attack'): if current_state in [$Attack, $Stagger]: return _change_state('attack') get_tree().set_input_as_handled() return current_state.handle_input(event) func _on_Health_damage_taken(new_health): _change_state('stagger') func _on_Health_health_depleted(): _change_state('die') ================================================ FILE: actors/player/body.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/body.png-f9a1fa1c6faee90775a5169653a19c8b.stex" metadata={ "vram_texture": false } [deps] source_file="res://actors/player/body.png" dest_files=[ "res://.import/body.png-f9a1fa1c6faee90775a5169653a19c8b.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: actors/player/shadow.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/shadow.png-a76d0d66e7c861fcbe21472ca29df610.stex" metadata={ "vram_texture": false } [deps] source_file="res://actors/player/shadow.png" dest_files=[ "res://.import/shadow.png-a76d0d66e7c861fcbe21472ca29df610.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: actors/player/states/Die.gd ================================================ extends "res://utils/state/State.gd" func enter(): owner.set_dead(true) owner.get_node("AnimationPlayer").play("die") func _on_animation_finished(anim_name): emit_signal("finished", "none") ================================================ FILE: actors/player/states/Fall.gd ================================================ extends "res://utils/state/State.gd" func enter(): owner.get_node('AnimationPlayer').play('fall') func _on_animation_finished(anim_name): emit_signal('finished', 'idle') ================================================ FILE: actors/player/states/combat/Attack.gd ================================================ """ The stagger state end with the stagger animation from the AnimationPlayer The animation only affects the Body Sprite"s modulate property so it could stack with other animations if we had two AnimationPlayer nodes """ extends "res://utils/state/State.gd" func enter(): owner.get_node("AnimationPlayer").play("idle") owner.weapon.attack() func _on_Sword_combo_finished(): emit_signal("finished", "previous") ================================================ FILE: actors/player/states/combat/Stagger.gd ================================================ """ The stagger state end with the stagger animation from the AnimationPlayer The animation only affects the Body Sprite"s modulate property so it could stack with other animations if we had two AnimationPlayer nodes """ extends "res://utils/state/State.gd" var knockback_direction = Vector2() func enter(): owner.get_node("AnimationPlayer").play("stagger") func _on_animation_finished(anim_name): owner.get_body().modulate = Color('#ffffff') emit_signal("finished", "previous") ================================================ FILE: actors/player/states/debug/StateNameDisplayer.gd ================================================ extends Label func _on_StateMachine_state_changed(current_state): text = current_state.name ================================================ FILE: actors/player/states/motion/Motion.gd ================================================ # Collection of important methods to handle direction and animation extends "res://utils/state/State.gd" func handle_input(event): if event.is_action_pressed("discrete_move_left") or Input.is_action_pressed("joy_move_left") \ or event.is_action_pressed("discrete_move_right") or Input.is_action_pressed("joy_move_right") \ or event.is_action_pressed("discrete_move_up") or Input.is_action_pressed("joy_move_up") \ or event.is_action_pressed("discrete_move_down") or Input.is_action_pressed("joy_move_down"): get_tree().set_input_as_handled() func get_input_direction(): var input_direction = Vector2() input_direction.x = \ int(Input.is_action_pressed("discrete_move_right") or Input.is_action_pressed("joy_move_right")) - \ int(Input.is_action_pressed("discrete_move_left") or Input.is_action_pressed("joy_move_left")) input_direction.y = \ int(Input.is_action_pressed("discrete_move_down") or Input.is_action_pressed("joy_move_down")) - \ int(Input.is_action_pressed("discrete_move_up") or Input.is_action_pressed("joy_move_up")) return input_direction func update_look_direction(direction): if direction and owner.look_direction != direction: owner.look_direction = direction ================================================ FILE: actors/player/states/motion/in_air/Jump.gd ================================================ extends "../Motion.gd" export(float) var BASE_MAX_HORIZONTAL_SPEED = 400.0 export(float) var AIR_ACCELERATION = 1000.0 export(float) var AIR_DECCELERATION = 2000.0 export(float) var AIR_STEERING_POWER = 50.0 export(float) var JUMP_HEIGHT = 120.0 export(float) var JUMP_DURATION = 0.8 export(float) var GRAVITY = 1600.0 var enter_velocity = Vector2() var max_horizontal_speed = 0.0 var horizontal_speed = 0.0 var horizontal_velocity = Vector2() var vertical_speed = 0.0 var height = 0.0 setget set_height func initialize(speed, velocity): horizontal_speed = speed max_horizontal_speed = speed if speed > 0.0 else BASE_MAX_HORIZONTAL_SPEED enter_velocity = velocity func enter(): var input_direction = get_input_direction() update_look_direction(input_direction) horizontal_velocity = enter_velocity if input_direction else Vector2() vertical_speed = 600.0 owner.get_node("AnimationPlayer").play("idle") func update(delta): var input_direction = get_input_direction() update_look_direction(input_direction) move_horizontally(delta, input_direction) animate_jump_height(delta) if height <= 0.0: emit_signal("finished", "previous") func move_horizontally(delta, direction): if direction: horizontal_speed += AIR_ACCELERATION * delta else: horizontal_speed -= AIR_DECCELERATION * delta horizontal_speed = clamp(horizontal_speed, 0, max_horizontal_speed) var target_velocity = horizontal_speed * direction.normalized() var steering_velocity = (target_velocity - horizontal_velocity).normalized() * AIR_STEERING_POWER horizontal_velocity += steering_velocity owner.move_and_slide(horizontal_velocity) owner.emit_signal("position_changed", owner.position) func set_height(new_height): height = new_height owner.get_node("BodyPivot").position.y = -height func animate_jump_height(delta): vertical_speed -= GRAVITY * delta set_height(max(0.0, height + vertical_speed * delta)) ================================================ FILE: actors/player/states/motion/on_ground/BumpPlayer.gd ================================================ extends "res://utils/state/State.gd" export(float) var SPEED = 240.0 var direction = Vector2(-1.0, 0.0) func _on_Move_last_moved(moved_direction): direction = -moved_direction func enter(): owner.get_node('AnimationPlayer').play('bump') func update(delta): owner.move_and_slide(direction * SPEED) func _on_animation_finished(anim_name): emit_signal('finished', 'idle') ================================================ FILE: actors/player/states/motion/on_ground/Idle.gd ================================================ extends "OnGround.gd" func enter(): owner.get_node("AnimationPlayer").play("idle") func handle_input(event): return .handle_input(event) func update(delta): var input_direction = get_input_direction() if input_direction: emit_signal("finished", "move") ================================================ FILE: actors/player/states/motion/on_ground/Move.gd ================================================ extends "OnGround.gd" signal last_moved(direction) export(float) var MAX_WALK_SPEED = 450 export(float) var MAX_RUN_SPEED = 700 const DustRun = preload("res://vfx/particles/dust_puffs/DustRun.tscn") const DustWalk = preload("res://vfx/particles/dust_puffs/DustWalk.tscn") func enter(): speed = 0.0 velocity = Vector2() var input_direction = get_input_direction() update_look_direction(input_direction) owner.get_node("AnimationPlayer").play("walk") func exit(): owner.get_node("AnimationPlayer").play("idle") func handle_input(event): return .handle_input(event) func update(delta): var input_direction = get_input_direction() if not input_direction: emit_signal("finished", "idle") update_look_direction(input_direction) speed = MAX_RUN_SPEED if Input.is_action_pressed("run") else MAX_WALK_SPEED velocity = input_direction.normalized() * speed var collision_info = owner.move(velocity) if not collision_info: return if speed == MAX_RUN_SPEED and collision_info.collider.is_in_group("environment"): emit_signal("last_moved", input_direction) emit_signal("finished", 'bump') func spawn_dust(): var dust match speed: MAX_RUN_SPEED: dust = DustRun.instance() MAX_WALK_SPEED: dust = DustWalk.instance() owner.add_child(dust) dust.start() ================================================ FILE: actors/player/states/motion/on_ground/OnGround.gd ================================================ extends "../Motion.gd" var speed = 0.0 var velocity = Vector2() func handle_input(event): if event.is_action_pressed("jump"): emit_signal("finished", "jump") return .handle_input(event) ================================================ FILE: actors/shadow.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/shadow.png-c2c688bd1e688f17d176ab7d3afdad57.stex" metadata={ "vram_texture": false } [deps] source_file="res://actors/shadow.png" dest_files=[ "res://.import/shadow.png-c2c688bd1e688f17d176ab7d3afdad57.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: actors/weapons/bullet/Bullet.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://actors/weapons/bullet/bullet.gd" type="Script" id=1] [sub_resource type="CircleShape2D" id=1] custom_solver_bias = 0.0 radius = 12.0 [node name="Bullet" type="KinematicBody2D" index="0"] input_pickable = false collision_layer = 2 collision_mask = 2 collision/safe_margin = 0.08 script = ExtResource( 1 ) _sections_unfolded = [ "Collision", "collision" ] SPEED = 1000.0 [node name="CollisionShape2D" type="CollisionShape2D" parent="." index="0"] shape = SubResource( 1 ) ================================================ FILE: actors/weapons/bullet/BulletSpawner.gd ================================================ extends Node2D var bullet = preload("Bullet.tscn") func _input(event): if event.is_action_pressed("fire"): fire(owner.look_direction) func fire(direction): if not $CooldownTimer.is_stopped(): return $CooldownTimer.start() var new_bullet = bullet.instance() new_bullet.direction = direction add_child(new_bullet) ================================================ FILE: actors/weapons/bullet/bullet.gd ================================================ extends KinematicBody2D var direction = Vector2() export(float) var SPEED = 1000.0 func _ready(): set_as_toplevel(true) func _physics_process(delta): if is_outside_view_bounds(): queue_free() var motion = direction * SPEED * delta var collision_info = move_and_collide(motion) if collision_info: queue_free() func is_outside_view_bounds(): return position.x > OS.get_screen_size().x or position.x < 0.0 \ or position.y > OS.get_screen_size().y or position.y < 0.0 func _draw(): draw_circle(Vector2(), $CollisionShape2D.shape.radius, Color('#ffffff')) ================================================ FILE: actors/weapons/sword/Sword.gd ================================================ extends "res://actors/DamageSource.gd" signal combo_finished() enum States { IDLE, ATTACK } var state = null enum AttackInputStates { WAITING, LISTENING, REGISTERED } var attack_input_state = AttackInputStates.WAITING var ready_for_next_attack = false var attack_id = 0 var combo = [ { 'damage': 1, 'animation': 'attack_fast', }, { 'damage': 1, 'animation': 'attack_fast', }, { 'damage': 3, 'animation': 'attack_medium', }] func _ready(): $AnimationPlayer.connect('animation_finished', self, "_on_animation_finished") _change_state(States.IDLE) func _change_state(new_state): match state: States.IDLE: visible = true match new_state: States.IDLE: attack_id = 0 visible = false States.ATTACK: attack_input_state = AttackInputStates.WAITING ready_for_next_attack = false var attack = combo[min(attack_id, combo.size() - 1)] damage = attack['damage'] $AnimationPlayer.play(attack['animation']) attack_id += 1 state = new_state func _input(event): if not state == States.ATTACK: return if attack_input_state != AttackInputStates.LISTENING: return if event.is_action_pressed('attack'): attack_input_state = AttackInputStates.REGISTERED func _physics_process(delta): if attack_input_state == AttackInputStates.REGISTERED and ready_for_next_attack: attack() func attack(): _change_state(States.ATTACK) # use with AnimationPlayer func track func set_attack_input_listening(): attack_input_state = AttackInputStates.LISTENING # use with AnimationPlayer func track func set_ready_for_next_attack(): ready_for_next_attack = true func _on_animation_finished(name): if attack_input_state == AttackInputStates.REGISTERED and attack_id < combo.size(): attack() else: _change_state(States.IDLE) emit_signal("combo_finished") ================================================ FILE: actors/weapons/sword/Sword.tscn ================================================ [gd_scene load_steps=8 format=2] [ext_resource path="res://actors/weapons/sword/Sword.gd" type="Script" id=1] [ext_resource path="res://actors/weapons/sword/sword.png" type="Texture" id=2] [sub_resource type="Animation" id=1] resource_name = "SETUP" length = 0.01 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath(".:rotation_degrees") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ 0.0 ] } tracks/1/type = "value" tracks/1/path = NodePath(".:scale") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 1, 1 ) ] } tracks/2/type = "value" tracks/2/path = NodePath(".:visible") tracks/2/interp = 1 tracks/2/loop_wrap = true tracks/2/imported = false tracks/2/enabled = true tracks/2/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 1, "values": [ true ] } tracks/3/type = "value" tracks/3/path = NodePath(".:monitoring") tracks/3/interp = 1 tracks/3/loop_wrap = true tracks/3/imported = false tracks/3/enabled = true tracks/3/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 1, "values": [ true ] } tracks/4/type = "value" tracks/4/path = NodePath(".:monitorable") tracks/4/interp = 1 tracks/4/loop_wrap = true tracks/4/imported = false tracks/4/enabled = true tracks/4/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 1, "values": [ false ] } tracks/5/type = "value" tracks/5/path = NodePath("CollisionPolygon2D:disabled") tracks/5/interp = 1 tracks/5/loop_wrap = true tracks/5/imported = false tracks/5/enabled = true tracks/5/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 1, "values": [ true ] } [sub_resource type="Animation" id=2] resource_name = "attack_circular" length = 0.3 loop = false step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath(".:rotation_degrees") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.15, 0.2 ), "transitions": PoolRealArray( 0.439427, 1, 1 ), "update": 0, "values": [ -100.0, 100.0, 90.0 ] } tracks/1/type = "value" tracks/1/path = NodePath(".:scale") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0, 0.05, 0.15, 0.2 ), "transitions": PoolRealArray( 1, 2.50795, 1, 1 ), "update": 0, "values": [ Vector2( 1, 1 ), Vector2( 1, 1.3 ), Vector2( 1, 1 ), Vector2( 1, 1 ) ] } tracks/2/type = "value" tracks/2/path = NodePath(".:visible") tracks/2/interp = 1 tracks/2/loop_wrap = true tracks/2/imported = false tracks/2/enabled = true tracks/2/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 1, "values": [ true ] } tracks/3/type = "value" tracks/3/path = NodePath("CollisionPolygon2D:disabled") tracks/3/interp = 1 tracks/3/loop_wrap = true tracks/3/imported = false tracks/3/enabled = true tracks/3/keys = { "times": PoolRealArray( 0, 0.2 ), "transitions": PoolRealArray( 1, 1 ), "update": 1, "values": [ false, true ] } [sub_resource type="Animation" id=3] length = 0.45 loop = false step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath(".:rotation_degrees") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.15, 0.2 ), "transitions": PoolRealArray( 0.439427, 1, 1 ), "update": 0, "values": [ -80.0, 85.0, 75.0 ] } tracks/1/type = "value" tracks/1/path = NodePath(".:scale") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0, 0.05, 0.15, 0.2 ), "transitions": PoolRealArray( 1, 2.50795, 1, 1 ), "update": 0, "values": [ Vector2( 1, 1 ), Vector2( 1, 1.3 ), Vector2( 1, 1 ), Vector2( 1, 1 ) ] } tracks/2/type = "value" tracks/2/path = NodePath(".:visible") tracks/2/interp = 1 tracks/2/loop_wrap = true tracks/2/imported = false tracks/2/enabled = true tracks/2/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 1, "values": [ true ] } tracks/3/type = "method" tracks/3/path = NodePath(".") tracks/3/interp = 1 tracks/3/loop_wrap = true tracks/3/imported = false tracks/3/enabled = true tracks/3/keys = { "times": PoolRealArray( 0.1, 0.25 ), "transitions": PoolRealArray( 1, 1 ), "values": [ { "args": [ ], "method": "set_attack_input_listening" }, { "args": [ ], "method": "set_ready_for_next_attack" } ] } tracks/4/type = "value" tracks/4/path = NodePath("CollisionPolygon2D:disabled") tracks/4/interp = 1 tracks/4/loop_wrap = true tracks/4/imported = false tracks/4/enabled = true tracks/4/keys = { "times": PoolRealArray( 0, 0.2 ), "transitions": PoolRealArray( 1, 1 ), "update": 1, "values": [ false, true ] } [sub_resource type="Animation" id=4] resource_name = "attack_medium" length = 0.5 loop = false step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath(".:rotation_degrees") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0.05, 0.25, 0.35 ), "transitions": PoolRealArray( 0.439427, 1, 1 ), "update": 0, "values": [ 95.0, -95.0, -90.0 ] } tracks/1/type = "value" tracks/1/path = NodePath(".:scale") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0, 0.1, 0.2, 0.25 ), "transitions": PoolRealArray( 1, 2.50795, 1, 1 ), "update": 0, "values": [ Vector2( 1, 1 ), Vector2( 1, 1.3 ), Vector2( 1, 1 ), Vector2( 1, 1 ) ] } tracks/2/type = "value" tracks/2/path = NodePath(".:visible") tracks/2/interp = 1 tracks/2/loop_wrap = true tracks/2/imported = false tracks/2/enabled = true tracks/2/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 1, "values": [ true ] } tracks/3/type = "value" tracks/3/path = NodePath("CollisionPolygon2D:disabled") tracks/3/interp = 1 tracks/3/loop_wrap = true tracks/3/imported = false tracks/3/enabled = true tracks/3/keys = { "times": PoolRealArray( 0, 0.35 ), "transitions": PoolRealArray( 1, 1 ), "update": 1, "values": [ false, true ] } [sub_resource type="Animation" id=5] length = 0.01 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath(".:visible") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 1, "values": [ false ] } tracks/1/type = "value" tracks/1/path = NodePath("CollisionPolygon2D:disabled") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 1, "values": [ true ] } [node name="Sword" type="Area2D"] rotation = 1.5708 input_pickable = false gravity_vec = Vector2( 0, 1 ) gravity = 98.0 linear_damp = 0.1 angular_damp = 1.0 monitoring = false collision_layer = 16 collision_mask = 8 audio_bus_override = false audio_bus_name = "Master" script = ExtResource( 1 ) _sections_unfolded = [ "Collision", "Transform" ] damage = 2 [node name="AnimationPlayer" type="AnimationPlayer" parent="." index="0"] root_node = NodePath("..") autoplay = "" playback_process_mode = 1 playback_default_blend_time = 0.0 playback_speed = 1.0 anims/SETUP = SubResource( 1 ) anims/attack_circular = SubResource( 2 ) anims/attack_fast = SubResource( 3 ) anims/attack_medium = SubResource( 4 ) anims/idle = SubResource( 5 ) blend_times = [ ] _sections_unfolded = [ "Playback Options" ] [node name="sword" type="Sprite" parent="." index="1"] position = Vector2( 4, 0 ) texture = ExtResource( 2 ) offset = Vector2( 67, 0 ) _sections_unfolded = [ "Offset", "Transform" ] [node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="." index="2"] build_mode = 0 polygon = PoolVector2Array( 32, -112, 128, -80, 160, 0, 128, 80, 32, 112 ) disabled = true ================================================ FILE: actors/weapons/sword/WeaponPivot.gd ================================================ extends Position2D func _on_Player_direction_changed(new_direction): rotation = new_direction.angle() show_behind_parent = new_direction == Vector2(0, -1) ================================================ FILE: actors/weapons/sword/sword.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/sword.png-2705643189a083599451044bb61b43fc.stex" metadata={ "vram_texture": false } [deps] source_file="res://actors/weapons/sword/sword.png" dest_files=[ "res://.import/sword.png-2705643189a083599451044bb61b43fc.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: audio/AudioShuffleStepSounds.gd ================================================ extends AudioStreamPlayer # In Godot 3.1 you can export the Array instead var samples = [ preload("res://audio/sfx/step_01.wav"), preload("res://audio/sfx/step_02.wav") ] func _ready(): randomize() func play_random(): # In Godot 3.1 you can use Array.shuffle() after going through the sounds stream = samples[randi() % samples.size()] play() ================================================ FILE: audio/AudioStreamPlayer.tscn ================================================ [gd_scene load_steps=2 format=2] [ext_resource path="res://audio/AudioShuffleStepSounds.gd" type="Script" id=1] [node name="AudioStreamPlayer" type="AudioStreamPlayer"] stream = null volume_db = 0.0 pitch_scale = 1.0 autoplay = false mix_target = 0 bus = "Master" script = ExtResource( 1 ) ================================================ FILE: audio/MusicPlayer.gd ================================================ extends AudioStreamPlayer func _ready(): play() ================================================ FILE: audio/MusicPlayer.tscn ================================================ [gd_scene load_steps=2 format=2] [ext_resource path="res://audio/music/birdy_pong.ogg" type="AudioStream" id=1] [node name="MusicPlayer" type="AudioStreamPlayer"] pause_mode = 2 stream = ExtResource( 1 ) volume_db = 0.0 pitch_scale = 1.0 autoplay = false mix_target = 0 bus = "Music" _sections_unfolded = [ "Pause" ] ================================================ FILE: audio/music/birdy_pong.ogg.import ================================================ [remap] importer="ogg_vorbis" type="AudioStreamOGGVorbis" path="res://.import/birdy_pong.ogg-25193f4693fd63a5305fa3c526808da0.oggstr" [deps] source_file="res://audio/music/birdy_pong.ogg" dest_files=[ "res://.import/birdy_pong.ogg-25193f4693fd63a5305fa3c526808da0.oggstr" ] [params] loop=true loop_offset=-2.65 ================================================ FILE: audio/sfx/menu_confirm.wav.import ================================================ [remap] importer="wav" type="AudioStreamSample" path="res://.import/menu_confirm.wav-b14347e8ceccbb161b72ec9db2392e19.sample" [deps] source_file="res://audio/sfx/menu_confirm.wav" dest_files=[ "res://.import/menu_confirm.wav-b14347e8ceccbb161b72ec9db2392e19.sample" ] [params] force/8_bit=false force/mono=false force/max_rate=false force/max_rate_hz=44100 edit/trim=true edit/normalize=true edit/loop=false compress/mode=0 ================================================ FILE: audio/sfx/menu_navigate_01.wav.import ================================================ [remap] importer="wav" type="AudioStreamSample" path="res://.import/menu_navigate_01.wav-773eee8fbe1dd9eb11962e36b57bc664.sample" [deps] source_file="res://audio/sfx/menu_navigate_01.wav" dest_files=[ "res://.import/menu_navigate_01.wav-773eee8fbe1dd9eb11962e36b57bc664.sample" ] [params] force/8_bit=false force/mono=false force/max_rate=false force/max_rate_hz=44100 edit/trim=true edit/normalize=true edit/loop=false compress/mode=0 ================================================ FILE: audio/sfx/menu_navigate_02.wav.import ================================================ [remap] importer="wav" type="AudioStreamSample" path="res://.import/menu_navigate_02.wav-671622ef2a874b5827dcda32ef1e01ba.sample" [deps] source_file="res://audio/sfx/menu_navigate_02.wav" dest_files=[ "res://.import/menu_navigate_02.wav-671622ef2a874b5827dcda32ef1e01ba.sample" ] [params] force/8_bit=false force/mono=false force/max_rate=false force/max_rate_hz=44100 edit/trim=true edit/normalize=true edit/loop=false compress/mode=0 ================================================ FILE: audio/sfx/menu_popup_open.wav.import ================================================ [remap] importer="wav" type="AudioStreamSample" path="res://.import/menu_popup_open.wav-51859fa0446f42584709772f4d8e8405.sample" [deps] source_file="res://audio/sfx/menu_popup_open.wav" dest_files=[ "res://.import/menu_popup_open.wav-51859fa0446f42584709772f4d8e8405.sample" ] [params] force/8_bit=false force/mono=false force/max_rate=false force/max_rate_hz=44100 edit/trim=true edit/normalize=true edit/loop=false compress/mode=0 ================================================ FILE: audio/sfx/step_01.wav.import ================================================ [remap] importer="wav" type="AudioStreamSample" path="res://.import/step_01.wav-daf925df75ada545cb636d177cd40f57.sample" [deps] source_file="res://audio/sfx/step_01.wav" dest_files=[ "res://.import/step_01.wav-daf925df75ada545cb636d177cd40f57.sample" ] [params] force/8_bit=false force/mono=false force/max_rate=false force/max_rate_hz=44100 edit/trim=true edit/normalize=true edit/loop=false compress/mode=0 ================================================ FILE: audio/sfx/step_02.wav.import ================================================ [remap] importer="wav" type="AudioStreamSample" path="res://.import/step_02.wav-f7737a1e06e1f3d2e9e00fd041d0652d.sample" [deps] source_file="res://audio/sfx/step_02.wav" dest_files=[ "res://.import/step_02.wav-f7737a1e06e1f3d2e9e00fd041d0652d.sample" ] [params] force/8_bit=false force/mono=false force/max_rate=false force/max_rate_hz=44100 edit/trim=true edit/normalize=true edit/loop=false compress/mode=0 ================================================ FILE: core/Game.gd ================================================ extends Node onready var level_loader = $LevelLoader onready var transition = $Overlays/TransitionColor onready var pause_menu = $Interface/PauseMenu onready var tree = get_tree() func _ready(): $Interface.initialize($LevelLoader/Player) level_loader.initialize() for door in level_loader.get_doors(): door.connect("player_entered", self, "_on_Door_player_entered") func change_level(scene_path): tree.paused = true yield(transition.fade_to_color(), "completed") level_loader.change_level(scene_path) for door in level_loader.get_doors(): door.connect("player_entered", self, "_on_Door_player_entered") yield(transition.fade_from_color(), "completed") tree.paused = false func _on_Door_player_entered(target_map): change_level(target_map) func _unhandled_input(event): if event.is_action_pressed("pause"): pause() tree.set_input_as_handled() if event.is_action_pressed("toggle_fullscreen"): OS.window_fullscreen = not OS.window_fullscreen func pause(): tree.paused = true pause_menu.open() yield(pause_menu, "closed") tree.paused = false func _on_ShopMenu_open(): tree.paused = true func _on_ShopMenu_closed(): tree.paused = false ================================================ FILE: core/LevelLoader.gd ================================================ extends Node signal loaded(level) export(String, FILE, "*.tscn") var LEVEL_START var map onready var player = $Player func initialize(): remove_child(player) change_level(LEVEL_START) func change_level(scene_path): if map: map.get_ysort_node().remove_child(player) remove_child(map) map.queue_free() map = load(scene_path).instance() add_child(map) map.get_ysort_node().add_child(player) var spawn = map.get_node("PlayerSpawningPoint") player.reset(spawn.global_position) for monster in get_tree().get_nodes_in_group("monster"): monster.initialize(player) map.initialize() emit_signal("loaded", map) func get_doors(): var doors = [] for door in get_tree().get_nodes_in_group("doors"): if not map.is_a_parent_of(door): continue doors.append(door) return doors ================================================ FILE: core/inventory/Inventory.gd ================================================ extends Node signal content_changed(items_as_string) signal item_added(item) signal item_removed(item) func get_items(): return get_children() func find_item(reference): for item in get_items(): if item.name == reference.name: return item func has(item): return true if find_item(item) else false func get_count(reference): var item = find_item(reference) return item.amount if item else 0 func add(reference, amount=1): var item = find_item(reference) if not item: item = _instance_item_from_db(reference) amount -= item.amount item.amount += amount emit_signal("content_changed", get_content_as_string()) func trash(reference, amount=1): var item = find_item(reference) if not item: return item.amount -= amount emit_signal("content_changed", get_content_as_string()) func use(item, user): item.use(user) emit_signal("content_changed", get_content_as_string()) func get_content_as_string(): var string = "" for item in get_items(): if item.amount == 0: continue string += "%s: %s" % [item.name, item.amount] string += "\n" return string func _instance_item_from_db(reference): var item = ItemDatabase.get_item(reference) add_child(item) item.connect("depleted", self, "_on_Item_depleted", [item]) emit_signal("item_added", item) return item func _on_Item_depleted(item): emit_signal("item_removed", item) ================================================ FILE: core/inventory/Inventory.tscn ================================================ [gd_scene load_steps=2 format=2] [ext_resource path="res://core/inventory/Inventory.gd" type="Script" id=1] [node name="Inventory" type="Node"] script = ExtResource( 1 ) ================================================ FILE: core/inventory/ItemDatabase.gd ================================================ extends Node func get_item(reference): for item in get_children(): if reference.name == item.name: return item.duplicate() func get_items(): return get_children() ================================================ FILE: core/inventory/ItemDatabase.tscn ================================================ [gd_scene load_steps=6 format=2] [ext_resource path="res://core/inventory/ItemDatabase.gd" type="Script" id=1] [ext_resource path="res://core/inventory/items/equipment/sword/Sword.tscn" type="PackedScene" id=2] [ext_resource path="res://core/inventory/items/usable/potions/restore_health/MinorHealthPotion.tscn" type="PackedScene" id=3] [ext_resource path="res://core/inventory/items/usable/potions/restore_health/StrongHealthPotion.tscn" type="PackedScene" id=4] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/FireballScroll.tscn" type="PackedScene" id=5] [node name="ItemDatabase" type="Node"] script = ExtResource( 1 ) [node name="Sword" parent="." index="0" instance=ExtResource( 2 )] [node name="MinorHealthPotion" parent="." index="1" instance=ExtResource( 3 )] [node name="StrongHealthPotion" parent="." index="2" instance=ExtResource( 4 )] [node name="FireballScroll" parent="." index="3" instance=ExtResource( 5 )] ================================================ FILE: core/inventory/items/Coins.gd ================================================ tool extends Area2D enum CoinAmounts {SMALL=10, MID=30, HIGH=100} export(CoinAmounts) var amount = CoinAmounts.SMALL setget set_amount export(float) var MAX_START_VERTICAL_THRUST = 400.0 export(float) var MAX_HORIZONTAL_SPEED = 200.0 export(float) var GRAVITY = 2000.0 export(float) var STOP_THRESHOLD_VERTICAL_SPEED = 4.0 export(float, 0.0, 1.0) var DAMPING_FACTOR = 0.4 onready var sprite = $coins var direction = Vector2() var velocity = Vector2() var speed_horizontal = 0.0 var speed_vertical = 0.0 var height = 0.0 setget set_height var TEXTURES = { CoinAmounts.SMALL: preload("res://core/inventory/items/coins/coin_single.png"), CoinAmounts.MID: preload("res://core/inventory/items/coins/coins_three.png"), CoinAmounts.HIGH: preload("res://core/inventory/items/coins/coins_stack.png"), } func set_amount(value): amount = value if not sprite: return sprite.texture = TEXTURES[value] func _ready(): set_process(false) func throw(): var rand_angle = randf() * 2 * PI direction = Vector2( cos(rand_angle), sin(rand_angle)) speed_vertical = (randf() * 0.5 + 0.5) * MAX_START_VERTICAL_THRUST speed_horizontal = (randf() * 0.8 + 0.2) * MAX_HORIZONTAL_SPEED $Timer.wait_time = rand_range(1.0, 2.0) $Timer.start() set_process(true) func _process(delta): # Move horizontally var speed_scale = $Timer.time_left / $Timer.wait_time velocity = speed_horizontal * direction * speed_scale position += velocity * delta # Move vertically speed_vertical -= GRAVITY * delta var distance_vertical = speed_vertical * delta self.height += distance_vertical if height < 0.0: self.height = 0.0 set_process(false) func set_height(value): height = value if is_processing(): $coins.position.y = -height func set_random_amount(): var amounts = [CoinAmounts.SMALL, CoinAmounts.MID, CoinAmounts.HIGH] self.amount = amounts[randi() % amounts.size()] # TODO: won't work as currently velocity is re-calculated on every process tick #func steer_towards(target_global_position): # velocity = Steering.follow( # velocity, # global_position, # target_global_position, # MAX_HORIZONTAL_SPEED) ================================================ FILE: core/inventory/items/Coins.tscn ================================================ [gd_scene load_steps=4 format=2] [ext_resource path="res://core/inventory/items/Coins.gd" type="Script" id=1] [ext_resource path="res://core/inventory/items/coins/coin_single.png" type="Texture" id=2] [sub_resource type="CircleShape2D" id=1] custom_solver_bias = 0.0 radius = 25.1241 [node name="Coins" type="Area2D" index="0"] input_pickable = true gravity_vec = Vector2( 0, 1 ) gravity = 98.0 linear_damp = 0.1 angular_damp = 1.0 monitoring = false collision_layer = 64 collision_mask = 0 audio_bus_override = false audio_bus_name = "Master" script = ExtResource( 1 ) _sections_unfolded = [ "Audio Bus", "Collision" ] amount = 10 MAX_START_VERTICAL_THRUST = 700.0 MAX_HORIZONTAL_SPEED = 200.0 GRAVITY = 1000.0 STOP_THRESHOLD_VERTICAL_SPEED = 3.0 DAMPING_FACTOR = 0.6 [node name="coins" type="Sprite" parent="." index="0"] texture = ExtResource( 2 ) _sections_unfolded = [ "Transform" ] [node name="CollisionShape2D" type="CollisionShape2D" parent="." index="1"] shape = SubResource( 1 ) [node name="Timer" type="Timer" parent="." index="2"] process_mode = 1 wait_time = 1.0 one_shot = true autostart = false ================================================ FILE: core/inventory/items/Item.gd ================================================ extends Node signal amount_changed(amount) signal depleted() export(Texture) var icon export(String) var display_name = "" export(String) var description = "" export(int) var price = 100 export(int) var amount = 1 setget set_amount export(bool) var unique = false export(bool) var usable = true func use(user): if (not usable) or unique: return if amount == 0: return self.amount -= 1 _apply_effect(user) func set_amount(value): amount = max(0, value) emit_signal("amount_changed", amount) if amount == 0: queue_free() emit_signal("depleted") func _apply_effect(user): print("Item %s has no apply_effect override" % name) ================================================ FILE: core/inventory/items/Item.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://core/inventory/items/Item.gd" type="Script" id=1] [ext_resource path="res://icon.png" type="Texture" id=2] [node name="Item" type="Node" index="0"] script = ExtResource( 1 ) icon = ExtResource( 2 ) display_name = "" description = "" price = 100 amount = 1 unique = false usable = true ================================================ FILE: core/inventory/items/coins/coin_single.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/coin_single.png-d22b36184b3f7cd2e981df8d72015e0f.stex" metadata={ "vram_texture": false } [deps] source_file="res://core/inventory/items/coins/coin_single.png" dest_files=[ "res://.import/coin_single.png-d22b36184b3f7cd2e981df8d72015e0f.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: core/inventory/items/coins/coins_stack.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/coins_stack.png-b4644d39c8e95f1e5c2242620e4272e4.stex" metadata={ "vram_texture": false } [deps] source_file="res://core/inventory/items/coins/coins_stack.png" dest_files=[ "res://.import/coins_stack.png-b4644d39c8e95f1e5c2242620e4272e4.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: core/inventory/items/coins/coins_three.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/coins_three.png-29938721d7b59c8b32b7201678affe18.stex" metadata={ "vram_texture": false } [deps] source_file="res://core/inventory/items/coins/coins_three.png" dest_files=[ "res://.import/coins_three.png-29938721d7b59c8b32b7201678affe18.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: core/inventory/items/equipment/Equipment.gd ================================================ extends '../Item.gd' export(int) var STRENGTH = 0 export(int) var MAGIC = 0 export(int) var ARMOR = 0 export(int) var SPEED = 0 ================================================ FILE: core/inventory/items/equipment/Equipment.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://core/inventory/items/Item.tscn" type="PackedScene" id=1] [ext_resource path="res://core/inventory/items/equipment/Equipment.gd" type="Script" id=2] [node name="Equipment" index="0" instance=ExtResource( 1 )] script = ExtResource( 2 ) icon = null STRENGTH = 0 MAGIC = 0 ARMOR = 0 SPEED = 0 ================================================ FILE: core/inventory/items/equipment/sword/Sword.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://core/inventory/items/equipment/Equipment.tscn" type="PackedScene" id=1] [ext_resource path="res://interface/theme/icons/sword.png" type="Texture" id=2] [node name="Sword" index="0" instance=ExtResource( 1 )] icon = ExtResource( 2 ) display_name = "Sword" description = "An old, slightly rusted sword. Fairly dull." price = 25 usable = false STRENGTH = 20 ================================================ FILE: core/inventory/items/usable/potions/BaseHealthPotion.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://core/inventory/items/Item.tscn" type="PackedScene" id=1] [ext_resource path="res://core/inventory/items/usable/potions/HealthPotion.gd" type="Script" id=2] [node name="HealthPotion" index="0" instance=ExtResource( 1 )] script = ExtResource( 2 ) icon = null price = 20 HEAL_AMOUNT = 20 ================================================ FILE: core/inventory/items/usable/potions/HealthPotion.gd ================================================ extends "res://core/inventory/items/Item.gd" export(int) var HEAL_AMOUNT = 20 func _apply_effect(user): if not user.has_node("Health"): return user.get_node("Health").heal(HEAL_AMOUNT) user.get_node("AnimationPlayer").play("heal") ================================================ FILE: core/inventory/items/usable/potions/restore_health/MinorHealthPotion.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://core/inventory/items/usable/potions/BaseHealthPotion.tscn" type="PackedScene" id=1] [ext_resource path="res://interface/theme/icons/potion_health.png" type="Texture" id=2] [node name="MinorHealthPotion" index="0" instance=ExtResource( 1 )] icon = ExtResource( 2 ) display_name = "Minor health potion" description = "Heals 10 life points" amount = 1 HEAL_AMOUNT = 10 ================================================ FILE: core/inventory/items/usable/potions/restore_health/StrongHealthPotion.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://core/inventory/items/usable/potions/BaseHealthPotion.tscn" type="PackedScene" id=1] [ext_resource path="res://interface/theme/icons/potion_health.png" type="Texture" id=2] [node name="StrongHealthPotion" index="0" instance=ExtResource( 1 )] icon = ExtResource( 2 ) display_name = "Strong health potion" description = "Heals 50 life points" price = 100 HEAL_AMOUNT = 50 ================================================ FILE: core/inventory/items/usable/scroll_fireball/FireballScroll.gd ================================================ extends "res://core/inventory/items/Item.gd" export(PackedScene) var Fireball func _apply_effect(user): var fireball = Fireball.instance() user.add_child(fireball) ================================================ FILE: core/inventory/items/usable/scroll_fireball/FireballScroll.tscn ================================================ [gd_scene load_steps=5 format=2] [ext_resource path="res://core/inventory/items/Item.tscn" type="PackedScene" id=1] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/FireballScroll.gd" type="Script" id=2] [ext_resource path="res://interface/theme/icons/fire_scroll.png" type="Texture" id=3] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/fireball/Fireball.tscn" type="PackedScene" id=4] [node name="FireballScroll" index="0" instance=ExtResource( 1 )] script = ExtResource( 2 ) icon = ExtResource( 3 ) display_name = "Fire scroll" description = "Launches a fire ball that sweeps through the air and damages a single target." Fireball = ExtResource( 4 ) ================================================ FILE: core/inventory/items/usable/scroll_fireball/fireball/Fireball.gd ================================================ extends Area2D export(PackedScene) var Explosion export(float) var SPEED = 1000.0 var direction = Vector2(1, 0) func _physics_process(delta): position += direction * SPEED * delta func _on_body_entered(body): explode() func _on_area_entered(area): explode() func explode(): set_active(false) var explosion_node = Explosion.instance() add_child(explosion_node) get_tree().create_timer(explosion_node.lifetime * 2.0).connect("timeout", self, "queue_free") func set_active(value): set_physics_process(value) $CollisionShape2D.disabled = value $Fireball.active = value ================================================ FILE: core/inventory/items/usable/scroll_fireball/fireball/Fireball.tscn ================================================ [gd_scene load_steps=5 format=2] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/fireball/Fireball.gd" type="Script" id=1] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/fireball/particles/explosions/Explosion.tscn" type="PackedScene" id=2] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/fireball/particles/FireballParticles.tscn" type="PackedScene" id=3] [sub_resource type="CircleShape2D" id=1] custom_solver_bias = 0.0 radius = 31.9831 [node name="Fireball" type="Area2D"] input_pickable = true gravity_vec = Vector2( 0, 1 ) gravity = 98.0 linear_damp = 0.1 angular_damp = 1.0 collision_layer = 8 collision_mask = 6 audio_bus_override = false audio_bus_name = "Master" script = ExtResource( 1 ) _sections_unfolded = [ "Collision" ] Explosion = ExtResource( 2 ) SPEED = 1400.0 [node name="Fireball" parent="." index="0" instance=ExtResource( 3 )] [node name="CollisionShape2D" type="CollisionShape2D" parent="." index="1"] shape = SubResource( 1 ) [connection signal="area_entered" from="." to="." method="_on_area_entered"] [connection signal="body_entered" from="." to="." method="_on_body_entered"] ================================================ FILE: core/inventory/items/usable/scroll_fireball/fireball/particles/FireballParticles.tscn ================================================ [gd_scene load_steps=13 format=2] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/fireball/particles/fireball/fireball.material" type="Material" id=1] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/fireball/particles/sprites/smoke_clouds.png" type="Texture" id=2] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/fireball/particles/ParticlesToggle.gd" type="Script" id=3] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/fireball/particles/assets/gradient_ramps/sparkles_small.tres" type="Gradient" id=4] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/fireball/particles/sprites/circle.png" type="Texture" id=5] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/fireball/particles/assets/gradient_ramps/sparkles.tres" type="Gradient" id=6] [sub_resource type="GradientTexture" id=1] flags = 4 gradient = ExtResource( 4 ) width = 2048 [sub_resource type="Curve" id=2] min_value = 0.0 max_value = 1.0 bake_resolution = 100 _data = [ Vector2( 0, 0.399763 ), 0.0, 0.0, 0, 0, Vector2( 1, 1 ), 0.0, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=3] flags = 4 width = 2048 curve = SubResource( 2 ) [sub_resource type="ParticlesMaterial" id=4] render_priority = 0 trail_divisor = 1 emission_shape = 1 emission_sphere_radius = 24.0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 120.0 flatness = 0.0 gravity = Vector3( 0, 500, 0 ) initial_velocity = 200.0 initial_velocity_random = 0.6 angular_velocity = 0.0 angular_velocity_random = 0.0 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = 0.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 100.0 tangential_accel_random = 0.0 damping = 0.0 damping_random = 0.0 angle = 0.0 angle_random = 0.0 scale = 0.06 scale_random = 0.0 scale_curve = SubResource( 3 ) color_ramp = SubResource( 1 ) hue_variation = 0.0 hue_variation_random = 0.0 anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 0.0 anim_offset_random = 0.0 anim_loop = false _sections_unfolded = [ "Color", "Gravity", "Scale", "Tangential Accel" ] [sub_resource type="GradientTexture" id=5] flags = 4 gradient = ExtResource( 6 ) width = 2048 [sub_resource type="ParticlesMaterial" id=6] render_priority = 0 trail_divisor = 1 emission_shape = 1 emission_sphere_radius = 24.0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 120.0 flatness = 0.0 gravity = Vector3( 0, 450, 0 ) initial_velocity = 200.0 initial_velocity_random = 0.6 angular_velocity = 0.0 angular_velocity_random = 0.0 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = 0.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 100.0 tangential_accel_random = 0.0 damping = 0.0 damping_random = 0.0 angle = 0.0 angle_random = 0.0 scale = 0.08 scale_random = 0.0 scale_curve = SubResource( 3 ) color_ramp = SubResource( 5 ) hue_variation = 0.0 hue_variation_random = 0.0 anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 0.0 anim_offset_random = 0.0 anim_loop = false _sections_unfolded = [ "Color", "Gravity", "Scale" ] [node name="FireballParticles" type="Particles2D" index="0"] emitting = true amount = 300 lifetime = 0.4 one_shot = false preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.0 randomness = 0.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -400, -400, 800, 800 ) local_coords = false draw_order = 1 process_material = ExtResource( 1 ) texture = ExtResource( 2 ) normal_map = null h_frames = 2 v_frames = 1 script = ExtResource( 3 ) _sections_unfolded = [ "Process Material", "Time", "Transform" ] active = true [node name="SmallSparkles" type="Particles2D" parent="." index="0"] rotation = -1.61079 emitting = true amount = 40 lifetime = 0.6 one_shot = false preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.2 randomness = 1.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -400, -400, 800, 800 ) local_coords = false draw_order = 0 process_material = SubResource( 4 ) texture = ExtResource( 5 ) normal_map = null h_frames = 1 v_frames = 1 _sections_unfolded = [ "Drawing", "Process Material", "Textures", "Time" ] [node name="TinySparkles" type="Particles2D" parent="." index="1"] rotation = -1.61079 emitting = true amount = 60 lifetime = 0.6 one_shot = false preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.2 randomness = 1.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -400, -400, 800, 800 ) local_coords = false draw_order = 0 process_material = SubResource( 6 ) texture = ExtResource( 2 ) normal_map = null h_frames = 2 v_frames = 1 _sections_unfolded = [ "Drawing", "Process Material", "Textures", "Time" ] ================================================ FILE: core/inventory/items/usable/scroll_fireball/fireball/particles/ParticlesToggle.gd ================================================ tool extends Particles2D export(bool) var active = true setget set_active func set_active(value): active = value emitting = value for child in get_children(): if not child.get_class() == "Particles2D": continue child.emitting = value ================================================ FILE: core/inventory/items/usable/scroll_fireball/fireball/particles/assets/gradient_ramps/fire_to_black.tres ================================================ [gd_resource type="Gradient" format=2] [resource] offsets = PoolRealArray( 0, 0.00682594, 0.0887372, 0.395904, 0.915601, 1 ) colors = PoolColorArray( 1, 0.773438, 0, 0, 1, 0.755566, 0, 0.381278, 1, 0.726563, 0, 1, 1, 0.304688, 0, 1, 0.160156, 0.115112, 0.115112, 1, 0, 0, 0, 0 ) ================================================ FILE: core/inventory/items/usable/scroll_fireball/fireball/particles/assets/gradient_ramps/sparkles.tres ================================================ [gd_resource type="Gradient" format=2] [resource] offsets = PoolRealArray( 0, 0.0613811, 0.84399, 1 ) colors = PoolColorArray( 1, 0.846985, 0.148438, 0, 1, 0.820313, 0, 1, 1, 0.398438, 0, 1, 0.964844, 0, 0, 0 ) ================================================ FILE: core/inventory/items/usable/scroll_fireball/fireball/particles/assets/gradient_ramps/sparkles_small.tres ================================================ [gd_resource type="Gradient" format=2] [resource] offsets = PoolRealArray( 0, 0.0971867, 0.751918, 1 ) colors = PoolColorArray( 0.980469, 0.878616, 0.413635, 0, 1, 0.820313, 0, 1, 1, 0.257813, 0, 1, 0, 0, 0, 0 ) ================================================ FILE: core/inventory/items/usable/scroll_fireball/fireball/particles/explosions/Explosion.gd ================================================ extends Particles2D func _ready(): one_shot = true $SmallSparkles.one_shot = true get_tree().create_timer(lifetime * 2.0).connect('timeout', self, 'queue_free') ================================================ FILE: core/inventory/items/usable/scroll_fireball/fireball/particles/explosions/Explosion.tscn ================================================ [gd_scene load_steps=16 format=2] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/fireball/particles/assets/gradient_ramps/fire_to_black.tres" type="Gradient" id=1] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/fireball/particles/sprites/smoke_clouds.png" type="Texture" id=2] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/fireball/particles/explosions/Explosion.gd" type="Script" id=3] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/fireball/particles/assets/gradient_ramps/sparkles.tres" type="Gradient" id=4] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/fireball/particles/sprites/circle.png" type="Texture" id=5] [sub_resource type="GradientTexture" id=1] flags = 4 gradient = ExtResource( 1 ) width = 2048 [sub_resource type="Curve" id=2] min_value = -0.2 max_value = 0.2 bake_resolution = 100 _data = [ Vector2( 0, 0.0277257 ), 0.0, 0.0, 0, 0, Vector2( 1, -0.0310864 ), 0.0, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=3] flags = 4 width = 2048 curve = SubResource( 2 ) [sub_resource type="Curve" id=4] min_value = 0.0 max_value = 1.0 bake_resolution = 100 _data = [ Vector2( 0, 0.166992 ), 0.0, 1.80027, 0, 0, Vector2( 1, 1 ), 0.121391, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=5] flags = 4 width = 2048 curve = SubResource( 4 ) [sub_resource type="ParticlesMaterial" id=6] render_priority = 0 trail_divisor = 1 emission_shape = 0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 180.0 flatness = 0.0 gravity = Vector3( 0, 1200, 0 ) initial_velocity = 600.0 initial_velocity_random = 0.6 angular_velocity = 180.0 angular_velocity_random = 0.6 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = 0.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 0.0 tangential_accel_random = 0.0 damping = 0.0 damping_random = 0.0 angle = 360.0 angle_random = 1.0 scale = 0.4 scale_random = 1.0 scale_curve = SubResource( 5 ) color_ramp = SubResource( 1 ) hue_variation = 0.0 hue_variation_random = 0.0 hue_variation_curve = SubResource( 3 ) anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 1.0 anim_offset_random = 1.0 anim_loop = false _sections_unfolded = [ "Spread" ] [sub_resource type="GradientTexture" id=7] flags = 4 gradient = ExtResource( 4 ) width = 2048 [sub_resource type="Curve" id=8] min_value = 0.0 max_value = 1.0 bake_resolution = 100 _data = [ Vector2( 0, 0.399763 ), 0.0, 0.0, 0, 0, Vector2( 1, 1 ), 0.0, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=9] flags = 4 width = 2048 curve = SubResource( 8 ) [sub_resource type="ParticlesMaterial" id=10] render_priority = 0 trail_divisor = 1 emission_shape = 1 emission_sphere_radius = 24.0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 60.0 flatness = 0.0 gravity = Vector3( 0, 1200, 0 ) initial_velocity = 800.0 initial_velocity_random = 0.6 angular_velocity = 0.0 angular_velocity_random = 0.0 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = 0.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 100.0 tangential_accel_random = 0.0 damping = 0.0 damping_random = 0.0 angle = 0.0 angle_random = 0.0 scale = 0.04 scale_random = 0.04 scale_curve = SubResource( 9 ) color_ramp = SubResource( 7 ) hue_variation = 0.0 hue_variation_random = 0.0 anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 0.0 anim_offset_random = 0.0 anim_loop = false _sections_unfolded = [ "Emission Shape", "Initial Velocity", "Orbit Velocity", "Scale" ] [node name="Explosion" type="Particles2D"] rotation = -1.5708 z_index = 20 emitting = true amount = 80 lifetime = 0.8 one_shot = false preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.8 randomness = 1.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -400, -400, 800, 800 ) local_coords = false draw_order = 0 process_material = SubResource( 6 ) texture = ExtResource( 2 ) normal_map = null h_frames = 2 v_frames = 1 script = ExtResource( 3 ) _sections_unfolded = [ "Drawing", "Process Material", "Time", "Transform", "Z Index" ] [node name="SmallSparkles" type="Particles2D" parent="." index="0"] rotation = 0.00504816 emitting = true amount = 80 lifetime = 0.8 one_shot = false preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.8 randomness = 1.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -400, -400, 800, 800 ) local_coords = false draw_order = 0 process_material = SubResource( 10 ) texture = ExtResource( 5 ) normal_map = null h_frames = 1 v_frames = 1 _sections_unfolded = [ "Drawing", "Process Material", "Time" ] ================================================ FILE: core/inventory/items/usable/scroll_fireball/fireball/particles/sprites/circle.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/circle.png-3a0701102b0b6f1dc869953be140b137.stex" metadata={ "vram_texture": false } [deps] source_file="res://core/inventory/items/usable/scroll_fireball/fireball/particles/sprites/circle.png" dest_files=[ "res://.import/circle.png-3a0701102b0b6f1dc869953be140b137.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: core/inventory/items/usable/scroll_fireball/fireball/particles/sprites/smoke_clouds.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/smoke_clouds.png-75a81e90df68496c912ffb2365928e06.stex" metadata={ "vram_texture": false } [deps] source_file="res://core/inventory/items/usable/scroll_fireball/fireball/particles/sprites/smoke_clouds.png" dest_files=[ "res://.import/smoke_clouds.png-75a81e90df68496c912ffb2365928e06.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: core/save/SaveAndLoad.gd ================================================ extends Node signal game_saved(id) signal game_loaded(id) onready var GAME_VERSION = ProjectSettings.get_setting("application/config/version") var SAVE_DIRECTORY = "res://save/" if ProjectSettings.get_setting("application/config/debug") else "res://user/" const SAVE_FILE_EXT = ".game" func save_game(id): var save_data = { "version": GAME_VERSION, "data": [] } # Get nodes in group works in tree order, from top to bottom # So we are guaranteed to get the parent first for node in get_tree().get_nodes_in_group("save"): var node_save_data = node.get_save_data() assert(node_save_data["filename"] != "") assert(node_save_data["parent"] != "") save_data["data"].append(node_save_data) var directory = Directory.new() if not directory.dir_exists(SAVE_DIRECTORY): directory.make_dir_recursive(SAVE_DIRECTORY) var path = get_save_file_path(id) var file = File.new() file.open(path, File.WRITE) file.store_string(to_json(save_data)) file.close() emit_signal("game_saved", id) func load_game(id): var path = get_save_file_path(id) var file = File.new() if not file.file_exists(path): print("Couldn't load: file %s does not exist." % path) return file.open(path, File.READ) var save_data = parse_json(file.get_as_text()) file.close() for node in get_tree().get_nodes_in_group("save"): node.queue_free() for node_data in save_data["data"]: var node = load(node_data["filename"]).instance() get_node(node_data["parent"]).add_child(node) var properties = node_data["properties"] for property in properties.keys(): var value if is_vector_2(property, node): value = parse_vector_2(properties[property]) else: value = properties[property] node.set(property, value) emit_signal("game_loaded", id) func get_save_file_path(id): return SAVE_DIRECTORY + str(id) + SAVE_FILE_EXT func is_vector_2(property_name, node): return typeof(node.get(property_name)) == typeof(Vector2()) func parse_vector_2(json_string): var numbers_string = json_string.substr(1, len(json_string) - 2) var comma_position = numbers_string.find(",") var value_x = float(numbers_string.left(comma_position)) var value_y = float(numbers_string.right(comma_position + 1)) return Vector2(value_x, value_y) ================================================ FILE: core/save/SaveAndLoad.tscn ================================================ [gd_scene load_steps=2 format=2] [ext_resource path="res://SaveAndLoad.gd" type="Script" id=1] [node name="SaveAndLoad" type="Node" index="0"] script = ExtResource( 1 ) ================================================ FILE: core/shop/Shop.gd ================================================ extends Node export(bool) var STOCK_INFINITE = false export(bool) var MONEY_INFINITE = false export(int) var MAX_TRANSACTION_COUNT = 100 export(float, 0.0, 1.0) var BUY_MULTIPLIER = 0.25 onready var inventory = $Inventory onready var purse = $Purse func _ready(): assert(inventory != null) func buy_from(actor, item, amount=1): amount = clamp(amount, 1, MAX_TRANSACTION_COUNT) var transaction_value = max(get_buy_value(item) * amount, purse.coins) actor.get_node("Inventory").trash(item, amount) actor.get_node("Purse").add_coins(transaction_value) if not STOCK_INFINITE: inventory.add(item, amount) if not MONEY_INFINITE: purse.remove_coins(transaction_value) func sell_to(actor, item, amount=1): amount = clamp(amount, 1, MAX_TRANSACTION_COUNT) var transaction_value = item.price * amount actor.get_node("Purse").remove_coins(item.price * amount) actor.get_node("Inventory").add(item, amount) if not STOCK_INFINITE: inventory.trash(item, amount) if MONEY_INFINITE: return purse.add_coins(item.price * amount) func get_buy_value(item): return round(item.price * BUY_MULTIPLIER) func get_purse(): return purse ================================================ FILE: core/shop/Shop.tscn ================================================ [gd_scene load_steps=7 format=2] [ext_resource path="res://core/shop/Shop.gd" type="Script" id=1] [ext_resource path="res://core/inventory/Inventory.tscn" type="PackedScene" id=2] [ext_resource path="res://core/inventory/items/equipment/sword/Sword.tscn" type="PackedScene" id=3] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/FireballScroll.tscn" type="PackedScene" id=4] [ext_resource path="res://core/inventory/items/usable/potions/restore_health/StrongHealthPotion.tscn" type="PackedScene" id=5] [ext_resource path="res://core/shop/purse/Purse.tscn" type="PackedScene" id=6] [node name="Shop" type="Node"] editor/display_folded = true script = ExtResource( 1 ) STOCK_INFINITE = false MONEY_INFINITE = false MAX_TRANSACTION_COUNT = 100 BUY_MULTIPLIER = 0.25 [node name="Inventory" parent="." index="0" instance=ExtResource( 2 )] [node name="Sword" parent="Inventory" index="0" instance=ExtResource( 3 )] amount = 6 [node name="FireballScroll" parent="Inventory" index="1" instance=ExtResource( 4 )] [node name="StrongHealthPotion" parent="Inventory" index="2" instance=ExtResource( 5 )] [node name="Purse" parent="." index="1" instance=ExtResource( 6 )] MAXIMUM = 1000000 ================================================ FILE: core/shop/purse/Purse.gd ================================================ extends Node signal coins_changed(coins) export(int) var coins = 0 export(int) var MAXIMUM = 1000000 func has_coins(amount): return coins >= amount func add_coins(amount): coins = min(coins + amount, MAXIMUM) emit_signal("coins_changed", coins) func remove_coins(amount): if not has_coins(amount): return coins = max(0, coins - amount) emit_signal("coins_changed", coins) ================================================ FILE: core/shop/purse/Purse.tscn ================================================ [gd_scene load_steps=2 format=2] [ext_resource path="res://core/shop/purse/Purse.gd" type="Script" id=1] [node name="Purse" type="Node" index="0"] script = ExtResource( 1 ) coins = 0 ================================================ FILE: core/world/Door.gd ================================================ extends Area2D signal player_entered(map_path) export(String, FILE, "*.tscn") var map_path var PlayerController = preload("res://actors/player/PlayerController.gd") export(bool) var ACTIVE_AT_START = true func _ready(): set_active(ACTIVE_AT_START) assert(map_path != "") func _on_body_entered(body): if not body is PlayerController: return emit_signal("player_entered", map_path) func set_active(value): visible = value $CollisionShape2D.disabled = not value ================================================ FILE: core/world/Door.tscn ================================================ [gd_scene load_steps=4 format=2] [ext_resource path="res://core/world/Door.gd" type="Script" id=1] [ext_resource path="res://core/world/stairs.png" type="Texture" id=2] [sub_resource type="RectangleShape2D" id=1] custom_solver_bias = 0.0 extents = Vector2( 66, 58.7724 ) [node name="Door" type="Area2D" index="0" groups=[ "doors", ]] input_pickable = false gravity_vec = Vector2( 0, 1 ) gravity = 98.0 linear_damp = 0.1 angular_damp = 1.0 collision_layer = 8 collision_mask = 3 audio_bus_override = false audio_bus_name = "Master" script = ExtResource( 1 ) _sections_unfolded = [ "Visibility" ] map_path = null [node name="Stairs" type="Sprite" parent="." index="0"] position = Vector2( 1, -24.0106 ) texture = ExtResource( 2 ) [node name="CollisionShape2D" type="CollisionShape2D" parent="." index="1"] position = Vector2( -3, -16.2276 ) shape = SubResource( 1 ) [connection signal="body_entered" from="." to="." method="_on_body_entered"] ================================================ FILE: core/world/Gap.gd ================================================ extends Area2D func _on_body_entered(body): if not body.has_method('fall'): return body.fall($CollisionShape2D.shape.extents) ================================================ FILE: core/world/Gap.tscn ================================================ [gd_scene load_steps=4 format=2] [ext_resource path="res://core/world/Gap.gd" type="Script" id=1] [ext_resource path="res://core/world/pit.png" type="Texture" id=2] [sub_resource type="RectangleShape2D" id=1] custom_solver_bias = 0.0 extents = Vector2( 50, 30 ) [node name="Gap" type="Area2D" groups=[ "environment", "gap", ]] input_pickable = false gravity_vec = Vector2( 0, 1 ) gravity = 98.0 linear_damp = 0.1 angular_damp = 1.0 monitorable = false collision_layer = 2 audio_bus_override = false audio_bus_name = "Master" script = ExtResource( 1 ) _sections_unfolded = [ "Collision" ] [node name="Gap" type="Sprite" parent="." index="0"] position = Vector2( 1, -24.0106 ) texture = ExtResource( 2 ) [node name="CollisionShape2D" type="CollisionShape2D" parent="." index="1"] position = Vector2( 1, -24.2276 ) shape = SubResource( 1 ) [connection signal="body_entered" from="." to="." method="_on_body_entered"] ================================================ FILE: core/world/PlayerSpawningPoint.tscn ================================================ [gd_scene load_steps=2 format=2] [sub_resource type="GDScript" id=1] script/source = "tool extends Position2D export(float) var RADIUS = 100.0 export(int) var EDGES = 32 export(Color) var LINE_COLOR = Color(\"#ffffff\") func _ready(): set_as_toplevel(true) func _draw(): if not Engine.editor_hint: return var points = PoolVector2Array() var angle_step = PI * 2 / EDGES for i in range(EDGES + 1): var point = Vector2( cos(angle_step * i) * RADIUS, sin(angle_step * i) * RADIUS ) points.append(point) draw_polyline(points, LINE_COLOR, 4.0) " [node name="PlayerSpawningPoint" type="Position2D" index="0"] script = SubResource( 1 ) RADIUS = 100.0 EDGES = 16 LINE_COLOR = Color( 0.921875, 0.154846, 0.766072, 1 ) ================================================ FILE: core/world/Rock.tscn ================================================ [gd_scene load_steps=4 format=2] [ext_resource path="res://core/world/rock.png" type="Texture" id=1] [sub_resource type="RectangleShape2D" id=1] custom_solver_bias = 0.0 extents = Vector2( 23.4314, 15.2998 ) [sub_resource type="RectangleShape2D" id=2] custom_solver_bias = 0.0 extents = Vector2( 44.0727, 26.1865 ) [node name="Rock" type="StaticBody2D" groups=[ "environment", ]] input_pickable = false collision_layer = 2 collision_mask = 1 constant_linear_velocity = Vector2( 0, 0 ) constant_angular_velocity = 0.0 friction = 1.0 bounce = 0.0 _sections_unfolded = [ "Collision" ] [node name="rock" type="Sprite" parent="." index="0"] position = Vector2( 12.0737, 1.98891 ) texture = ExtResource( 1 ) [node name="CollisionShape2D" type="CollisionShape2D" parent="." index="1"] position = Vector2( 43.7353, 34.2526 ) shape = SubResource( 1 ) [node name="CollisionShape2D2" type="CollisionShape2D" parent="." index="2"] position = Vector2( -1.99999, -6.48269 ) shape = SubResource( 2 ) ================================================ FILE: core/world/pit.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/pit.png-5ec5084f4b0d321ced939a029f9e9f2b.stex" metadata={ "vram_texture": false } [deps] source_file="res://core/world/pit.png" dest_files=[ "res://.import/pit.png-5ec5084f4b0d321ced939a029f9e9f2b.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: core/world/rock.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/rock.png-d90c7ea6986b7d7efafc6116d7469b11.stex" metadata={ "vram_texture": false } [deps] source_file="res://core/world/rock.png" dest_files=[ "res://.import/rock.png-d90c7ea6986b7d7efafc6116d7469b11.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: core/world/stairs.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/stairs.png-459082f78726e41c4edb789b8d018960.stex" metadata={ "vram_texture": false } [deps] source_file="res://core/world/stairs.png" dest_files=[ "res://.import/stairs.png-459082f78726e41c4edb789b8d018960.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: core/world/tilesets/cave/cave.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/cave.png-7421b3ea2eb0cd51e25cb4e00e5ffa5c.stex" metadata={ "vram_texture": false } [deps] source_file="res://core/world/tilesets/cave/cave.png" dest_files=[ "res://.import/cave.png-7421b3ea2eb0cd51e25cb4e00e5ffa5c.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: core/world/tilesets/cave/cave.tres ================================================ [gd_resource type="TileSet" load_steps=14 format=2] [ext_resource path="res://core/world/tilesets/cave/cave.png" type="Texture" id=1] [sub_resource type="ConvexPolygonShape2D" id=1] custom_solver_bias = 0.0 points = PoolVector2Array( 0, 0, 128, 0, 128, 128, 0, 128 ) [sub_resource type="ConvexPolygonShape2D" id=2] custom_solver_bias = 0.0 points = PoolVector2Array( 0, 0, 128, 0, 128, 128, 0, 128 ) [sub_resource type="ConvexPolygonShape2D" id=3] custom_solver_bias = 0.0 points = PoolVector2Array( 0, 0, 128, 0, 128, 128, 0, 128 ) [sub_resource type="ConvexPolygonShape2D" id=4] custom_solver_bias = 0.0 points = PoolVector2Array( 0, 0, 128, 0, 128, 128, 128, 128, 0, 128 ) [sub_resource type="ConvexPolygonShape2D" id=5] custom_solver_bias = 0.0 points = PoolVector2Array( 0, 0, 128, 0, 128, 128, 0, 128 ) [sub_resource type="ConvexPolygonShape2D" id=6] custom_solver_bias = 0.0 points = PoolVector2Array( 0, 0, 128, 0, 128, 128, 0, 128 ) [sub_resource type="ConvexPolygonShape2D" id=7] custom_solver_bias = 0.0 points = PoolVector2Array( 0, 0, 128, 0, 128, 128, 0, 128 ) [sub_resource type="ConvexPolygonShape2D" id=8] custom_solver_bias = 0.0 points = PoolVector2Array( 0, 0, 128, 0, 128, 128, 0, 128 ) [sub_resource type="ConvexPolygonShape2D" id=9] custom_solver_bias = 0.0 points = PoolVector2Array( 0, 0, 128, 0, 128, 128, 0, 128 ) [sub_resource type="ConvexPolygonShape2D" id=10] custom_solver_bias = 0.0 points = PoolVector2Array( 0, 0, 128, 0, 128, 128, 0, 128 ) [sub_resource type="ConvexPolygonShape2D" id=11] custom_solver_bias = 0.0 points = PoolVector2Array( 0, 0, 128, 0, 128, 128, 0, 128 ) [sub_resource type="ConvexPolygonShape2D" id=12] custom_solver_bias = 0.0 points = PoolVector2Array( 0, 0, 128, 0, 128, 128, 0, 128 ) [resource] 0/name = "cave" 0/texture = ExtResource( 1 ) 0/tex_offset = Vector2( 0, 0 ) 0/modulate = Color( 1, 1, 1, 1 ) 0/region = Rect2( 0, 0, 640, 384 ) 0/is_autotile = true 0/autotile/bitmask_mode = 0 0/autotile/icon_coordinate = Vector2( 0, 0 ) 0/autotile/tile_size = Vector2( 128, 128 ) 0/autotile/spacing = 0 0/autotile/bitmask_flags = [ Vector2( 0, 0 ), 256, Vector2( 0, 1 ), 260, Vector2( 0, 2 ), 4, Vector2( 1, 0 ), 320, Vector2( 1, 1 ), 325, Vector2( 1, 2 ), 5, Vector2( 2, 0 ), 64, Vector2( 2, 1 ), 65, Vector2( 2, 2 ), 1, Vector2( 3, 0 ), 69, Vector2( 3, 1 ), 321, Vector2( 4, 0 ), 261, Vector2( 4, 1 ), 324 ] 0/autotile/occluder_map = [ ] 0/autotile/navpoly_map = [ ] 0/autotile/priority_map = [ ] 0/occluder_offset = Vector2( 320, 192 ) 0/navigation_offset = Vector2( 320, 192 ) 0/shapes = [ { "autotile_coord": Vector2( 0, 0 ), "one_way": false, "shape": SubResource( 1 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 1, 0 ), "one_way": false, "shape": SubResource( 2 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 2, 0 ), "one_way": false, "shape": SubResource( 3 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 2, 1 ), "one_way": false, "shape": SubResource( 4 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 2, 2 ), "one_way": false, "shape": SubResource( 5 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 1, 2 ), "one_way": false, "shape": SubResource( 6 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 0, 2 ), "one_way": false, "shape": SubResource( 7 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 0, 1 ), "one_way": false, "shape": SubResource( 8 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 3, 0 ), "one_way": false, "shape": SubResource( 9 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 4, 0 ), "one_way": false, "shape": SubResource( 10 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 3, 1 ), "one_way": false, "shape": SubResource( 11 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 4, 1 ), "one_way": false, "shape": SubResource( 12 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) } ] _sections_unfolded = [ "0" ] ================================================ FILE: core/world/tilesets/cave/cave_tileset_src.tscn ================================================ [gd_scene load_steps=2 format=2] [ext_resource path="res://core/world/tilesets/cave/cave.png" type="Texture" id=1] [node name="Node2D" type="Node2D" index="0"] [node name="cave" type="Sprite" parent="." index="0"] position = Vector2( 322.14, 192 ) texture = ExtResource( 1 ) region_enabled = true region_rect = Rect2( 0, 0, 640, 384 ) _sections_unfolded = [ "Region" ] ================================================ FILE: core/world/tilesets/outdoor/outdoor.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/outdoor.png-1eb405fc65af37f625e19d928044f95c.stex" metadata={ "vram_texture": false } [deps] source_file="res://core/world/tilesets/outdoor/outdoor.png" dest_files=[ "res://.import/outdoor.png-1eb405fc65af37f625e19d928044f95c.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: core/world/tilesets/outdoor/outdoor.tres ================================================ [gd_resource type="TileSet" load_steps=18 format=2] [ext_resource path="res://core/world/tilesets/outdoor/outdoor.png" type="Texture" id=1] [ext_resource path="res://core/world/tilesets/outdoor/pit.png" type="Texture" id=2] [sub_resource type="ConvexPolygonShape2D" id=1] custom_solver_bias = 0.0 points = PoolVector2Array( -48, 16, -48, -48, 24, -48, 24, 8, 8, 16 ) [sub_resource type="ConvexPolygonShape2D" id=2] custom_solver_bias = 0.0 points = PoolVector2Array( 24, 8, 48, 8, 48, 40, 8, 40, 8, 16 ) [sub_resource type="ConvexPolygonShape2D" id=3] custom_solver_bias = 0.0 points = PoolVector2Array( 80, 128, 80, 96, 96, 80, 128, 80, 128, 128 ) [sub_resource type="ConvexPolygonShape2D" id=4] custom_solver_bias = 0.0 points = PoolVector2Array( 0, 80, 32, 80, 48, 96, 48, 128, 0, 128 ) [sub_resource type="ConvexPolygonShape2D" id=5] custom_solver_bias = 0.0 points = PoolVector2Array( 48, 0, 48, 128, 0, 128, 0, 0 ) [sub_resource type="ConvexPolygonShape2D" id=6] custom_solver_bias = 0.0 points = PoolVector2Array( 0, 0, 48, 0, 48, 32, 32, 48, 0, 48 ) [sub_resource type="ConvexPolygonShape2D" id=7] custom_solver_bias = 0.0 points = PoolVector2Array( 128, 0, 128, 48, 0, 48, 0, 0 ) [sub_resource type="ConvexPolygonShape2D" id=8] custom_solver_bias = 0.0 points = PoolVector2Array( 128, 48, 96, 48, 80, 32, 80, 0, 128, 0 ) [sub_resource type="ConvexPolygonShape2D" id=9] custom_solver_bias = 0.0 points = PoolVector2Array( 80, 128, 80, 0, 128, 0, 128, 128 ) [sub_resource type="ConvexPolygonShape2D" id=10] custom_solver_bias = 0.0 points = PoolVector2Array( 0, 0, 128, 0, 128, 128, 0, 128 ) [sub_resource type="ConvexPolygonShape2D" id=11] custom_solver_bias = 0.0 points = PoolVector2Array( 0, 80, 128, 80, 128, 128, 0, 128 ) [sub_resource type="ConvexPolygonShape2D" id=12] custom_solver_bias = 0.0 points = PoolVector2Array( 128, 0, 128, 128, 0, 128, 0, 80, 80, 80, 80, 0 ) [sub_resource type="ConvexPolygonShape2D" id=13] custom_solver_bias = 0.0 points = PoolVector2Array( 0, 128, 0, 112, 0, 0, 128, 0, 128, 48, 48, 48, 48, 128 ) [sub_resource type="ConvexPolygonShape2D" id=14] custom_solver_bias = 0.0 points = PoolVector2Array( 0, 0, 128, 0, 128, 128, 80, 128, 80, 48, 0, 48 ) [sub_resource type="ConvexPolygonShape2D" id=15] custom_solver_bias = 0.0 points = PoolVector2Array( 48, 0, 48, 80, 128, 80, 128, 128, 0, 128, 0, 0 ) [resource] 0/name = "grass" 0/texture = ExtResource( 1 ) 0/tex_offset = Vector2( 0, 0 ) 0/modulate = Color( 1, 1, 1, 1 ) 0/region = Rect2( 0, 0, 384, 256 ) 0/is_autotile = true 0/autotile/bitmask_mode = 0 0/autotile/icon_coordinate = Vector2( 0, 1 ) 0/autotile/tile_size = Vector2( 128, 128 ) 0/autotile/spacing = 0 0/autotile/bitmask_flags = [ Vector2( 0, 0 ), 325, Vector2( 0, 1 ), 325, Vector2( 1, 0 ), 325, Vector2( 2, 0 ), 325 ] 0/autotile/occluder_map = [ ] 0/autotile/navpoly_map = [ ] 0/autotile/priority_map = [ Vector3( 0, 1, 35 ) ] 0/occluder_offset = Vector2( 192, 128 ) 0/navigation_offset = Vector2( 192, 128 ) 0/shapes = [ ] 1/name = "dirt" 1/texture = ExtResource( 1 ) 1/tex_offset = Vector2( 0, 0 ) 1/modulate = Color( 1, 1, 1, 1 ) 1/region = Rect2( 384, 0, 640, 512 ) 1/is_autotile = true 1/autotile/bitmask_mode = 0 1/autotile/icon_coordinate = Vector2( 1, 1 ) 1/autotile/tile_size = Vector2( 128, 128 ) 1/autotile/spacing = 0 1/autotile/bitmask_flags = [ Vector2( 0, 0 ), 256, Vector2( 0, 1 ), 260, Vector2( 0, 2 ), 4, Vector2( 0, 3 ), 325, Vector2( 1, 0 ), 320, Vector2( 1, 1 ), 325, Vector2( 1, 2 ), 5, Vector2( 1, 3 ), 325, Vector2( 2, 0 ), 64, Vector2( 2, 1 ), 65, Vector2( 2, 2 ), 1, Vector2( 2, 3 ), 325, Vector2( 3, 0 ), 69, Vector2( 3, 1 ), 321, Vector2( 3, 2 ), 257, Vector2( 3, 3 ), 68, Vector2( 4, 0 ), 261, Vector2( 4, 1 ), 324, Vector2( 4, 2 ), 68, Vector2( 4, 3 ), 257 ] 1/autotile/occluder_map = [ ] 1/autotile/navpoly_map = [ ] 1/autotile/priority_map = [ Vector3( 0, 3, 2 ), Vector3( 1, 1, 48 ) ] 1/occluder_offset = Vector2( 320, 256 ) 1/navigation_offset = Vector2( 320, 256 ) 1/shapes = [ ] 2/name = "rock" 2/texture = ExtResource( 1 ) 2/tex_offset = Vector2( 0, 0 ) 2/modulate = Color( 1, 1, 1, 1 ) 2/region = Rect2( 256, 384, 128, 128 ) 2/is_autotile = false 2/occluder_offset = Vector2( 64, 64 ) 2/navigation_offset = Vector2( 64, 64 ) 2/shapes = [ { "autotile_coord": Vector2( 0, 0 ), "one_way": false, "shape": SubResource( 1 ), "shape_transform": Transform2D( 1, 0, 0, 1, 64, 64 ) }, { "autotile_coord": Vector2( 0, 0 ), "one_way": false, "shape": SubResource( 2 ), "shape_transform": Transform2D( 1, 0, 0, 1, 64, 64 ) } ] 3/name = "outdoor" 3/texture = ExtResource( 1 ) 3/tex_offset = Vector2( 0, 0 ) 3/modulate = Color( 1, 1, 1, 1 ) 3/region = Rect2( 0, 0, 384, 256 ) 3/is_autotile = false 3/occluder_offset = Vector2( 192, 128 ) 3/navigation_offset = Vector2( 192, 128 ) 3/shapes = [ ] 4/name = "bush" 4/texture = ExtResource( 1 ) 4/tex_offset = Vector2( 0, 0 ) 4/modulate = Color( 1, 1, 1, 1 ) 4/region = Rect2( 0, 512, 1024, 384 ) 4/is_autotile = true 4/autotile/bitmask_mode = 1 4/autotile/icon_coordinate = Vector2( 1, 1 ) 4/autotile/tile_size = Vector2( 128, 128 ) 4/autotile/spacing = 0 4/autotile/bitmask_flags = [ Vector2( 0, 0 ), 176, Vector2( 0, 1 ), 146, Vector2( 0, 2 ), 50, Vector2( 1, 0 ), 56, Vector2( 1, 1 ), 16, Vector2( 1, 2 ), 56, Vector2( 2, 0 ), 152, Vector2( 2, 1 ), 146, Vector2( 2, 2 ), 26, Vector2( 3, 0 ), 144, Vector2( 3, 1 ), 18, Vector2( 3, 2 ), 48, Vector2( 4, 0 ), 178, Vector2( 4, 1 ), 184, Vector2( 4, 2 ), 24, Vector2( 5, 0 ), 154, Vector2( 5, 1 ), 58, Vector2( 5, 2 ), 186, Vector2( 6, 0 ), 176, Vector2( 6, 1 ), 50, Vector2( 7, 0 ), 152, Vector2( 7, 1 ), 26 ] 4/autotile/occluder_map = [ ] 4/autotile/navpoly_map = [ ] 4/autotile/priority_map = [ ] 4/occluder_offset = Vector2( 512, 192 ) 4/navigation_offset = Vector2( 512, 192 ) 4/shapes = [ ] 5/name = "pit" 5/texture = ExtResource( 2 ) 5/tex_offset = Vector2( 0, 0 ) 5/modulate = Color( 1, 1, 1, 1 ) 5/region = Rect2( 0, 0, 640, 384 ) 5/is_autotile = true 5/autotile/bitmask_mode = 0 5/autotile/icon_coordinate = Vector2( 1, 1 ) 5/autotile/tile_size = Vector2( 128, 128 ) 5/autotile/spacing = 0 5/autotile/bitmask_flags = [ Vector2( 0, 0 ), 256, Vector2( 0, 1 ), 260, Vector2( 0, 2 ), 4, Vector2( 1, 0 ), 320, Vector2( 1, 1 ), 325, Vector2( 1, 2 ), 5, Vector2( 2, 0 ), 64, Vector2( 2, 1 ), 65, Vector2( 2, 2 ), 1, Vector2( 3, 0 ), 69, Vector2( 3, 1 ), 321, Vector2( 4, 0 ), 261, Vector2( 4, 1 ), 324 ] 5/autotile/occluder_map = [ ] 5/autotile/navpoly_map = [ ] 5/autotile/priority_map = [ ] 5/occluder_offset = Vector2( 320, 192 ) 5/navigation_offset = Vector2( 320, 192 ) 5/shapes = [ { "autotile_coord": Vector2( 0, 0 ), "one_way": false, "shape": SubResource( 3 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 2, 0 ), "one_way": false, "shape": SubResource( 4 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 2, 1 ), "one_way": false, "shape": SubResource( 5 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 2, 2 ), "one_way": false, "shape": SubResource( 6 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 1, 2 ), "one_way": false, "shape": SubResource( 7 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 0, 2 ), "one_way": false, "shape": SubResource( 8 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 0, 1 ), "one_way": false, "shape": SubResource( 9 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 1, 1 ), "one_way": false, "shape": SubResource( 10 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 1, 0 ), "one_way": false, "shape": SubResource( 11 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 4, 1 ), "one_way": false, "shape": SubResource( 12 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 3, 0 ), "one_way": false, "shape": SubResource( 13 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 4, 0 ), "one_way": false, "shape": SubResource( 14 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) }, { "autotile_coord": Vector2( 3, 1 ), "one_way": false, "shape": SubResource( 15 ), "shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 ) } ] _sections_unfolded = [ "5", "Resource" ] ================================================ FILE: core/world/tilesets/outdoor/outdoor.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://core/world/tilesets/outdoor/outdoor.png" type="Texture" id=1] [ext_resource path="res://core/world/tilesets/outdoor/pit.png" type="Texture" id=2] [node name="Outdoor" type="Node"] [node name="outdoor" type="Sprite" parent="." index="0"] position = Vector2( 192, 160 ) texture = ExtResource( 1 ) region_enabled = true region_rect = Rect2( 0, 0, 384, 256 ) _sections_unfolded = [ "Region" ] [node name="dirt" type="Sprite" parent="." index="1"] position = Vector2( 320, 576 ) texture = ExtResource( 1 ) region_enabled = true region_rect = Rect2( 384, 0, 640, 512 ) _sections_unfolded = [ "Region" ] [node name="bush" type="Sprite" parent="." index="2"] position = Vector2( 1200, 592 ) texture = ExtResource( 1 ) region_enabled = true region_rect = Rect2( 0, 512, 1024, 384 ) _sections_unfolded = [ "Region" ] [node name="rock" type="Sprite" parent="." index="3"] position = Vector2( 832, 192 ) texture = ExtResource( 1 ) region_enabled = true region_rect = Rect2( 256, 384, 128, 128 ) _sections_unfolded = [ "Region" ] [node name="StaticBody2D" type="StaticBody2D" parent="rock" index="0"] input_pickable = false collision_layer = 1 collision_mask = 1 constant_linear_velocity = Vector2( 0, 0 ) constant_angular_velocity = 0.0 friction = 1.0 bounce = 0.0 [node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="rock/StaticBody2D" index="0"] build_mode = 0 polygon = PoolVector2Array( 24, -48, 24, 8, 48, 8, 48, 40, 8, 40, 8, 16, -48, 16, -48, -48 ) [node name="pit" type="Sprite" parent="." index="4"] position = Vector2( 1056, 1024 ) texture = ExtResource( 2 ) ================================================ FILE: core/world/tilesets/outdoor/pit.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/pit.png-81c563e22c5b735099e3aed47ef25a25.stex" metadata={ "vram_texture": false } [deps] source_file="res://core/world/tilesets/outdoor/pit.png" dest_files=[ "res://.import/pit.png-81c563e22c5b735099e3aed47ef25a25.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: default_bus_layout.tres ================================================ [gd_resource type="AudioBusLayout" format=2] [resource] bus/0/name = "Master" bus/0/solo = false bus/0/mute = false bus/0/bypass_fx = false bus/0/volume_db = 0.0 bus/0/send = "" bus/1/name = "Music" bus/1/solo = false bus/1/mute = false bus/1/bypass_fx = false bus/1/volume_db = -4.8 bus/1/send = "Master" bus/2/name = "Sounds" bus/2/solo = false bus/2/mute = false bus/2/bypass_fx = false bus/2/volume_db = 0.0 bus/2/send = "LowPass" bus/3/name = "Interface" bus/3/solo = false bus/3/mute = false bus/3/bypass_fx = false bus/3/volume_db = 0.0 bus/3/send = "Master" ================================================ FILE: default_env.tres ================================================ [gd_resource type="Environment" load_steps=2 format=2] [sub_resource type="ProceduralSky" id=1] sky_top_color = Color( 0.0470588, 0.454902, 0.976471, 1 ) sky_horizon_color = Color( 0.556863, 0.823529, 0.909804, 1 ) sky_curve = 0.25 ground_bottom_color = Color( 0.101961, 0.145098, 0.188235, 1 ) ground_horizon_color = Color( 0.482353, 0.788235, 0.952941, 1 ) ground_curve = 0.01 sun_energy = 16.0 [resource] background_mode = 2 background_sky = SubResource( 1 ) ================================================ FILE: icon.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" metadata={ "vram_texture": false } [deps] source_file="res://icon.png" dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: interface/Interface.gd ================================================ extends CanvasLayer onready var shop_menu = $ShopMenu func _ready(): shop_menu.connect('closed', self, 'remove_child', [shop_menu]) remove_child(shop_menu) func initialize(player): $PlayerGUI.initialize(player.get_health_node(), player.get_purse()) $PauseMenu.initialize({'actor': player}) func _on_Level_loaded(level): var tree = get_tree() for seller in tree.get_nodes_in_group('seller'): seller.connect('shop_open_requested', self, 'shop_open') var monsters = tree.get_nodes_in_group('monster') var spawners = tree.get_nodes_in_group('monster_spawner') $LifebarsBuilder.initialize(monsters, spawners) func shop_open(seller_shop, buyer): add_child(shop_menu) shop_menu.open({'shop': seller_shop, 'buyer': buyer}) ================================================ FILE: interface/TopLevelUi.gd ================================================ tool extends Control func _ready(): set_as_toplevel(true) ================================================ FILE: interface/fonts/montserrat_black_48.tres ================================================ [gd_resource type="DynamicFont" load_steps=2 format=2] [ext_resource path="res://interface/fonts/montserrat_black.ttf" type="DynamicFontData" id=1] [resource] size = 48 use_mipmaps = true use_filter = false font_data = ExtResource( 1 ) _sections_unfolded = [ "Font", "Settings" ] ================================================ FILE: interface/fonts/source_code_pro_explanations.tres ================================================ [gd_resource type="DynamicFont" load_steps=2 format=2] [ext_resource path="res://interface/fonts/SourceCodePro-Bold.ttf" type="DynamicFontData" id=1] [resource] size = 18 use_mipmaps = false use_filter = true font_data = ExtResource( 1 ) _sections_unfolded = [ "Font", "Settings" ] ================================================ FILE: interface/fonts/source_code_pro_explanations_bold.tres ================================================ [gd_resource type="DynamicFont" load_steps=2 format=2] [ext_resource path="res://interface/fonts/SourceCodePro-Black.ttf" type="DynamicFontData" id=1] [resource] size = 24 use_mipmaps = false use_filter = true font_data = ExtResource( 1 ) _sections_unfolded = [ "Font", "Settings" ] ================================================ FILE: interface/gui/boss/BossLifebar.gd ================================================ tool extends Control export(String) var boss_name = "Boss Name" onready var bar = $Bar onready var anim_player = $AnimationPlayer func _ready(): set_as_toplevel(true) $Label.text = boss_name hide() func initialize(health_node): bar.max_value = health_node.max_health bar.value = health_node.health print(bar.value) health_node.connect('health_changed', self, '_on_Health_health_changed') func appear(): show() anim_player.play("appear") func disappear(): anim_player.play("disappear") yield(anim_player, "animation_finished") hide() func _on_Health_health_changed(value): bar.value = value ================================================ FILE: interface/gui/boss/BossLifebar.tscn ================================================ [gd_scene load_steps=7 format=2] [ext_resource path="res://interface/gui/boss/BossLifebar.gd" type="Script" id=1] [ext_resource path="res://interface/default.theme" type="Theme" id=2] [ext_resource path="res://interface/gui/boss/boss_bar_bg.png" type="Texture" id=3] [ext_resource path="res://interface/gui/boss/boss_bar_fill.png" type="Texture" id=4] [sub_resource type="Animation" id=1] resource_name = "appear" length = 1.0 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath("Label:self_modulate") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.5 ), "transitions": PoolRealArray( 1, 1 ), "update": 0, "values": [ Color( 1, 1, 1, 0 ), Color( 1, 1, 1, 1 ) ] } tracks/1/type = "value" tracks/1/path = NodePath("Bar:self_modulate") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0.2, 0.7 ), "transitions": PoolRealArray( 1, 1 ), "update": 0, "values": [ Color( 1, 1, 1, 0 ), Color( 1, 1, 1, 1 ) ] } tracks/2/type = "value" tracks/2/path = NodePath("Label:rect_position") tracks/2/interp = 1 tracks/2/loop_wrap = true tracks/2/imported = false tracks/2/enabled = true tracks/2/keys = { "times": PoolRealArray( 0, 0.5 ), "transitions": PoolRealArray( 0.356926, 1 ), "update": 0, "values": [ Vector2( -84, 0 ), Vector2( 0, 0 ) ] } tracks/3/type = "value" tracks/3/path = NodePath("Bar:rect_position") tracks/3/interp = 1 tracks/3/loop_wrap = true tracks/3/imported = false tracks/3/enabled = true tracks/3/keys = { "times": PoolRealArray( 0.2, 0.7 ), "transitions": PoolRealArray( 0.407274, 1 ), "update": 0, "values": [ Vector2( 104, 27 ), Vector2( 156, 27 ) ] } [sub_resource type="Animation" id=2] resource_name = "disappear" length = 0.8 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath("Label:self_modulate") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.7 ), "transitions": PoolRealArray( 1, 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ] } tracks/1/type = "value" tracks/1/path = NodePath("Bar:self_modulate") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0.1, 0.8 ), "transitions": PoolRealArray( 1, 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ] } [node name="BossLifebar" type="VBoxContainer"] visible = false anchor_left = 0.5 anchor_top = 1.0 anchor_right = 0.5 anchor_bottom = 1.0 margin_left = -780.0 margin_top = -133.0 margin_right = 780.0 margin_bottom = -40.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 alignment = 0 script = ExtResource( 1 ) boss_name = "" [node name="Label" type="Label" parent="." index="0"] self_modulate = Color( 1, 1, 1, 0 ) anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_right = 1560.0 margin_bottom = 23.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 theme = ExtResource( 2 ) align = 1 valign = 2 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "Theme", "Visibility", "custom_fonts" ] [node name="Bar" type="TextureProgress" parent="." index="1"] modulate = Color( 1, 0.0195313, 0.272308, 1 ) self_modulate = Color( 1, 1, 1, 5.96046e-008 ) anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 156.0 margin_top = 27.0 margin_right = 1404.0 margin_bottom = 93.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 4 size_flags_vertical = 4 min_value = 0.0 max_value = 100.0 step = 1.0 page = 0.0 value = 100.0 exp_edit = false rounded = false texture_under = ExtResource( 3 ) texture_over = null texture_progress = ExtResource( 4 ) radial_fill_degrees = 360.0 radial_center_offset = Vector2( 0, 0 ) nine_patch_stretch = false _sections_unfolded = [ "Size Flags", "Textures", "Visibility" ] [node name="AnimationPlayer" type="AnimationPlayer" parent="." index="2"] root_node = NodePath("..") autoplay = "" playback_process_mode = 1 playback_default_blend_time = 0.0 playback_speed = 1.0 anims/appear = SubResource( 1 ) anims/disappear = SubResource( 2 ) blend_times = [ ] ================================================ FILE: interface/gui/boss/boss_bar_bg.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/boss_bar_bg.png-aed3843f4ed3efb0dbc21b2322fd9e56.stex" metadata={ "vram_texture": false } [deps] source_file="res://interface/gui/boss/boss_bar_bg.png" dest_files=[ "res://.import/boss_bar_bg.png-aed3843f4ed3efb0dbc21b2322fd9e56.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: interface/gui/boss/boss_bar_fill.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/boss_bar_fill.png-9d50dc46e3fabfa93c1e17061ffa511b.stex" metadata={ "vram_texture": false } [deps] source_file="res://interface/gui/boss/boss_bar_fill.png" dest_files=[ "res://.import/boss_bar_fill.png-9d50dc46e3fabfa93c1e17061ffa511b.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: interface/gui/lifebar/HookableLifeBar.tscn ================================================ [gd_scene load_steps=4 format=2] [ext_resource path="res://interface/gui/lifebar/Lifebar.gd" type="Script" id=1] [ext_resource path="res://interface/gui/lifebar/background.png" type="Texture" id=2] [ext_resource path="res://interface/gui/lifebar/fill.png" type="Texture" id=3] [node name="HookableLifeBar" type="Node2D" groups=[ "bars", ]] script = ExtResource( 1 ) [node name="Background" type="TextureRect" parent="." index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = -95.0 margin_top = -11.0 margin_right = 97.0 margin_bottom = 11.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 texture = ExtResource( 2 ) stretch_mode = 0 _sections_unfolded = [ "Rect", "Textures" ] [node name="TextureProgress" type="TextureProgress" parent="." index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = -95.0 margin_top = -11.0 margin_right = 97.0 margin_bottom = 11.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 min_value = 0.0 max_value = 100.0 step = 1.0 page = 0.0 value = 60.0 exp_edit = false rounded = false texture_under = null texture_over = null texture_progress = ExtResource( 3 ) radial_fill_degrees = 360.0 radial_center_offset = Vector2( 0, 0 ) nine_patch_stretch = false _sections_unfolded = [ "Rect" ] ================================================ FILE: interface/gui/lifebar/InterfaceAnchor.tscn ================================================ [gd_scene format=2] [node name="InterfaceAnchor" type="RemoteTransform2D"] position = Vector2( 0, -98.2191 ) remote_path = NodePath("") use_global_coordinates = true update_position = true update_rotation = false update_scale = false ================================================ FILE: interface/gui/lifebar/Lifebar.gd ================================================ extends Node2D var max_health = 0 setget set_max_health var health = 0 setget set_health func set_max_health(value): max_health = value $TextureProgress.max_value = value func set_health(value): health = value $TextureProgress.value = value func initialize(actor): var hook = actor.get_node("InterfaceAnchor") global_position = hook.global_position hook.remote_path = hook.get_path_to(self) var health_node = actor.get_node("Stats") health_node.connect("health_changed", self, "_on_Actor_health_changed") health_node.connect("health_depleted", self, "_on_Actor_health_depleted") self.health = health_node.health self.max_health = health_node.max_health func _on_Actor_health_changed(new_health): self.health = new_health func _on_Actor_health_depleted(): queue_free() ================================================ FILE: interface/gui/lifebar/LifebarsBuilder.gd ================================================ extends Node const Lifebar = preload("res://interface/gui/lifebar/HookableLifeBar.tscn") func initialize(monsters, monster_spawners): for monster in monsters: create_lifebar(monster) for spawner in monster_spawners: monster_spawners.connect('spawned_monster', self, '_on_MonsterSpawner_spawned_monster') func _on_MonsterSpawner_spawned_monster(monster_node): create_lifebar(monster_node) func create_lifebar(actor): if not actor.has_node('InterfaceAnchor'): return var lifebar = Lifebar.instance() actor.add_child(lifebar) lifebar.initialize(actor) ================================================ FILE: interface/gui/lifebar/LifebarsBuilder.tscn ================================================ [gd_scene load_steps=2 format=2] [ext_resource path="res://interface/gui/lifebar/LifebarsBuilder.gd" type="Script" id=1] [node name="LifebarsBuilder" type="Node"] script = ExtResource( 1 ) ================================================ FILE: interface/gui/lifebar/background.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/background.png-62efda1a07fd52ccf13fb5c00abc7e8c.stex" metadata={ "vram_texture": false } [deps] source_file="res://interface/gui/lifebar/background.png" dest_files=[ "res://.import/background.png-62efda1a07fd52ccf13fb5c00abc7e8c.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: interface/gui/lifebar/fill.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/fill.png-b3e6044072b4f216e075877da6e81969.stex" metadata={ "vram_texture": false } [deps] source_file="res://interface/gui/lifebar/fill.png" dest_files=[ "res://.import/fill.png-b3e6044072b4f216e075877da6e81969.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: interface/gui/player/PlayerGUI.gd ================================================ extends Control func initialize(health_node, purse): $LifeBar.initialize(health_node) $CoinsCounter.initialize(purse) health_node.connect('health_depleted', self, '_on_Player_Health_health_depleted') func _on_Player_Health_health_depleted(): $AnimationPlayer.play("fade_out") ================================================ FILE: interface/gui/player/PlayerGUI.tscn ================================================ [gd_scene load_steps=9 format=2] [ext_resource path="res://interface/default.theme" type="Theme" id=1] [ext_resource path="res://interface/gui/player/PlayerGUI.gd" type="Script" id=2] [ext_resource path="res://interface/gui/player/life_bar/LifeBar.tscn" type="PackedScene" id=3] [ext_resource path="res://core/inventory/items/coins/coin_single.png" type="Texture" id=4] [ext_resource path="res://interface/fonts/source_code_pro_explanations_bold.tres" type="DynamicFont" id=5] [sub_resource type="GDScript" id=3] script/source = "extends Panel func initialize(purse): purse.connect('coins_changed', self, '_on_Purse_coins_changed') update_count(purse.coins) func _on_Purse_coins_changed(coins): update_count(coins) func update_count(value): $Label.text = str(value) " [sub_resource type="Animation" id=1] resource_name = "SETUP" length = 0.5 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath(".:modulate") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ) ] } [sub_resource type="Animation" id=2] length = 0.8 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath(".:modulate") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.8 ), "transitions": PoolRealArray( 1, 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ] } tracks/1/type = "method" tracks/1/path = NodePath(".") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0.8 ), "transitions": PoolRealArray( 1 ), "values": [ { "args": [ ], "method": "queue_free" } ] } [node name="PlayerGUI" type="HBoxContainer" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 0.0 margin_left = 20.0 margin_top = 20.0 margin_right = -30.0 margin_bottom = 73.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 theme = ExtResource( 1 ) custom_constants/separation = 16 alignment = 0 script = ExtResource( 2 ) _sections_unfolded = [ "Anchor", "Theme", "custom_constants" ] [node name="LifeBar" parent="." index="0" instance=ExtResource( 3 )] anchor_right = 0.0 anchor_bottom = 0.0 margin_right = 396.0 margin_bottom = 53.0 _sections_unfolded = [ "Rect", "Size Flags" ] [node name="CoinsCounter" type="Panel" parent="." index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 412.0 margin_right = 532.0 margin_bottom = 53.0 rect_min_size = Vector2( 120, 0 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 script = SubResource( 3 ) _sections_unfolded = [ "Rect" ] [node name="Coin" type="TextureRect" parent="CoinsCounter" index="0"] anchor_left = 0.0 anchor_top = 0.5 anchor_right = 0.0 anchor_bottom = 0.5 margin_left = 15.0 margin_top = -16.5 margin_right = 45.0 margin_bottom = 16.5 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 texture = ExtResource( 4 ) expand = true stretch_mode = 0 [node name="Label" type="Label" parent="CoinsCounter" index="1"] anchor_left = 1.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 margin_left = -72.0 margin_right = -20.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 custom_fonts/font = ExtResource( 5 ) text = "120" align = 2 valign = 1 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "custom_fonts" ] [node name="AnimationPlayer" type="AnimationPlayer" parent="." index="2"] root_node = NodePath("..") autoplay = "" playback_process_mode = 1 playback_default_blend_time = 0.0 playback_speed = 1.0 anims/SETUP = SubResource( 1 ) anims/fade_out = SubResource( 2 ) blend_times = [ ] ================================================ FILE: interface/gui/player/life_bar/LifeBar.tscn ================================================ [gd_scene load_steps=8 format=2] [ext_resource path="res://interface/gui/player/life_bar/bg.png" type="Texture" id=1] [ext_resource path="res://interface/gui/player/life_bar/Lifebar.gd" type="Script" id=2] [ext_resource path="res://interface/gui/player/life_bar/fill.png" type="Texture" id=3] [ext_resource path="res://interface/gui/player/life_bar/TextureProgress.gd" type="Script" id=4] [sub_resource type="Animation" id=1] resource_name = "SETUP" length = 0.01 loop = false step = 0.1 [sub_resource type="Animation" id=2] resource_name = "heal" length = 0.4 loop = false step = 0.1 [sub_resource type="Animation" id=3] length = 0.4 loop = false step = 0.1 [node name="LifeBar" type="TextureRect" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 margin_right = -884.0 margin_bottom = -667.0 rect_pivot_offset = Vector2( 196.476, 27.8519 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 texture = ExtResource( 1 ) stretch_mode = 0 script = ExtResource( 2 ) _sections_unfolded = [ "Rect" ] [node name="TextureProgress" type="TextureProgress" parent="." index="0"] modulate = Color( 0.366329, 0.902344, 0.0951691, 1 ) anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 min_value = 0.0 max_value = 34.0 step = 1.0 page = 0.0 value = 16.0 exp_edit = false rounded = false texture_under = null texture_over = null texture_progress = ExtResource( 3 ) radial_fill_degrees = 360.0 radial_center_offset = Vector2( 0, 0 ) nine_patch_stretch = false script = ExtResource( 4 ) _sections_unfolded = [ "Textures", "Visibility" ] COLOR_FULL = Color( 0.708904, 0.9375, 0.0769043, 1 ) COLOR_NORMAL = Color( 0.366329, 0.902344, 0.0951691, 1 ) COLOR_LOW = Color( 0.910156, 0.62426, 0.131546, 1 ) COLOR_CRITICAL = Color( 0.957031, 0.203889, 0.056076, 1 ) THRESHOLD_LOW = 0.4 THRESHOLD_CRITICAL = 0.2 [node name="Tween" type="Tween" parent="TextureProgress" index="0"] repeat = false playback_process_mode = 1 playback_speed = 1.0 playback/active = false playback/repeat = false playback/speed = 1.0 [node name="AnimationPlayer" type="AnimationPlayer" parent="." index="1"] root_node = NodePath("..") autoplay = "SETUP" playback_process_mode = 1 playback_default_blend_time = 0.0 playback_speed = 1.0 anims/SETUP = SubResource( 1 ) anims/heal = SubResource( 2 ) anims/shake = SubResource( 3 ) blend_times = [ ] [connection signal="maximum_changed" from="." to="TextureProgress" method="_on_Bar_maximum_changed"] ================================================ FILE: interface/gui/player/life_bar/Lifebar.gd ================================================ extends Control signal maximum_changed(maximum) var maximum = 100 var current_health = 0 func initialize(health_node): health_node.connect('health_changed', self, '_on_Player_Health_health_changed') maximum = health_node.max_health current_health = health_node.health emit_signal("maximum_changed", maximum) animate_bar(current_health) func _on_Player_Health_health_changed(new_health): animate_bar(new_health) current_health = new_health func animate_bar(target_health): $TextureProgress.animate_value(current_health, target_health) $TextureProgress.update_color(target_health) ================================================ FILE: interface/gui/player/life_bar/TextureProgress.gd ================================================ tool extends TextureProgress export(Color) var COLOR_FULL export(Color) var COLOR_NORMAL export(Color) var COLOR_LOW export(Color) var COLOR_CRITICAL export(float, 0, 1) var THRESHOLD_LOW = 0.3 export(float, 0, 1) var THRESHOLD_CRITICAL = 0.1 var color_active = COLOR_NORMAL func _on_Bar_maximum_changed(maximum): max_value = maximum func animate_value(start, end): $Tween.interpolate_property(self, "value", start, end, 0.5, Tween.TRANS_QUART, Tween.EASE_OUT) $Tween.start() func update_color(new_value): var new_color if new_value > THRESHOLD_LOW * max_value: if new_value < max_value: new_color = COLOR_NORMAL else: new_color = COLOR_FULL elif new_value > THRESHOLD_CRITICAL * max_value: new_color = COLOR_LOW else: new_color = COLOR_CRITICAL if new_color == color_active: return color_active = new_color $Tween.interpolate_property(self, "modulate", modulate, new_color, 0.4, Tween.TRANS_QUART, Tween.EASE_OUT) $Tween.start() ================================================ FILE: interface/gui/player/life_bar/bg.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/bg.png-4137f69cffc7cfbd089694c7a17196f3.stex" metadata={ "vram_texture": false } [deps] source_file="res://interface/gui/player/life_bar/bg.png" dest_files=[ "res://.import/bg.png-4137f69cffc7cfbd089694c7a17196f3.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: interface/gui/player/life_bar/fill.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/fill.png-6d81f3dffced581fbfcd68a8ff5225b0.stex" metadata={ "vram_texture": false } [deps] source_file="res://interface/gui/player/life_bar/fill.png" dest_files=[ "res://.import/fill.png-6d81f3dffced581fbfcd68a8ff5225b0.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: interface/items/ItemButton.gd ================================================ extends Button signal amount_changed(value) var description = "" var amount = 0 func initialize(item, price, purse): $Name.text = item.display_name $Price.text = str(price) $Icon.texture = item.icon description = item.description amount = item.amount if purse.coins < price: disabled = true item.connect("amount_changed", self, "_on_Item_amount_changed") item.connect("depleted", self, "_on_Item_depleted") purse.connect("coins_changed", self, "_on_Purse_coins_changed", [price]) func _on_Item_depleted(): disabled = true func _on_Item_amount_changed(value): amount = value emit_signal("amount_changed", value) func _on_Purse_coins_changed(coins, price): if price > coins: disabled = true ================================================ FILE: interface/items/ItemButton.tscn ================================================ [gd_scene load_steps=5 format=2] [ext_resource path="res://interface/default.theme" type="Theme" id=1] [ext_resource path="res://interface/items/ItemButton.gd" type="Script" id=2] [ext_resource path="res://interface/theme/icons/purse.png" type="Texture" id=3] [ext_resource path="res://interface/theme/icons/coins.png" type="Texture" id=4] [node name="ItemButton" type="Button" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_right = 300.0 margin_bottom = 60.0 rect_min_size = Vector2( 300, 60 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false focus_mode = 2 mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 3 size_flags_vertical = 1 theme = ExtResource( 1 ) toggle_mode = false enabled_focus_mode = 2 shortcut = null group = null flat = false align = 1 script = ExtResource( 2 ) _sections_unfolded = [ "Focus", "Rect", "Size Flags", "Theme" ] [node name="Name" type="Label" parent="." index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 1.0 margin_left = 54.0 margin_right = 254.0 rect_min_size = Vector2( 200, 0 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 text = "Item Name" valign = 1 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "Rect" ] [node name="Icon" type="TextureRect" parent="." index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 1.0 margin_right = 70.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 texture = ExtResource( 3 ) stretch_mode = 4 [node name="coins" type="TextureRect" parent="." index="2"] anchor_left = 1.0 anchor_top = 0.5 anchor_right = 1.0 anchor_bottom = 0.5 margin_left = -41.0 margin_top = -18.0 margin_right = -9.0 margin_bottom = 14.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 texture = ExtResource( 4 ) stretch_mode = 0 [node name="Price" type="Label" parent="." index="3"] anchor_left = 1.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 margin_left = -127.0 margin_right = -47.0 rect_min_size = Vector2( 80, 0 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 text = "20" align = 2 valign = 1 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "Rect" ] ================================================ FILE: interface/items/ItemGrid.gd ================================================ extends GridContainer func initialize(): update_focus_neighbours() get_child(0).grab_focus() func update_focus_neighbours(ignore=null): var buttons_to_update = get_children() # There's a bug with the Node.tree_exited signal so the button is still in the tree if ignore: buttons_to_update.remove(ignore.get_index()) var count = buttons_to_update.size() var index = 0 for button in buttons_to_update: var index_previous = index - 1 var index_next = (index + 1) % count var button_previous = button.get_path_to(buttons_to_update[index_previous]) var button_next = button.get_path_to(buttons_to_update[index_next]) button.focus_neighbour_left = button_previous button.focus_neighbour_right = button_next button.focus_neighbour_top = button_previous button.focus_neighbour_bottom = button_next button.focus_previous = button_previous button.focus_next = button_next index += 1 ================================================ FILE: interface/items/ItemsList.gd ================================================ extends Control signal focused_button_changed(button) signal item_amount_changed(amount) signal focused_item_changed(item) export(PackedScene) var ItemButton = preload("res://interface/items/ItemButton.tscn") onready var _grid = $Grid func initialize(): _grid.initialize() func add_item_button(item, price, purse): var item_button = ItemButton.instance() item_button.initialize(item, price, purse) _grid.add_child(item_button) item_button.connect("focus_entered", self, "_on_ItemButton_focus_entered", [item_button, item]) item_button.connect("amount_changed", self, "_on_ItemButton_amount_changed") return item_button func _gui_input(event): if not get_focus_owner() == self: return if event.is_action_pressed('ui_left') or \ event.is_action_pressed('ui_right') or \ event.is_action_pressed('ui_up') or \ event.is_action_pressed('ui_down'): $MenuSfx/Navigate.play() accept_event() func get_item_buttons(): return _grid.get_children() func _on_ItemButton_focus_entered(button, item): emit_signal("focused_button_changed", button) emit_signal("focused_item_changed", item) func _on_ItemButton_amount_changed(value): emit_signal("item_amount_changed", value) ================================================ FILE: interface/items/ItemsList.tscn ================================================ [gd_scene load_steps=5 format=2] [ext_resource path="res://interface/items/ItemsList.gd" type="Script" id=1] [ext_resource path="res://interface/items/ItemButton.tscn" type="PackedScene" id=2] [ext_resource path="res://interface/items/ItemGrid.gd" type="Script" id=3] [ext_resource path="res://interface/menus/MenuSfx.tscn" type="PackedScene" id=4] [node name="ItemsList" type="Panel"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 3 size_flags_vertical = 3 script = ExtResource( 1 ) _sections_unfolded = [ "Size Flags" ] ItemButton = ExtResource( 2 ) [node name="Grid" type="GridContainer" parent="." index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 margin_left = 40.0 margin_top = 40.0 margin_right = -40.0 margin_bottom = -40.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 3 size_flags_vertical = 1 custom_constants/vseparation = 16 custom_constants/hseparation = 16 columns = 2 script = ExtResource( 3 ) [node name="MenuSfx" parent="." index="1" instance=ExtResource( 4 )] ================================================ FILE: interface/menus/Menu.gd ================================================ extends Control class_name Menu signal open() signal closed() export(NodePath) var SUB_MENU_PATH onready var sound_confirm = $MenuSfx/Confirm onready var sound_navigate = $MenuSfx/Navigate onready var sound_open = $MenuSfx/Open func _ready(): set_process_input(false) func open(args={}): set_process_input(true) show() sound_open.play() emit_signal("open") func close(): sound_confirm.play() set_process_input(false) hide() emit_signal("closed") func _gui_input(event): if event.is_action_pressed("ui_cancel"): accept_event() close() # You can streamline opening sub menus with these methods # The main drawback is you lose the initialize method's signature # Instead you have to group the arguments in a dictionary func initialize(args={}): return func open_sub_menu(menu, args={}): var sub_menu = menu.instance() if menu is PackedScene else menu if SUB_MENU_PATH: get_node(SUB_MENU_PATH).add_child(sub_menu) else: add_child(sub_menu) sub_menu.initialize(args) set_process_input(false) sub_menu.open(args) yield(sub_menu, "closed") set_process_input(true) remove_child(sub_menu) ================================================ FILE: interface/menus/Menu.tscn ================================================ [gd_scene load_steps=4 format=2] [ext_resource path="res://interface/default.theme" type="Theme" id=1] [ext_resource path="res://interface/menus/Menu.gd" type="Script" id=2] [ext_resource path="res://interface/menus/MenuSfx.tscn" type="PackedScene" id=3] [node name="Menu" type="Control"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 theme = ExtResource( 1 ) script = ExtResource( 2 ) _sections_unfolded = [ "Theme" ] SUB_MENU_PATH = null [node name="MenuSfx" parent="." index="0" instance=ExtResource( 3 )] ================================================ FILE: interface/menus/MenuSfx.tscn ================================================ [gd_scene load_steps=4 format=2] [ext_resource path="res://audio/sfx/menu_confirm.wav" type="AudioStream" id=1] [ext_resource path="res://audio/sfx/menu_navigate_01.wav" type="AudioStream" id=2] [ext_resource path="res://audio/sfx/menu_popup_open.wav" type="AudioStream" id=3] [node name="MenuSfx" type="Node" index="0"] [node name="Confirm" type="AudioStreamPlayer" parent="." index="0"] stream = ExtResource( 1 ) volume_db = -1.0 pitch_scale = 1.0 autoplay = false mix_target = 2 bus = "Interface" [node name="Navigate" type="AudioStreamPlayer" parent="." index="1"] stream = ExtResource( 2 ) volume_db = -6.0 pitch_scale = 1.0 autoplay = false mix_target = 2 bus = "Interface" [node name="Open" type="AudioStreamPlayer" parent="." index="2"] stream = ExtResource( 3 ) volume_db = -3.0 pitch_scale = 1.0 autoplay = false mix_target = 2 bus = "Interface" ================================================ FILE: interface/menus/MenuTitle.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://interface/theme/fonts/source_code_pro_26.tres" type="DynamicFont" id=1] [sub_resource type="GDScript" id=1] script/source = "tool extends Control export(String) var title = \"Title\" setget set_title onready var label = $Label func _ready(): set_title(title) func set_title(string): title = string if not label: return label.text = string " [node name="TitlePanel" type="Panel" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_right = 1920.0 margin_bottom = 80.0 rect_min_size = Vector2( 0, 80 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 script = SubResource( 1 ) _sections_unfolded = [ "Rect" ] title = "Title" [node name="Label" type="Label" parent="." index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 margin_left = 2.0 margin_right = 2.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 custom_fonts/font = ExtResource( 1 ) text = "Title" align = 1 valign = 1 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "custom_fonts" ] ================================================ FILE: interface/menus/inventory/InventoryMenu.gd ================================================ extends Menu onready var items_list = $Column/ItemsMenu """args: {inventory}""" func initialize(args={}): items_list.initialize(args['inventory']) """args: {inventory}""" func open(args={}): assert(args.size() == 1) var inventory = args['inventory'] .open() func close(): .close() queue_free() ================================================ FILE: interface/menus/inventory/InventoryMenu.tscn ================================================ [gd_scene load_steps=6 format=2] [ext_resource path="res://interface/menus/Menu.tscn" type="PackedScene" id=1] [ext_resource path="res://interface/menus/inventory/InventoryMenu.gd" type="Script" id=2] [ext_resource path="res://interface/default.theme" type="Theme" id=3] [ext_resource path="res://interface/menus/MenuTitle.tscn" type="PackedScene" id=4] [ext_resource path="res://interface/menus/inventory/ItemsMenu.tscn" type="PackedScene" id=5] [node name="InventoryMenu" instance=ExtResource( 1 )] script = ExtResource( 2 ) [node name="Column" type="VBoxContainer" parent="." index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 theme = ExtResource( 3 ) custom_constants/separation = 0 alignment = 0 _sections_unfolded = [ "Theme", "custom_constants" ] [node name="TitlePanel" parent="Column" index="0" instance=ExtResource( 4 )] title = "Inventory" [node name="ItemsMenu" parent="Column" index="1" instance=ExtResource( 5 )] anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 80.0 margin_right = 1920.0 margin_bottom = 1080.0 ================================================ FILE: interface/menus/inventory/ItemButton.gd ================================================ extends Button var description = "" func initialize(item): $Name.text = item.display_name $Amount.text = str(item.amount) $Icon.texture = item.icon description = item.description disabled = not item.usable item.connect("amount_changed", self, "_on_Item_amount_changed") item.connect("depleted", self, "queue_free") func _on_Item_amount_changed(amount): $Amount.text = str(amount) ================================================ FILE: interface/menus/inventory/ItemButton.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://interface/menus/inventory/ItemButton.gd" type="Script" id=1] [ext_resource path="res://interface/theme/icons/purse.png" type="Texture" id=2] [node name="ItemButton" type="Button" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_right = 280.0 margin_bottom = 60.0 rect_min_size = Vector2( 300, 60 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false focus_mode = 2 mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 3 size_flags_vertical = 1 toggle_mode = false enabled_focus_mode = 2 shortcut = null group = null flat = false align = 1 script = ExtResource( 1 ) _sections_unfolded = [ "Rect", "Size Flags" ] [node name="Name" type="Label" parent="." index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 1.0 margin_left = 70.0 margin_right = 270.0 rect_min_size = Vector2( 200, 0 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 text = "Item Name" valign = 1 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "Rect" ] [node name="Icon" type="TextureRect" parent="." index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 1.0 margin_right = 70.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 texture = ExtResource( 2 ) stretch_mode = 4 [node name="Amount" type="Label" parent="." index="2"] anchor_left = 1.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 margin_left = -100.0 margin_right = -20.0 rect_min_size = Vector2( 80, 0 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 text = "20" align = 2 valign = 1 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "Rect" ] ================================================ FILE: interface/menus/inventory/ItemGrid.gd ================================================ extends GridContainer onready var placeholder_button = $Placeholder func _ready(): remove_child(placeholder_button) func initialize(item_buttons): for button in item_buttons: add_child(button) update_focus_neighbours() for button in get_children(): button.connect("tree_exited", self, "_on_ItemButton_tree_exited", [button]) get_child(0).grab_focus() add_child(placeholder_button) func _on_ItemButton_tree_exited(button): var to_focus_path = button.focus_neighbour_left if button.get_index() > 0 else button.focus_neighbour_right button.get_node(to_focus_path).grab_focus() update_focus_neighbours(button) func update_focus_neighbours(ignore=null): var buttons_to_update = get_children() # There's a bug with the Node.tree_exited signal so the button is still in the tree if ignore: buttons_to_update.remove(ignore.get_index()) var count = buttons_to_update.size() var index = 0 for button in buttons_to_update: var index_previous = index - 1 var index_next = (index + 1) % count button.focus_neighbour_left = button.get_path_to(buttons_to_update[index_previous]) button.focus_neighbour_right = button.get_path_to(buttons_to_update[index_next]) index += 1 ================================================ FILE: interface/menus/inventory/ItemsMenu.gd ================================================ extends Control signal item_use_requested(item, actor) export(PackedScene) var ItemButton onready var _item_grid = $Column/ItemsList/Margin/Grid onready var _description_label = $Column/DescriptionPanel/Margin/Label func initialize(inventory): var buttons = [] for item in inventory.get_items(): var item_button = create_item_button(item) item_button.connect("focus_entered", self, "_on_ItemButton_focus_entered") item_button.connect("pressed", self, "_on_ItemButton_pressed", [item]) buttons.append(item_button) _item_grid.initialize(buttons) inventory.connect("item_added", self, "create_item_button") connect("item_use_requested", inventory, "use") func create_item_button(item): var item_button = ItemButton.instance() item_button.initialize(item) return item_button func _on_ItemButton_focus_entered(): _description_label.text = get_focus_owner().description func _on_ItemButton_pressed(item): var button = get_focus_owner() $UserSelectMenu.open() var actor = yield($UserSelectMenu, "closed") button.grab_focus() if not actor: return emit_signal("item_use_requested", item, actor) ================================================ FILE: interface/menus/inventory/ItemsMenu.tscn ================================================ [gd_scene load_steps=6 format=2] [ext_resource path="res://interface/default.theme" type="Theme" id=1] [ext_resource path="res://interface/menus/inventory/ItemsMenu.gd" type="Script" id=2] [ext_resource path="res://interface/menus/inventory/ItemButton.tscn" type="PackedScene" id=3] [ext_resource path="res://interface/menus/inventory/ItemGrid.gd" type="Script" id=4] [ext_resource path="res://interface/menus/inventory/user_select/UserSelectMenu.tscn" type="PackedScene" id=5] [node name="ItemsMenu" type="Control"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 3 theme = ExtResource( 1 ) script = ExtResource( 2 ) _sections_unfolded = [ "Size Flags" ] ItemButton = ExtResource( 3 ) [node name="Column" type="VBoxContainer" parent="." index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 custom_constants/separation = 0 alignment = 0 [node name="ItemsList" type="Panel" parent="Column" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_right = 1920.0 margin_bottom = 980.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 3 [node name="Margin" type="MarginContainer" parent="Column/ItemsList" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 _sections_unfolded = [ "custom_constants" ] [node name="Grid" type="GridContainer" parent="Column/ItemsList/Margin" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 16.0 margin_top = 16.0 margin_right = 1904.0 margin_bottom = 964.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 3 size_flags_vertical = 1 custom_constants/vseparation = 16 custom_constants/hseparation = 16 columns = 2 script = ExtResource( 4 ) _sections_unfolded = [ "custom_constants" ] [node name="Placeholder" type="Button" parent="Column/ItemsList/Margin/Grid" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_right = 1888.0 margin_bottom = 27.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false focus_mode = 2 mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 3 size_flags_vertical = 1 disabled = true toggle_mode = false enabled_focus_mode = 2 shortcut = null group = null flat = true align = 1 _sections_unfolded = [ "Size Flags" ] [node name="DescriptionPanel" type="Panel" parent="Column" index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 980.0 margin_right = 1920.0 margin_bottom = 1080.0 rect_min_size = Vector2( 0, 100 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 _sections_unfolded = [ "Rect" ] [node name="Margin" type="MarginContainer" parent="Column/DescriptionPanel" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 [node name="Label" type="Label" parent="Column/DescriptionPanel/Margin" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 16.0 margin_top = 25.0 margin_right = 1904.0 margin_bottom = 74.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 text = "Item descripton here. " autowrap = true percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 [node name="UserSelectMenu" parent="." index="1" instance=ExtResource( 5 )] visible = false ================================================ FILE: interface/menus/inventory/user_select/ActorButton.tscn ================================================ [gd_scene load_steps=2 format=2] [ext_resource path="res://actors/body.png" type="Texture" id=1] [node name="ActorButton" type="Button"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 310.0 margin_right = 420.0 margin_bottom = 410.0 rect_min_size = Vector2( 300, 100 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false focus_mode = 2 mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 3 size_flags_vertical = 1 toggle_mode = false enabled_focus_mode = 2 shortcut = null group = null flat = false align = 1 _sections_unfolded = [ "Rect", "Size Flags" ] [node name="Name" type="Label" parent="." index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 1.0 margin_left = 90.0 margin_right = 290.0 rect_min_size = Vector2( 200, 0 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 text = "Actor" valign = 1 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "Rect" ] [node name="Icon" type="TextureRect" parent="." index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 1.0 margin_right = 90.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 texture = ExtResource( 1 ) stretch_mode = 4 ================================================ FILE: interface/menus/inventory/user_select/UserSelectMenu.gd ================================================ extends Control signal closed(selected_actor) export(PackedScene) var ActorButton func _ready(): set_as_toplevel(true) func initialize(actors): for actor in actors: create_actor_button(actor) func create_actor_button(actor): var button = ActorButton.instance() button.get_node("Name").text = actor.name button.connect("pressed", self, "_on_SelectButton_pressed", [actor]) $ActorsList.add_child(button) func _input(event): if event.is_action_pressed("ui_cancel"): close() func _on_SelectButton_pressed(actor): close(actor) # TODO: Temporarily bypassing the menu, # see https://github.com/GDquest/make-pro-2d-games-with-godot/issues/66 func open(): close() return $ActorsList.get_child(0).grab_focus() visible = true set_process_input(true) func close(selected_actor=null): visible = false set_process_input(false) emit_signal("closed", selected_actor) ================================================ FILE: interface/menus/inventory/user_select/UserSelectMenu.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://interface/menus/inventory/user_select/UserSelectMenu.gd" type="Script" id=1] [ext_resource path="res://interface/menus/inventory/user_select/ActorButton.tscn" type="PackedScene" id=2] [node name="UserSelectMenu" type="Control" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 script = ExtResource( 1 ) ActorButton = ExtResource( 2 ) [node name="BlackOverlay" type="ColorRect" parent="." index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 color = Color( 0, 0, 0, 0.313726 ) [node name="ActorsList" type="VBoxContainer" parent="." index="1"] anchor_left = 0.5 anchor_top = 0.0 anchor_right = 0.5 anchor_bottom = 1.0 margin_left = -210.0 margin_right = 210.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 alignment = 1 ================================================ FILE: interface/menus/pause/OptionsMenu.gd ================================================ extends Menu const SoundController = preload("res://interface/menus/pause/SoundController.gd") onready var first_slider = $Column/MusicController/Row/HSlider func open(args={}): .open() first_slider.grab_focus() set_focus_neighbors() func set_focus_neighbors(): """ Loops through the sliders and assign their focus neighbors manually This fixes keyboard navigation in the options menu """ var sliders = get_sound_sliders() var index = 0 for slider in sliders: var index_previous = index - 1 if index_previous >= 0: slider.focus_neighbour_top = slider.get_path_to(sliders[index_previous]) var index_next = index + 1 if index_next < sliders.size(): slider.focus_neighbour_bottom = NodePath(slider.get_path_to(sliders[index_next])) index += 1 var back_button = $Column/GoBackButton var last_slider = sliders[-1] last_slider.focus_neighbour_bottom = last_slider.get_path_to(back_button) back_button.focus_neighbour_top = back_button.get_path_to(last_slider) func get_sound_sliders(): var sliders = [] for node in $Column.get_children(): if not node is SoundController: continue sliders.append(node.slider) return sliders ================================================ FILE: interface/menus/pause/OptionsMenu.tscn ================================================ [gd_scene load_steps=6 format=2] [ext_resource path="res://interface/default.theme" type="Theme" id=1] [ext_resource path="res://interface/menus/pause/OptionsMenu.gd" type="Script" id=2] [ext_resource path="res://interface/menus/MenuSfx.tscn" type="PackedScene" id=3] [ext_resource path="res://interface/theme/fonts/default_font_comfortaa.tres" type="DynamicFont" id=4] [ext_resource path="res://interface/menus/pause/SoundController.tscn" type="PackedScene" id=5] [node name="OptionsMenu" type="Panel"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false focus_mode = 2 mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 theme = ExtResource( 1 ) script = ExtResource( 2 ) _sections_unfolded = [ "Focus", "Theme" ] SUB_MENU_PATH = null [node name="MenuSfx" parent="." index="0" instance=ExtResource( 3 )] [node name="Column" type="VBoxContainer" parent="." index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 margin_left = 570.0 margin_top = 147.0 margin_right = -570.0 margin_bottom = -147.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 alignment = 1 _sections_unfolded = [ "Focus" ] [node name="Title" type="Label" parent="Column" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 73.0 margin_right = 780.0 margin_bottom = 108.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 custom_fonts/font = ExtResource( 4 ) text = "Sound Options" align = 1 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "Focus", "custom_fonts" ] [node name="HSeparator" type="HSeparator" parent="Column" index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 124.0 margin_right = 780.0 margin_bottom = 128.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 [node name="MusicController" parent="Column" index="2" instance=ExtResource( 5 )] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 0.0 margin_top = 144.0 margin_right = 780.0 margin_bottom = 284.0 [node name="SfxController" parent="Column" index="3" instance=ExtResource( 5 )] editor/display_folded = true anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 0.0 margin_top = 300.0 margin_right = 780.0 margin_bottom = 440.0 [node name="InterfaceController" parent="Column" index="4" instance=ExtResource( 5 )] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 0.0 margin_top = 456.0 margin_right = 780.0 margin_bottom = 596.0 [node name="HSeparator2" type="HSeparator" parent="Column" index="5"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 612.0 margin_right = 780.0 margin_bottom = 616.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 [node name="GoBackButton" type="Button" parent="Column" index="6"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 632.0 margin_right = 780.0 margin_bottom = 712.0 rect_min_size = Vector2( 0, 80 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false focus_mode = 2 mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 toggle_mode = false enabled_focus_mode = 2 shortcut = null group = null text = "Go back" flat = false align = 1 _sections_unfolded = [ "Focus", "Rect" ] [connection signal="pressed" from="Column/GoBackButton" to="." method="close"] ================================================ FILE: interface/menus/pause/PauseMenu.gd ================================================ extends Menu signal unpause() const InventoryMenu = preload("res://interface/menus/inventory/InventoryMenu.tscn") const PlayerController = preload("res://actors/player/PlayerController.gd") onready var continue_button = $Background/Column/ContinueButton onready var items_button = $Background/Column/ItemsButton onready var options_button = $Background/Column/OptionsButton onready var save_button = $Background/Column/SaveButton onready var buttons_container = $Background/Column onready var save_menu = $SaveMenu onready var options_menu = $OptionsMenu func _ready(): options_button.connect('pressed', self, 'open_sub_menu', [options_menu]) save_button.connect('pressed', self, 'open_sub_menu', [save_menu]) remove_child(save_menu) remove_child(options_menu) """args: {actor}""" func initialize(args={}): var actor = args['actor'] assert(actor is PlayerController) var inventory = actor.get_inventory() items_button.connect('pressed', self, 'open_sub_menu', [InventoryMenu, {'inventory':inventory}]) actor.connect('died', self, '_on_Player_died') func _on_Player_died(): items_button.disabled = true func open(args={}): .open() continue_button.grab_focus() func open_sub_menu(menu, args={}): var last_focused_item = get_focus_owner() buttons_container.hide() yield(.open_sub_menu(menu, args), 'completed') buttons_container.show() last_focused_item.grab_focus() ================================================ FILE: interface/menus/pause/PauseMenu.tscn ================================================ [gd_scene load_steps=7 format=2] [ext_resource path="res://interface/menus/Menu.tscn" type="PackedScene" id=1] [ext_resource path="res://interface/menus/pause/PauseMenu.gd" type="Script" id=2] [ext_resource path="res://interface/menus/shared/Button.tscn" type="PackedScene" id=3] [ext_resource path="res://interface/menus/save_and_load/SaveMenu.tscn" type="PackedScene" id=4] [ext_resource path="res://interface/menus/pause/OptionsMenu.tscn" type="PackedScene" id=5] [sub_resource type="GDScript" id=1] script/source = "extends VBoxContainer var focus_active = true setget set_focus_active func _ready(): self.focus_active = focus_active func set_focus_active(value): focus_active = true var focus_mode = FOCUS_ALL if focus_active else FOCUS_NONE for child in get_children(): child.focus_mode = focus_mode " [node name="PauseMenu" instance=ExtResource( 1 )] script = ExtResource( 2 ) [node name="DarkOverlay" type="ColorRect" parent="." index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 color = Color( 0, 0, 0, 0.313726 ) _sections_unfolded = [ "Visibility" ] [node name="Background" type="ColorRect" parent="." index="2"] anchor_left = 0.5 anchor_top = 0.5 anchor_right = 0.5 anchor_bottom = 0.5 margin_left = -300.0 margin_top = -280.0 margin_right = 300.0 margin_bottom = 280.0 rect_min_size = Vector2( 600, 0 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 color = Color( 0.136719, 0.136719, 0.136719, 1 ) _sections_unfolded = [ "Rect", "custom_constants" ] [node name="Column" type="VBoxContainer" parent="Background" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 rect_min_size = Vector2( 600, 0 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 alignment = 1 script = SubResource( 1 ) _sections_unfolded = [ "Focus", "Margin", "Rect", "Theme" ] [node name="Label" type="Label" parent="Background/Column" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 68.0 margin_right = 600.0 margin_bottom = 91.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 text = "Pause Menu" align = 1 valign = 1 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "Focus", "Theme" ] [node name="ContinueButton" parent="Background/Column" index="1" instance=ExtResource( 3 )] margin_left = 100.0 margin_top = 107.0 margin_right = 500.0 margin_bottom = 171.0 text = "Continue" [node name="ItemsButton" parent="Background/Column" index="2" instance=ExtResource( 3 )] margin_left = 100.0 margin_top = 187.0 margin_right = 500.0 margin_bottom = 251.0 text = "Items" [node name="SaveButton" parent="Background/Column" index="3" instance=ExtResource( 3 )] margin_left = 100.0 margin_top = 267.0 margin_right = 500.0 margin_bottom = 331.0 text = "Save" [node name="OptionsButton" parent="Background/Column" index="4" instance=ExtResource( 3 )] margin_left = 100.0 margin_top = 347.0 margin_right = 500.0 margin_bottom = 411.0 text = "Options" [node name="TitleScreenButton" parent="Background/Column" index="5" instance=ExtResource( 3 )] margin_left = 100.0 margin_top = 427.0 margin_right = 500.0 margin_bottom = 491.0 text = "Title Screen" [node name="SaveMenu" parent="." index="3" instance=ExtResource( 4 )] visible = false [node name="OptionsMenu" parent="." index="4" instance=ExtResource( 5 )] visible = false [connection signal="pressed" from="Background/Column/ContinueButton" to="." method="close"] [connection signal="pressed" from="Background/Column/TitleScreenButton" to="." method="close"] ================================================ FILE: interface/menus/pause/SoundController.gd ================================================ tool extends Panel onready var audio_bus_label = $Row/Label onready var amount_label = $Row/Amount onready var slider = $Row/HSlider export(String, "Music", "World", "Interface") var BUS_NAME = "Music" var audio_bus_index func _ready(): audio_bus_index = AudioServer.get_bus_index(BUS_NAME) audio_bus_label.text = BUS_NAME var volume_db = AudioServer.get_bus_volume_db(audio_bus_index) slider.value = round(min(db2linear(volume_db) * 100.0, 100.0)) func change_volume(value): var volume = max(linear2db(value / slider.max_value), -80.0) AudioServer.set_bus_volume_db(audio_bus_index, volume) ================================================ FILE: interface/menus/pause/SoundController.tscn ================================================ [gd_scene load_steps=5 format=2] [ext_resource path="res://interface/default.theme" type="Theme" id=1] [ext_resource path="res://interface/menus/pause/SoundController.gd" type="Script" id=2] [ext_resource path="res://interface/theme/fonts/source_code_pro_26.tres" type="DynamicFont" id=3] [sub_resource type="GDScript" id=2] resource_local_to_scene = true script/source = "extends Label func _on_HSlider_value_changed(value): text = str(value) " _sections_unfolded = [ "Resource" ] [node name="SoundController" type="Panel" index="0"] anchor_left = 0.5 anchor_top = 0.5 anchor_right = 0.5 anchor_bottom = 0.5 margin_left = -390.0 margin_top = -110.0 margin_right = 390.0 margin_bottom = 110.0 rect_min_size = Vector2( 780, 140 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 theme = ExtResource( 1 ) script = ExtResource( 2 ) _sections_unfolded = [ "Focus", "Rect", "Theme" ] [node name="Row" type="HBoxContainer" parent="." index="0"] anchor_left = 0.5 anchor_top = 0.5 anchor_right = 0.5 anchor_bottom = 0.5 margin_left = -320.0 margin_top = -80.0 margin_right = 320.0 margin_bottom = 80.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 alignment = 0 _sections_unfolded = [ "Focus" ] [node name="Label" type="Label" parent="Row" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_right = 140.0 margin_bottom = 160.0 rect_min_size = Vector2( 140, 0 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 5 custom_fonts/font = ExtResource( 3 ) text = "Music" valign = 1 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "Focus", "Rect", "custom_colors", "custom_fonts" ] [node name="HSlider" type="HSlider" parent="Row" index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 156.0 margin_right = 576.0 margin_bottom = 160.0 rect_min_size = Vector2( 0, 140 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false focus_mode = 2 mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 3 size_flags_vertical = 1 min_value = 0.0 max_value = 100.0 step = 10.0 page = 0.0 value = 58.0 exp_edit = false rounded = false editable = true tick_count = 0 ticks_on_borders = false focus_mode = 2 _sections_unfolded = [ "Focus" ] [node name="Amount" type="Label" parent="Row" index="2"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 592.0 margin_top = 63.0 margin_right = 640.0 margin_bottom = 97.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 custom_fonts/font = ExtResource( 3 ) text = "100" align = 1 valign = 2 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 script = SubResource( 2 ) _sections_unfolded = [ "custom_colors", "custom_fonts" ] [connection signal="value_changed" from="Row/HSlider" to="." method="change_volume"] [connection signal="value_changed" from="Row/HSlider" to="Row/Amount" method="_on_HSlider_value_changed"] ================================================ FILE: interface/menus/save_and_load/SaveMenu.gd ================================================ extends Menu onready var save_button = $Panel/Column/SaveButton onready var load_button = $Panel/Column/LoadButton func open(args={}): .open() save_button.grab_focus() ================================================ FILE: interface/menus/save_and_load/SaveMenu.tscn ================================================ [gd_scene load_steps=5 format=2] [ext_resource path="res://interface/menus/Menu.tscn" type="PackedScene" id=1] [ext_resource path="res://interface/menus/save_and_load/SaveMenu.gd" type="Script" id=2] [ext_resource path="res://interface/default.theme" type="Theme" id=3] [ext_resource path="res://interface/theme/fonts/default_font_comfortaa.tres" type="DynamicFont" id=4] [node name="SaveMenu" instance=ExtResource( 1 )] script = ExtResource( 2 ) [node name="Panel" type="Panel" parent="." index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false focus_mode = 2 mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 theme = ExtResource( 3 ) _sections_unfolded = [ "Focus", "Theme" ] [node name="Column" type="VBoxContainer" parent="Panel" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 margin_left = 570.0 margin_top = 147.0 margin_right = -570.0 margin_bottom = -147.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 alignment = 1 _sections_unfolded = [ "Focus" ] [node name="Title" type="Label" parent="Panel/Column" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 211.0 margin_right = 780.0 margin_bottom = 246.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 custom_fonts/font = ExtResource( 4 ) text = "Save and Load" align = 1 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "Focus", "custom_fonts" ] [node name="HSeparator" type="HSeparator" parent="Panel/Column" index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 262.0 margin_right = 780.0 margin_bottom = 266.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 [node name="SaveButton" type="Button" parent="Panel/Column" index="2"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 282.0 margin_right = 780.0 margin_bottom = 362.0 rect_min_size = Vector2( 0, 80 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false focus_mode = 2 mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 custom_fonts/font = ExtResource( 4 ) toggle_mode = false enabled_focus_mode = 2 shortcut = null group = null text = "Save" flat = false align = 1 _sections_unfolded = [ "Focus", "custom_fonts" ] [node name="LoadButton" type="Button" parent="Panel/Column" index="3"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 378.0 margin_right = 780.0 margin_bottom = 458.0 rect_min_size = Vector2( 0, 80 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false focus_mode = 2 mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 custom_fonts/font = ExtResource( 4 ) toggle_mode = false enabled_focus_mode = 2 shortcut = null group = null text = "Load" flat = false align = 1 _sections_unfolded = [ "Focus", "custom_fonts" ] [node name="HSeparator2" type="HSeparator" parent="Panel/Column" index="4"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 474.0 margin_right = 780.0 margin_bottom = 478.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 [node name="GoBackButton" type="Button" parent="Panel/Column" index="5"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 494.0 margin_right = 780.0 margin_bottom = 574.0 rect_min_size = Vector2( 0, 80 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false focus_mode = 2 mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 toggle_mode = false enabled_focus_mode = 2 shortcut = null group = null text = "Go back" flat = false align = 1 _sections_unfolded = [ "Focus", "Rect" ] [connection signal="pressed" from="Panel/Column/GoBackButton" to="." method="close"] ================================================ FILE: interface/menus/shared/Button.gd ================================================ extends Button func _gui_input(event): if event.is_action_pressed('ui_accept'): accept_event() ================================================ FILE: interface/menus/shared/Button.tscn ================================================ [gd_scene format=2] [node name="Button" type="Button"] editor/display_folded = true anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_right = 400.0 margin_bottom = 64.0 rect_min_size = Vector2( 400, 64 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false focus_mode = 2 mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 4 size_flags_vertical = 4 toggle_mode = false enabled_focus_mode = 2 shortcut = null group = null text = "Button" flat = false align = 1 _sections_unfolded = [ "Rect", "Theme" ] ================================================ FILE: interface/menus/shop/ShopMenu.gd ================================================ extends Menu export(PackedScene) var BuyMenu = preload("menus/BuySubMenu.tscn") export(PackedScene) var SellMenu = preload("menus/SellSubMenu.tscn") onready var buttons = $Column/Buttons onready var submenu = $Column/Menu onready var button_buy = $Column/Buttons/BuyButton onready var button_sell = $Column/Buttons/SellButton func _ready(): hide() """args: {shop, buyer}""" func open(args={}): assert(args.size() == 2) var shop = args['shop'] var buyer = args['buyer'] button_buy.connect("pressed", self, "open_submenu", [BuyMenu, { 'shop':shop, 'buyer':buyer, 'inventory':shop.inventory}]) button_sell.connect("pressed", self, "open_submenu", [SellMenu, { 'shop':shop, 'buyer':buyer, 'inventory':buyer.get_node("Inventory")}]) .open() buttons.get_child(0).grab_focus() func close(): button_buy.disconnect('pressed', self, 'open_submenu') button_sell.disconnect('pressed', self, 'open_submenu') .close() """args: shop, buyer, inventory""" func open_submenu(Menu, args={}): assert(args.size() == 3) var shop = args['shop'] var buyer = args['buyer'] var inventory = args['inventory'] var pressed_button = get_focus_owner() var active_menu = Menu.instance() submenu.add_child(active_menu) active_menu.initialize({'shop':shop, 'buyer':buyer, 'items':inventory.get_items()}) set_process_input(false) active_menu.open() yield(active_menu, "closed") set_process_input(true) pressed_button.grab_focus() func _on_QuitButton_pressed(): close() ================================================ FILE: interface/menus/shop/ShopMenu.tscn ================================================ [gd_scene load_steps=6 format=2] [ext_resource path="res://interface/menus/Menu.tscn" type="PackedScene" id=1] [ext_resource path="res://interface/menus/shop/ShopMenu.gd" type="Script" id=2] [ext_resource path="res://interface/menus/shop/menus/BuySubMenu.tscn" type="PackedScene" id=3] [ext_resource path="res://interface/menus/shop/menus/SellSubMenu.tscn" type="PackedScene" id=4] [ext_resource path="res://interface/menus/MenuTitle.tscn" type="PackedScene" id=5] [node name="ShopMenu" instance=ExtResource( 1 )] script = ExtResource( 2 ) BuyMenu = ExtResource( 3 ) SellMenu = ExtResource( 4 ) [node name="DarkOverlay" type="ColorRect" parent="." index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 color = Color( 0, 0, 0, 0.313726 ) [node name="Column" type="VBoxContainer" parent="." index="2"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 alignment = 0 _sections_unfolded = [ "custom_constants" ] [node name="TitlePanel" parent="Column" index="0" instance=ExtResource( 5 )] title = "Terrence's shop" [node name="Buttons" type="HBoxContainer" parent="Column" index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 96.0 margin_right = 1920.0 margin_bottom = 166.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 alignment = 0 [node name="BuyButton" type="Button" parent="Column/Buttons" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_right = 629.0 margin_bottom = 70.0 rect_min_size = Vector2( 0, 70 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false focus_mode = 2 mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 3 size_flags_vertical = 1 toggle_mode = false enabled_focus_mode = 2 shortcut = null group = null text = "Buy" flat = false align = 1 [node name="SellButton" type="Button" parent="Column/Buttons" index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 645.0 margin_right = 1274.0 margin_bottom = 70.0 rect_min_size = Vector2( 0, 70 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false focus_mode = 2 mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 3 size_flags_vertical = 1 toggle_mode = false enabled_focus_mode = 2 shortcut = null group = null text = "Sell" flat = false align = 1 [node name="QuitButton" type="Button" parent="Column/Buttons" index="2"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 1290.0 margin_right = 1920.0 margin_bottom = 70.0 rect_min_size = Vector2( 0, 70 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false focus_mode = 2 mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 3 size_flags_vertical = 1 toggle_mode = false enabled_focus_mode = 2 shortcut = null group = null text = "Quit" flat = false align = 1 [node name="Menu" type="Control" parent="Column" index="2"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 182.0 margin_right = 1920.0 margin_bottom = 1080.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 3 [connection signal="pressed" from="Column/Buttons/QuitButton" to="." method="_on_QuitButton_pressed"] ================================================ FILE: interface/menus/shop/menus/BuySubMenu.tscn ================================================ [gd_scene load_steps=5 format=2] [ext_resource path="res://interface/menus/shop/menus/ShopSubMenu.tscn" type="PackedScene" id=1] [ext_resource path="res://audio/sfx/menu_confirm.wav" type="AudioStream" id=2] [ext_resource path="res://audio/sfx/menu_navigate_01.wav" type="AudioStream" id=3] [ext_resource path="res://audio/sfx/menu_popup_open.wav" type="AudioStream" id=4] [node name="BuySubMenu" instance=ExtResource( 1 )] ACTION = "sell_to" [node name="Sfx" type="Node" parent="." index="0"] [node name="Confirm" type="AudioStreamPlayer" parent="Sfx" index="0"] stream = ExtResource( 2 ) volume_db = 0.0 pitch_scale = 1.0 autoplay = false mix_target = 0 bus = "Interface" [node name="Navigate" type="AudioStreamPlayer" parent="Sfx" index="1"] stream = ExtResource( 3 ) volume_db = 0.0 pitch_scale = 1.0 autoplay = false mix_target = 0 bus = "Interface" [node name="Open" type="AudioStreamPlayer" parent="Sfx" index="2"] stream = ExtResource( 4 ) volume_db = 0.0 pitch_scale = 1.0 autoplay = false mix_target = 0 bus = "Interface" ================================================ FILE: interface/menus/shop/menus/SellSubMenu.tscn ================================================ [gd_scene load_steps=2 format=2] [ext_resource path="res://interface/menus/shop/menus/ShopSubMenu.tscn" type="PackedScene" id=1] [node name="SellSubMenu" instance=ExtResource( 1 )] ACTION = "buy_from" ================================================ FILE: interface/menus/shop/menus/ShopSubMenu.gd ================================================ extends Menu export(String, "sell_to", "buy_from") var ACTION = "" onready var items_list = $Column/Row/ShopItemsList onready var description_panel = $Column/DescriptionPanel onready var info_panel = $Column/Row/InfoPanel onready var amount_popup = items_list.get_node("AmountPopup") func _ready(): assert(ACTION != "") """Args: {shop, buyer, items}""" func initialize(args={}): assert(args.size() == 3) # Extract the nodes from the args dict to preserve legacy code below var shop = args['shop'] var items = args['items'] var buyer = args['buyer'] var purse = buyer.get_purse() info_panel.initialize(purse) for item in items: var price = shop.get_buy_value(item) if ACTION == "buy_from" else item.price var item_button = items_list.add_item_button(item, price, purse) item_button.connect("pressed", self, "_on_ItemButton_pressed", [shop, buyer, item]) item_button.connect("pressed", info_panel, "_on_focused_Item_amount_changed", [item]) items_list.connect("focused_button_changed", self, "_on_ItemList_focused_button_changed") items_list.initialize() func _on_ItemList_focused_button_changed(item_button): description_panel.display(item_button.description) func open(args={}): .open() items_list.get_child(0).grab_focus() func close(): .close() queue_free() func _on_ItemButton_pressed(shop, buyer, item): var price = shop.get_buy_value(item) if ACTION == "buy_from" else item.price var coins = shop.get_purse().coins if ACTION == "buy_from" else buyer.get_purse().coins var max_amount = min(item.amount, floor(coins / price)) var focused_item = get_focus_owner() amount_popup.initialize({'value': 1, 'max_value': max_amount}) var amount = yield(amount_popup.open(), "completed") focused_item.grab_focus() if not amount: return shop.call(ACTION, buyer, item, amount) ================================================ FILE: interface/menus/shop/menus/ShopSubMenu.tscn ================================================ [gd_scene load_steps=7 format=2] [ext_resource path="res://interface/menus/Menu.tscn" type="PackedScene" id=1] [ext_resource path="res://interface/menus/shop/menus/ShopSubMenu.gd" type="Script" id=2] [ext_resource path="res://interface/default.theme" type="Theme" id=3] [ext_resource path="res://interface/menus/shop/panels/ShopItemsList.tscn" type="PackedScene" id=4] [ext_resource path="res://interface/menus/shop/panels/InfoPanel.tscn" type="PackedScene" id=5] [ext_resource path="res://interface/menus/shop/panels/DescriptionPanel.tscn" type="PackedScene" id=6] [node name="ShopSubMenu" index="0" instance=ExtResource( 1 )] script = ExtResource( 2 ) ACTION = "" [node name="Column" type="VBoxContainer" parent="." index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 3 theme = ExtResource( 3 ) alignment = 0 _sections_unfolded = [ "Rect", "Theme" ] [node name="Row" type="HBoxContainer" parent="Column" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_right = 1920.0 margin_bottom = 964.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 3 size_flags_vertical = 3 alignment = 0 _sections_unfolded = [ "Size Flags" ] [node name="ShopItemsList" parent="Column/Row" index="0" instance=ExtResource( 4 )] anchor_right = 0.0 anchor_bottom = 0.0 margin_right = 1504.0 margin_bottom = 964.0 [node name="InfoPanel" parent="Column/Row" index="1" instance=ExtResource( 5 )] margin_left = 1520.0 margin_right = 1920.0 margin_bottom = 964.0 [node name="DescriptionPanel" parent="Column" index="1" instance=ExtResource( 6 )] margin_top = 980.0 margin_right = 1920.0 margin_bottom = 1080.0 [connection signal="focused_button_changed" from="Column/Row/ShopItemsList" to="Column/Row/InfoPanel" method="_on_ItemsList_focused_button_changed"] [connection signal="item_amount_changed" from="Column/Row/ShopItemsList" to="Column/Row/InfoPanel" method="_on_ItemsList_item_amount_changed"] ================================================ FILE: interface/menus/shop/panels/DescriptionPanel.gd ================================================ extends Panel func display(message): $Description.text = message ================================================ FILE: interface/menus/shop/panels/DescriptionPanel.tscn ================================================ [gd_scene load_steps=2 format=2] [ext_resource path="res://interface/menus/shop/panels/DescriptionPanel.gd" type="Script" id=1] [node name="DescriptionPanel" type="Panel"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_top = 620.0 margin_right = 1280.0 margin_bottom = 720.0 rect_min_size = Vector2( 0, 100 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 script = ExtResource( 1 ) _sections_unfolded = [ "Rect" ] [node name="Description" type="Label" parent="." index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 40.0 margin_top = 20.0 margin_right = 1240.0 margin_bottom = 81.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 text = "Item descripton here. " autowrap = true percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 ================================================ FILE: interface/menus/shop/panels/InfoPanel.gd ================================================ extends Control onready var _money_label = $MoneyPanel/Count onready var _owned_label = $OwnedPanel/Count func initialize(purse): purse.connect("coins_changed", self, "_on_Purse_coins_changed") update_coins(purse.coins) func update_coins(amount): _money_label.text = str(amount) func update_amount(amount): _owned_label.text = str(amount) func _on_Purse_coins_changed(coins): update_coins(coins) func _on_focused_Item_amount_changed(item): update_amount(item.amount) func _on_ItemsList_focused_button_changed(button): update_amount(button.amount) func _on_ItemsList_item_amount_changed(amount): update_amount(amount) ================================================ FILE: interface/menus/shop/panels/InfoPanel.tscn ================================================ [gd_scene load_steps=4 format=2] [ext_resource path="res://interface/menus/shop/panels/InfoPanel.gd" type="Script" id=1] [ext_resource path="res://interface/theme/icons/coins.png" type="Texture" id=2] [ext_resource path="res://interface/theme/icons/purse.png" type="Texture" id=3] [node name="InfoPanel" type="Panel" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 880.0 margin_right = 1280.0 margin_bottom = 462.0 rect_min_size = Vector2( 400, 0 ) rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 script = ExtResource( 1 ) _sections_unfolded = [ "Rect" ] [node name="MoneyPanel" type="Panel" parent="." index="0"] anchor_left = 0.5 anchor_top = 0.0 anchor_right = 0.5 anchor_bottom = 0.0 margin_left = -180.0 margin_top = 18.0 margin_right = 180.0 margin_bottom = 78.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 [node name="Label" type="Label" parent="MoneyPanel" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 margin_left = 20.0 margin_right = -20.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 text = "Purse" valign = 1 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 [node name="Count" type="Label" parent="MoneyPanel" index="1"] anchor_left = 1.0 anchor_top = 0.5 anchor_right = 1.0 anchor_bottom = 0.5 margin_left = -240.0 margin_top = -30.0 margin_right = -60.0 margin_bottom = 30.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 text = "1600" align = 2 valign = 1 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 [node name="CoinsIcon" type="TextureRect" parent="MoneyPanel" index="2"] anchor_left = 1.0 anchor_top = 0.5 anchor_right = 1.0 anchor_bottom = 0.5 margin_left = -52.0 margin_top = -16.0 margin_right = -20.0 margin_bottom = 16.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 texture = ExtResource( 2 ) stretch_mode = 0 [node name="OwnedPanel" type="Panel" parent="." index="1"] anchor_left = 0.5 anchor_top = 0.0 anchor_right = 0.5 anchor_bottom = 0.0 margin_left = -180.0 margin_top = 98.0 margin_right = 180.0 margin_bottom = 158.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 [node name="Label" type="Label" parent="OwnedPanel" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 margin_left = 20.0 margin_right = -20.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 text = "Available" valign = 1 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 [node name="Count" type="Label" parent="OwnedPanel" index="1"] anchor_left = 1.0 anchor_top = 0.5 anchor_right = 1.0 anchor_bottom = 0.5 margin_left = -240.0 margin_top = -30.0 margin_right = -60.0 margin_bottom = 30.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 text = "4" align = 2 valign = 1 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 [node name="PurseIcon" type="TextureRect" parent="OwnedPanel" index="2"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 308.0 margin_top = 14.0 margin_right = 340.0 margin_bottom = 46.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 texture = ExtResource( 3 ) stretch_mode = 0 ================================================ FILE: interface/menus/shop/panels/ShopItemsList.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://interface/items/ItemsList.tscn" type="PackedScene" id=1] [ext_resource path="res://interface/menus/shop/popups/AmountPopup.tscn" type="PackedScene" id=2] [node name="ShopItemsList" instance=ExtResource( 1 )] [node name="AmountPopup" parent="." index="1" instance=ExtResource( 2 )] visible = false ================================================ FILE: interface/menus/shop/popups/AmountLabel.gd ================================================ extends Label var _max_value func initialize(value, max_value): _max_value = max_value update_text(value) func update_text(value): text = "%s/%s" % [value, _max_value] func _on_HSlider_value_changed(value): update_text(value) ================================================ FILE: interface/menus/shop/popups/AmountPopup.gd ================================================ extends Menu signal amount_confirmed(value) onready var popup = $Popup onready var slider = $Popup/VBoxContainer/Slider/HSlider onready var label = $Popup/VBoxContainer/Slider/Amount """args: {value, max_value}""" func initialize(args={}): assert(args.size() == 2) var value = args['value'] var max_value = args['max_value'] label.initialize(value, max_value) slider.initialize(value, max_value) slider.grab_focus() func open(args={}): popup.popup_centered() .open() var amount = yield(self, "amount_confirmed") close() return amount func _input(event): if event.is_action_pressed("ui_cancel"): emit_signal("amount_confirmed", 0) accept_event() elif event.is_action_pressed("ui_accept"): emit_signal("amount_confirmed", slider.value) accept_event() ================================================ FILE: interface/menus/shop/popups/AmountPopup.tscn ================================================ [gd_scene load_steps=6 format=2] [ext_resource path="res://interface/menus/shop/popups/AmountPopup.gd" type="Script" id=1] [ext_resource path="res://interface/menus/MenuSfx.tscn" type="PackedScene" id=2] [ext_resource path="res://interface/default.theme" type="Theme" id=3] [ext_resource path="res://interface/menus/shop/popups/HSlider.gd" type="Script" id=4] [sub_resource type="GDScript" id=1] resource_local_to_scene = true script/source = "extends Label var _max_value func initialize(value, max_value): _max_value = max_value update_text(value) func _on_HSlider_value_changed(value): update_text(value) func update_text(value): text = \"%s/%s\" % [value, _max_value] " [node name="AmountPopup" type="Control"] margin_right = 40.0 margin_bottom = 40.0 script = ExtResource( 1 ) [node name="MenuSfx" parent="." instance=ExtResource( 2 )] [node name="Popup" type="PopupPanel" parent="."] visible = true margin_right = 300.0 margin_bottom = 300.0 rect_min_size = Vector2( 300, 120 ) theme = ExtResource( 3 ) popup_exclusive = true [node name="VBoxContainer" type="VBoxContainer" parent="Popup"] anchor_right = 1.0 anchor_bottom = 1.0 margin_left = 2.0 margin_top = 2.0 margin_right = -2.0 margin_bottom = -2.0 [node name="Title" type="Label" parent="Popup/VBoxContainer"] margin_right = 296.0 margin_bottom = 60.0 rect_min_size = Vector2( 0, 60 ) text = "Amount" align = 1 valign = 1 [node name="Slider" type="Control" parent="Popup/VBoxContainer"] margin_top = 76.0 margin_right = 296.0 margin_bottom = 216.0 rect_min_size = Vector2( 0, 140 ) [node name="Amount" type="Label" parent="Popup/VBoxContainer/Slider"] anchor_right = 1.0 margin_top = 34.0 margin_bottom = 57.0 text = "6/8" align = 1 valign = 1 script = SubResource( 1 ) [node name="HSlider" type="HSlider" parent="Popup/VBoxContainer/Slider"] anchor_top = 0.5 anchor_right = 1.0 anchor_bottom = 0.5 margin_left = 20.0 margin_top = -7.0 margin_right = -20.0 margin_bottom = 9.0 max_value = 8.0 value = 6.0 script = ExtResource( 4 ) [node name="OkButton" type="Button" parent="Popup/VBoxContainer"] margin_left = 18.0 margin_top = 232.0 margin_right = 278.0 margin_bottom = 272.0 rect_min_size = Vector2( 260, 40 ) size_flags_horizontal = 4 text = "OK" [connection signal="value_changed" from="Popup/VBoxContainer/Slider/HSlider" to="Popup/VBoxContainer/Slider/Amount" method="_on_HSlider_value_changed"] ================================================ FILE: interface/menus/shop/popups/HSlider.gd ================================================ extends HSlider func initialize(current, maximum): max_value = maximum value = current ================================================ FILE: interface/theme/fonts/comfortaa_tips.tres ================================================ [gd_resource type="DynamicFont" load_steps=2 format=2] [ext_resource path="res://interface/theme/fonts/Comfortaa-Bold.ttf" type="DynamicFontData" id=1] [resource] size = 22 use_mipmaps = false use_filter = true font_data = ExtResource( 1 ) _sections_unfolded = [ "Extra Spacing", "Font", "Settings" ] ================================================ FILE: interface/theme/fonts/default_font_comfortaa.tres ================================================ [gd_resource type="DynamicFont" load_steps=2 format=2] [ext_resource path="res://interface/theme/fonts/Comfortaa-Bold.ttf" type="DynamicFontData" id=1] [resource] size = 30 use_mipmaps = false use_filter = true font_data = ExtResource( 1 ) ================================================ FILE: interface/theme/fonts/source_code_pro_26.tres ================================================ [gd_resource type="DynamicFont" load_steps=2 format=2] [ext_resource path="res://interface/theme/fonts/SourceCodePro-Regular.ttf" type="DynamicFontData" id=1] [resource] size = 26 use_mipmaps = false use_filter = true font_data = ExtResource( 1 ) _sections_unfolded = [ "Font", "Settings" ] ================================================ FILE: interface/theme/icons/add.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/add.png-a2d973072fa729536972b5d9b7b2035f.stex" metadata={ "vram_texture": false } [deps] source_file="res://interface/theme/icons/add.png" dest_files=[ "res://.import/add.png-a2d973072fa729536972b5d9b7b2035f.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: interface/theme/icons/cancel.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/cancel.png-037fe98dac59e9a85d5be364d636db68.stex" metadata={ "vram_texture": false } [deps] source_file="res://interface/theme/icons/cancel.png" dest_files=[ "res://.import/cancel.png-037fe98dac59e9a85d5be364d636db68.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: interface/theme/icons/coins.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/coins.png-d3cc02b051752e916d567a271598e8e8.stex" metadata={ "vram_texture": false } [deps] source_file="res://interface/theme/icons/coins.png" dest_files=[ "res://.import/coins.png-d3cc02b051752e916d567a271598e8e8.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: interface/theme/icons/fire_scroll.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/fire_scroll.png-ea84ffcfb65793b96e965f4d5bd34780.stex" metadata={ "vram_texture": false } [deps] source_file="res://interface/theme/icons/fire_scroll.png" dest_files=[ "res://.import/fire_scroll.png-ea84ffcfb65793b96e965f4d5bd34780.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: interface/theme/icons/potion_health.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/potion_health.png-e775c0060582f7b89180f1d376299720.stex" metadata={ "vram_texture": false } [deps] source_file="res://interface/theme/icons/potion_health.png" dest_files=[ "res://.import/potion_health.png-e775c0060582f7b89180f1d376299720.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: interface/theme/icons/potion_mana.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/potion_mana.png-7aa82fe7a278054b00e2e350eab56c9c.stex" metadata={ "vram_texture": false } [deps] source_file="res://interface/theme/icons/potion_mana.png" dest_files=[ "res://.import/potion_mana.png-7aa82fe7a278054b00e2e350eab56c9c.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: interface/theme/icons/purse.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/purse.png-98ac931d0e1f2927c25fc95f9b1cc6af.stex" metadata={ "vram_texture": false } [deps] source_file="res://interface/theme/icons/purse.png" dest_files=[ "res://.import/purse.png-98ac931d0e1f2927c25fc95f9b1cc6af.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: interface/theme/icons/remove.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/remove.png-0d204696e7aa93085028f1e68e1459d2.stex" metadata={ "vram_texture": false } [deps] source_file="res://interface/theme/icons/remove.png" dest_files=[ "res://.import/remove.png-0d204696e7aa93085028f1e68e1459d2.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: interface/theme/icons/sword.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/sword.png-217a5d3b34aaecc05313ecaf68a75610.stex" metadata={ "vram_texture": false } [deps] source_file="res://interface/theme/icons/sword.png" dest_files=[ "res://.import/sword.png-217a5d3b34aaecc05313ecaf68a75610.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: levels/Cave.tscn ================================================ [gd_scene load_steps=10 format=2] [ext_resource path="res://core/world/tilesets/cave/cave.tres" type="TileSet" id=1] [ext_resource path="res://monsters/BossShakingCamera.tscn" type="PackedScene" id=2] [ext_resource path="res://core/world/PlayerSpawningPoint.tscn" type="PackedScene" id=3] [ext_resource path="res://core/world/Door.tscn" type="PackedScene" id=4] [ext_resource path="res://core/world/pit.png" type="Texture" id=5] [ext_resource path="res://monsters/bosses/wild_boar/WildBoar.tscn" type="PackedScene" id=6] [ext_resource path="res://actors/CoinsFountain.tscn" type="PackedScene" id=7] [sub_resource type="GDScript" id=1] script/source = "extends \"res://levels/Level.gd\" onready var camera = $BossShakingCamera onready var wild_boar = $YSort/WildBoar const PlayerController = preload(\"res://actors/player/PlayerController.gd\") func _ready(): camera.current = true func _on_CameraTrigger_body_entered(body): assert(body is PlayerController) camera.initialize(body) yield(camera.move_to_room_center(), \"completed\") wild_boar.start() func _on_WildBoar_died(): $Door.set_active(true) " [sub_resource type="GDScript" id=2] script/source = "extends Area2D func _on_body_entered(body): queue_free() " [node name="Cave" type="TileMap" index="0"] position = Vector2( 0, 32 ) mode = 0 tile_set = ExtResource( 1 ) cell_size = Vector2( 128, 128 ) cell_quadrant_size = 16 cell_custom_transform = Transform2D( 1, 0, 0, 1, 0, 0 ) cell_half_offset = 2 cell_tile_origin = 0 cell_y_sort = false cell_clip_uv = false collision_use_kinematic = false collision_friction = 1.0 collision_bounce = 0.0 collision_layer = 2 collision_mask = 1 occluder_light_mask = 1 format = 1 tile_data = PoolIntArray( 1, 0, 0, 2, 0, 1, 3, 0, 1, 4, 0, 1, 5, 0, 1, 6, 0, 1, 7, 0, 1, 8, 0, 1, 9, 0, 1, 10, 0, 1, 11, 0, 1, 12, 0, 1, 13, 0, 2, 65537, 0, 65536, 65538, 0, 65537, 65539, 0, 65537, 65540, 0, 65537, 65541, 0, 65537, 65542, 0, 65537, 65543, 0, 65537, 65544, 0, 65537, 65545, 0, 65537, 65546, 0, 65537, 65547, 0, 65537, 65548, 0, 65537, 65549, 0, 65538, 131073, 0, 65536, 131074, 0, 65537, 131075, 0, 65537, 131076, 0, 65537, 131077, 0, 65537, 131078, 0, 65537, 131079, 0, 65537, 131080, 0, 65537, 131081, 0, 65537, 131082, 0, 65537, 131083, 0, 65537, 131084, 0, 65537, 131085, 0, 65538, 196609, 0, 65536, 196610, 0, 65537, 196611, 0, 65537, 196612, 0, 65537, 196613, 0, 65537, 196614, 0, 65537, 196615, 0, 65537, 196616, 0, 65537, 196617, 0, 65537, 196618, 0, 65537, 196619, 0, 65537, 196620, 0, 65537, 196621, 0, 65538, 262145, 0, 65536, 262146, 0, 65537, 262147, 0, 65537, 262148, 0, 65537, 262149, 0, 65537, 262150, 0, 65537, 262151, 0, 65537, 262152, 0, 65537, 262153, 0, 65537, 262154, 0, 65537, 262155, 0, 65537, 262156, 0, 65537, 262157, 0, 65538, 327681, 0, 65536, 327682, 0, 65537, 327683, 0, 65537, 327684, 0, 65537, 327685, 0, 65537, 327686, 0, 65537, 327687, 0, 65537, 327688, 0, 65537, 327689, 0, 65537, 327690, 0, 65537, 327691, 0, 65537, 327692, 0, 65537, 327693, 0, 65538, 393217, 0, 65536, 393218, 0, 65537, 393219, 0, 65537, 393220, 0, 65537, 393221, 0, 65537, 393222, 0, 65537, 393223, 0, 65537, 393224, 0, 65537, 393225, 0, 65537, 393226, 0, 65537, 393227, 0, 65537, 393228, 0, 65537, 393229, 0, 65538, 458753, 0, 131072, 458754, 0, 131073, 458755, 0, 131073, 458756, 0, 131073, 458757, 0, 131073, 458758, 0, 4, 458759, 0, 65537, 458760, 0, 3, 458761, 0, 131073, 458762, 0, 131073, 458763, 0, 131073, 458764, 0, 131073, 458765, 0, 131074, 524294, 0, 65536, 524295, 0, 65537, 524296, 0, 65538, 589830, 0, 65536, 589831, 0, 65537, 589832, 0, 65539, 589833, 0, 2, 655366, 0, 65536, 655367, 0, 65537, 655368, 0, 3, 655369, 0, 131074, 720902, 0, 65536, 720903, 0, 65537, 720904, 0, 65538, 786437, 0, 0, 786438, 0, 65540, 786439, 0, 65537, 786440, 0, 65538, 851973, 0, 131072, 851974, 0, 4, 851975, 0, 65537, 851976, 0, 65538, 917510, 0, 65536, 917511, 0, 65537, 917512, 0, 65538, 983046, 0, 65536, 983047, 0, 65537, 983048, 0, 65538, 1048582, 0, 65536, 1048583, 0, 65537, 1048584, 0, 65538, 1114118, 0, 65536, 1114119, 0, 65537, 1114120, 0, 65538, 1179654, 0, 65536, 1179655, 0, 65537, 1179656, 0, 65538, 1245190, 0, 65536, 1245191, 0, 65537, 1245192, 0, 65538, 1310724, 0, 0, 1310725, 0, 1, 1310726, 0, 65540, 1310727, 0, 65537, 1310728, 0, 65539, 1310729, 0, 1, 1310730, 0, 2, 1376260, 0, 65536, 1376261, 0, 65537, 1376262, 0, 65537, 1376263, 0, 65537, 1376264, 0, 65537, 1376265, 0, 65537, 1376266, 0, 65538, 1441796, 0, 65536, 1441797, 0, 65537, 1441798, 0, 65537, 1441799, 0, 65537, 1441800, 0, 65537, 1441801, 0, 65537, 1441802, 0, 65538, 1507332, 0, 65536, 1507333, 0, 65537, 1507334, 0, 65537, 1507335, 0, 65537, 1507336, 0, 65537, 1507337, 0, 65537, 1507338, 0, 65538, 1572868, 0, 131072, 1572869, 0, 131073, 1572870, 0, 131073, 1572871, 0, 131073, 1572872, 0, 131073, 1572873, 0, 131073, 1572874, 0, 131074 ) script = SubResource( 1 ) _sections_unfolded = [ "Cell", "Collision", "Transform" ] __meta__ = { "_edit_lock_": true } fog = true [node name="BossShakingCamera" parent="." index="0" instance=ExtResource( 2 )] position = Vector2( 960, 408 ) current = false [node name="CameraTrigger" type="Area2D" parent="." index="1"] editor/display_folded = true input_pickable = true gravity_vec = Vector2( 0, 1 ) gravity = 98.0 linear_damp = 0.1 angular_damp = 1.0 monitorable = false collision_layer = 0 audio_bus_override = false audio_bus_name = "Master" script = SubResource( 2 ) _sections_unfolded = [ "Collision" ] [node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="CameraTrigger" index="0"] build_mode = 0 polygon = PoolVector2Array( 768, 896, 1152, 896, 1152, 1024, 768, 1024 ) [node name="PlayerSpawningPoint" parent="." index="2" instance=ExtResource( 3 )] position = Vector2( 960, 2912 ) [node name="Door" parent="." index="3" instance=ExtResource( 4 )] editor/display_folded = true visible = false position = Vector2( 1570, 208 ) map_path = "res://levels/Grasslands.tscn" ACTIVE_AT_START = false [node name="Stairs" parent="Door" index="0"] texture = ExtResource( 5 ) [node name="YSort" type="YSort" parent="." index="4"] sort_enabled = true [node name="WildBoar" parent="YSort" index="0" instance=ExtResource( 6 )] position = Vector2( 970, 528 ) [node name="CoinsFountain" parent="YSort" index="1" instance=ExtResource( 7 )] position = Vector2( 970, 528 ) MAX_SPAWN_COUNT = 16 [connection signal="body_entered" from="CameraTrigger" to="." method="_on_CameraTrigger_body_entered"] [connection signal="body_entered" from="CameraTrigger" to="CameraTrigger" method="_on_body_entered"] [connection signal="died" from="YSort/WildBoar" to="." method="_on_WildBoar_died"] [connection signal="died" from="YSort/WildBoar" to="YSort/CoinsFountain" method="start"] [connection signal="hit_wall" from="YSort/WildBoar" to="BossShakingCamera" method="_on_WildBoar_hit_wall"] [editable path="Door"] ================================================ FILE: levels/Grasslands.tscn ================================================ [gd_scene load_steps=9 format=2] [ext_resource path="res://levels/Level.gd" type="Script" id=1] [ext_resource path="res://core/world/tilesets/outdoor/outdoor.tres" type="TileSet" id=2] [ext_resource path="res://core/world/Gap.tscn" type="PackedScene" id=3] [ext_resource path="res://monsters/porcupine/Porcupine.tscn" type="PackedScene" id=4] [ext_resource path="res://monsters/mosquito/Nest.tscn" type="PackedScene" id=5] [ext_resource path="res://actors/characters/seller/Seller.tscn" type="PackedScene" id=6] [ext_resource path="res://core/world/PlayerSpawningPoint.tscn" type="PackedScene" id=7] [ext_resource path="res://core/world/Door.tscn" type="PackedScene" id=8] [node name="Grasslands" type="Node2D" index="0"] script = ExtResource( 1 ) _sections_unfolded = [ "Cell", "Collision" ] fog = false [node name="Ground" type="TileMap" parent="." index="0"] mode = 0 tile_set = ExtResource( 2 ) cell_size = Vector2( 128, 128 ) cell_quadrant_size = 16 cell_custom_transform = Transform2D( 1, 0, 0, 1, 0, 0 ) cell_half_offset = 2 cell_tile_origin = 0 cell_y_sort = false cell_clip_uv = false collision_use_kinematic = false collision_friction = 1.0 collision_bounce = 0.0 collision_layer = 1 collision_mask = 1 occluder_light_mask = 1 format = 1 tile_data = PoolIntArray( 0, 0, 65536, 1, 0, 65536, 2, 0, 65536, 3, 0, 65536, 4, 0, 65536, 5, 0, 65536, 6, 0, 65536, 7, 0, 65536, 8, 0, 65536, 9, 0, 65536, 10, 0, 65536, 11, 0, 65536, 12, 0, 65536, 13, 0, 65536, 14, 0, 65536, 15, 0, 65536, 16, 0, 65536, 17, 0, 65536, 18, 0, 65536, 19, 0, 65536, 20, 0, 65536, 21, 0, 65536, 22, 0, 65536, 23, 0, 65536, 24, 0, 65536, 25, 0, 65536, 26, 0, 65536, 27, 0, 65536, 28, 0, 65536, 29, 0, 65536, 30, 0, 65536, 31, 0, 65536, 32, 0, 65536, 33, 0, 65536, 34, 0, 65536, 35, 0, 65536, 36, 0, 65536, 37, 0, 65536, 38, 0, 65536, 39, 0, 65536, 40, 0, 65536, 41, 0, 65536, 42, 0, 65536, 43, 0, 65536, 44, 0, 65536, 45, 0, 65536, 46, 0, 65536, 65536, 0, 65536, 65537, 0, 65536, 65538, 0, 2, 65539, 0, 65536, 65540, 0, 65536, 65541, 0, 65536, 65542, 0, 65536, 65543, 1, 0, 65544, 1, 1, 65545, 1, 1, 65546, 1, 1, 65547, 1, 1, 65548, 1, 1, 65549, 1, 1, 65550, 1, 1, 65551, 1, 1, 65552, 1, 1, 65553, 1, 1, 65554, 1, 1, 65555, 1, 2, 65556, 0, 65536, 65557, 0, 0, 65558, 0, 65536, 65559, 0, 65536, 65560, 0, 65536, 65561, 0, 0, 65562, 0, 65536, 65563, 0, 65536, 65564, 0, 0, 65565, 0, 65536, 65566, 0, 65536, 65567, 0, 65536, 65568, 0, 0, 65569, 0, 2, 65570, 0, 65536, 65571, 0, 65536, 65572, 0, 65536, 65573, 0, 65536, 65574, 0, 65536, 65575, 0, 65536, 65576, 0, 65536, 65577, 0, 65536, 65578, 0, 65536, 65579, 0, 65536, 65580, 0, 65536, 65581, 0, 65536, 65582, 0, 65536, 131072, 0, 65536, 131073, 0, 65536, 131074, 0, 65536, 131075, 0, 65536, 131076, 1, 0, 131077, 1, 1, 131078, 1, 1, 131079, 1, 65540, 131080, 1, 65537, 131081, 1, 65537, 131082, 1, 65537, 131083, 1, 65537, 131084, 1, 65537, 131085, 1, 65537, 131086, 1, 65537, 131087, 1, 65537, 131088, 1, 65537, 131089, 1, 65537, 131090, 1, 65537, 131091, 1, 65538, 131092, 0, 65536, 131093, 0, 65536, 131094, 0, 0, 131095, 0, 65536, 131096, 0, 65536, 131097, 0, 65536, 131098, 0, 65536, 131099, 0, 65536, 131100, 0, 65536, 131101, 0, 65536, 131102, 0, 65536, 131103, 0, 65536, 131104, 0, 65536, 131105, 0, 65536, 131106, 0, 65536, 131107, 0, 65536, 131108, 0, 65536, 131109, 0, 65536, 131110, 0, 65536, 131111, 0, 65536, 131112, 0, 65536, 131113, 0, 65536, 131114, 0, 65536, 131115, 0, 65536, 131116, 0, 65536, 131117, 0, 65536, 131118, 0, 65536, 196608, 0, 65536, 196609, 0, 65536, 196610, 0, 65536, 196611, 0, 65536, 196612, 1, 65536, 196613, 1, 65537, 196614, 1, 65537, 196615, 1, 65537, 196616, 1, 65537, 196617, 1, 65537, 196618, 1, 65537, 196619, 1, 65537, 196620, 1, 65537, 196621, 1, 65537, 196622, 1, 65537, 196623, 1, 65537, 196624, 1, 65537, 196625, 1, 65537, 196626, 1, 65537, 196627, 1, 65538, 196628, 0, 65536, 196629, 0, 65536, 196630, 0, 2, 196631, 0, 65536, 196632, 0, 65536, 196633, 0, 65536, 196634, 0, 65536, 196635, 0, 65536, 196636, 0, 65536, 196637, 0, 65536, 196638, 0, 65536, 196639, 0, 65536, 196640, 0, 65536, 196641, 0, 65536, 196642, 0, 65536, 196643, 0, 65536, 196644, 0, 65536, 196645, 0, 65536, 196646, 0, 65536, 196647, 0, 65536, 196648, 0, 65536, 196649, 0, 65536, 196650, 0, 65536, 196651, 0, 65536, 196652, 0, 65536, 196653, 0, 65536, 196654, 0, 65536, 262144, 0, 65536, 262145, 0, 65536, 262146, 0, 65536, 262147, 1, 0, 262148, 1, 65540, 262149, 1, 65537, 262150, 1, 65537, 262151, 1, 65537, 262152, 1, 65537, 262153, 1, 65537, 262154, 1, 65537, 262155, 1, 65537, 262156, 1, 65537, 262157, 1, 65537, 262158, 1, 65537, 262159, 1, 65537, 262160, 1, 65537, 262161, 1, 65537, 262162, 1, 65537, 262163, 1, 65538, 262164, 0, 65536, 262165, 0, 65536, 262166, 0, 65536, 262167, 0, 65536, 262168, 0, 65536, 262169, 0, 65536, 262170, 0, 65536, 262171, 0, 65536, 262172, 0, 65536, 262173, 0, 65536, 262174, 0, 65536, 262175, 0, 65536, 262176, 0, 65536, 262177, 0, 65536, 262178, 0, 65536, 262179, 0, 65536, 262180, 0, 65536, 262181, 0, 65536, 262182, 0, 65536, 262183, 0, 65536, 262184, 0, 65536, 262185, 0, 65536, 262186, 0, 0, 262187, 0, 65536, 262188, 0, 65536, 262189, 0, 65536, 262190, 0, 65536, 327680, 0, 65536, 327681, 0, 65536, 327682, 0, 65536, 327683, 1, 65536, 327684, 1, 65537, 327685, 1, 65537, 327686, 1, 65537, 327687, 1, 65537, 327688, 1, 65537, 327689, 1, 196609, 327690, 1, 65537, 327691, 1, 65537, 327692, 1, 65537, 327693, 1, 65537, 327694, 1, 65537, 327695, 1, 65537, 327696, 1, 65537, 327697, 1, 65537, 327698, 1, 65537, 327699, 1, 65538, 327700, 0, 65536, 327701, 0, 0, 327702, 0, 65536, 327703, 0, 0, 327704, 0, 65536, 327705, 0, 65536, 327706, 0, 65536, 327707, 0, 65536, 327708, 0, 65536, 327709, 0, 65536, 327710, 0, 65536, 327711, 0, 65536, 327712, 0, 65536, 327713, 0, 65536, 327714, 0, 65536, 327715, 0, 65536, 327716, 0, 65536, 327717, 0, 65536, 327718, 0, 65536, 327719, 0, 65536, 327720, 0, 65536, 327721, 0, 65536, 327722, 0, 65536, 327723, 0, 65536, 327724, 0, 65536, 327725, 0, 2, 327726, 0, 65536, 393216, 0, 65536, 393217, 0, 65536, 393218, 1, 0, 393219, 1, 65540, 393220, 1, 65537, 393221, 1, 65537, 393222, 1, 65537, 393223, 1, 65537, 393224, 1, 65537, 393225, 1, 65537, 393226, 1, 65537, 393227, 1, 65537, 393228, 1, 65537, 393229, 1, 65537, 393230, 1, 65537, 393231, 1, 65537, 393232, 1, 65537, 393233, 1, 65537, 393234, 1, 65537, 393235, 1, 65538, 393236, 0, 65536, 393237, 0, 65536, 393238, 0, 65536, 393239, 0, 65536, 393240, 0, 65536, 393241, 0, 65536, 393242, 0, 65536, 393243, 0, 65536, 393244, 0, 65536, 393245, 0, 65536, 393246, 0, 65536, 393247, 0, 65536, 393248, 0, 0, 393249, 0, 65536, 393250, 0, 65536, 393251, 0, 65536, 393252, 0, 65536, 393253, 0, 2, 393254, 0, 65536, 393255, 0, 65536, 393256, 0, 65536, 393257, 0, 65536, 393258, 0, 65536, 393259, 0, 65536, 393260, 0, 65536, 393261, 0, 65536, 393262, 0, 65536, 458752, 0, 65536, 458753, 0, 65536, 458754, 1, 65536, 458755, 1, 65537, 458756, 1, 65537, 458757, 1, 65537, 458758, 1, 65537, 458759, 1, 65537, 458760, 1, 65537, 458761, 1, 65537, 458762, 1, 65537, 458763, 1, 65537, 458764, 1, 65537, 458765, 1, 65537, 458766, 1, 65537, 458767, 1, 65537, 458768, 1, 65537, 458769, 1, 65537, 458770, 1, 65537, 458771, 1, 65538, 458772, 0, 65536, 458773, 0, 65536, 458774, 0, 65536, 458775, 0, 65536, 458776, 0, 65536, 458777, 0, 65536, 458778, 0, 65536, 458779, 0, 65536, 458780, 0, 65536, 458781, 0, 65536, 458782, 0, 65536, 458783, 0, 65536, 458784, 0, 65536, 458785, 0, 65536, 458786, 0, 65536, 458787, 0, 65536, 458788, 0, 65536, 458789, 0, 65536, 458790, 0, 65536, 458791, 0, 65536, 458792, 0, 65536, 458793, 0, 65536, 458794, 0, 65536, 458795, 0, 65536, 458796, 0, 65536, 458797, 0, 65536, 458798, 0, 65536, 524288, 0, 65536, 524289, 1, 0, 524290, 1, 65540, 524291, 1, 65537, 524292, 1, 65537, 524293, 1, 65537, 524294, 1, 65537, 524295, 1, 65537, 524296, 1, 65537, 524297, 1, 65537, 524298, 1, 65537, 524299, 1, 65537, 524300, 1, 65537, 524301, 1, 65537, 524302, 1, 65537, 524303, 1, 65537, 524304, 1, 65537, 524305, 1, 65537, 524306, 1, 65537, 524307, 1, 65539, 524308, 1, 1, 524309, 1, 1, 524310, 1, 2, 524311, 0, 65536, 524312, 0, 65536, 524313, 0, 65536, 524314, 0, 2, 524315, 0, 65536, 524316, 0, 65536, 524317, 0, 65536, 524318, 0, 65536, 524319, 0, 65536, 524320, 0, 1, 524321, 0, 65536, 524322, 0, 65536, 524323, 0, 65536, 524324, 0, 65536, 524325, 0, 65536, 524326, 0, 65536, 524327, 0, 65536, 524328, 0, 65536, 524329, 0, 65536, 524330, 0, 65536, 524331, 0, 65536, 524332, 0, 65536, 524333, 0, 65536, 524334, 0, 65536, 589824, 0, 65536, 589825, 1, 65536, 589826, 1, 65537, 589827, 1, 65537, 589828, 1, 65537, 589829, 1, 65537, 589830, 1, 65537, 589831, 1, 65537, 589832, 1, 65537, 589833, 1, 65537, 589834, 1, 65537, 589835, 1, 65537, 589836, 1, 65537, 589837, 1, 65537, 589838, 1, 65537, 589839, 1, 196609, 589840, 1, 65537, 589841, 1, 65537, 589842, 1, 65537, 589843, 1, 65537, 589844, 1, 65537, 589845, 1, 65537, 589846, 1, 65538, 589847, 0, 65536, 589848, 0, 65536, 589849, 0, 65536, 589850, 0, 65536, 589851, 0, 65536, 589852, 0, 65536, 589853, 0, 65536, 589854, 0, 65536, 589855, 0, 65536, 589856, 0, 65536, 589857, 0, 65536, 589858, 5, 0, 589859, 5, 1, 589860, 5, 1, 589861, 5, 1, 589862, 5, 1, 589863, 5, 2, 589864, 0, 65536, 589865, 0, 65536, 589866, 0, 0, 589867, 0, 65536, 589868, 0, 65536, 589869, 0, 65536, 589870, 0, 65536, 655360, 0, 65536, 655361, 1, 65536, 655362, 1, 65537, 655363, 1, 196610, 655364, 1, 65537, 655365, 1, 65537, 655366, 1, 65537, 655367, 1, 65537, 655368, 1, 65537, 655369, 1, 65537, 655370, 1, 65537, 655371, 1, 65537, 655372, 1, 65537, 655373, 1, 65537, 655374, 1, 65537, 655375, 1, 65537, 655376, 1, 65537, 655377, 1, 3, 655378, 1, 131073, 655379, 1, 131073, 655380, 1, 131073, 655381, 1, 131073, 655382, 1, 131074, 655383, 0, 65536, 655384, 0, 0, 655385, 0, 65536, 655386, 0, 65536, 655387, 0, 65536, 655388, 0, 65536, 655389, 0, 65536, 655390, 0, 65536, 655391, 0, 65536, 655392, 0, 65536, 655393, 0, 65536, 655394, 5, 131072, 655395, 5, 4, 655396, 5, 65537, 655397, 5, 65537, 655398, 5, 65537, 655399, 5, 65538, 655400, 0, 65536, 655401, 0, 65536, 655402, 0, 65536, 655403, 0, 65536, 655404, 0, 65536, 655405, 0, 65536, 655406, 0, 65536, 720896, 0, 65536, 720897, 1, 65536, 720898, 1, 65537, 720899, 1, 65537, 720900, 1, 65537, 720901, 1, 65537, 720902, 1, 65537, 720903, 1, 65537, 720904, 1, 65537, 720905, 1, 65537, 720906, 1, 196608, 720907, 1, 65537, 720908, 1, 65537, 720909, 1, 65537, 720910, 1, 65537, 720911, 1, 65537, 720912, 1, 65537, 720913, 1, 65538, 720914, 0, 65536, 720915, 0, 65536, 720916, 0, 65536, 720917, 0, 65536, 720918, 0, 65536, 720919, 0, 65536, 720920, 0, 65536, 720921, 0, 65536, 720922, 0, 65536, 720923, 0, 65536, 720924, 0, 65536, 720925, 0, 65536, 720926, 0, 65536, 720927, 0, 65536, 720928, 0, 65536, 720929, 0, 65536, 720930, 0, 65536, 720931, 5, 65536, 720932, 5, 65537, 720933, 5, 65537, 720934, 5, 65537, 720935, 5, 65539, 720936, 5, 1, 720937, 5, 2, 720938, 0, 65536, 720939, 0, 65536, 720940, 0, 65536, 720941, 0, 2, 720942, 0, 65536, 786432, 0, 65536, 786433, 1, 65536, 786434, 1, 65537, 786435, 1, 65537, 786436, 1, 65537, 786437, 1, 65537, 786438, 1, 196609, 786439, 1, 65537, 786440, 1, 65537, 786441, 1, 65537, 786442, 1, 65537, 786443, 1, 3, 786444, 1, 131073, 786445, 1, 131073, 786446, 1, 131073, 786447, 1, 4, 786448, 1, 65537, 786449, 1, 65538, 786450, 0, 65536, 786451, 0, 65536, 786452, 0, 65536, 786453, 0, 65536, 786454, 0, 65536, 786455, 0, 65536, 786456, 0, 65536, 786457, 0, 65536, 786458, 0, 65536, 786459, 0, 65536, 786460, 0, 65536, 786461, 0, 65536, 786462, 0, 65536, 786463, 0, 65536, 786464, 0, 65536, 786465, 0, 65536, 786466, 0, 65536, 786467, 5, 131072, 786468, 5, 131073, 786469, 5, 131073, 786470, 5, 4, 786471, 5, 65537, 786472, 5, 65537, 786473, 5, 65538, 786474, 0, 65536, 786475, 0, 65536, 786476, 0, 65536, 786477, 0, 65536, 786478, 0, 65536, 851968, 0, 65536, 851969, 1, 65536, 851970, 1, 65537, 851971, 1, 65537, 851972, 1, 65537, 851973, 1, 65537, 851974, 1, 65537, 851975, 1, 65537, 851976, 1, 65537, 851977, 1, 65537, 851978, 1, 65537, 851979, 1, 65538, 851980, 0, 65536, 851981, 0, 65536, 851982, 0, 65536, 851983, 1, 65536, 851984, 1, 65537, 851985, 1, 65538, 851986, 0, 65536, 851987, 0, 65536, 851988, 0, 65536, 851989, 0, 65536, 851990, 0, 65536, 851991, 0, 65536, 851992, 0, 65536, 851993, 0, 65536, 851994, 0, 65536, 851995, 0, 65536, 851996, 0, 65536, 851997, 0, 65536, 851998, 0, 0, 851999, 0, 65536, 852000, 0, 65536, 852001, 0, 65536, 852002, 0, 65536, 852003, 0, 65536, 852004, 0, 65536, 852005, 0, 65536, 852006, 5, 131072, 852007, 5, 131073, 852008, 5, 131073, 852009, 5, 131074, 852010, 0, 65536, 852011, 0, 65536, 852012, 0, 65536, 852013, 0, 65536, 852014, 0, 65536, 917504, 0, 65536, 917505, 1, 131072, 917506, 1, 131073, 917507, 1, 131073, 917508, 1, 131073, 917509, 1, 131073, 917510, 1, 131073, 917511, 1, 131073, 917512, 1, 131073, 917513, 1, 131073, 917514, 1, 131073, 917515, 1, 131074, 917516, 0, 65536, 917517, 0, 65536, 917518, 0, 65536, 917519, 1, 131072, 917520, 1, 131073, 917521, 1, 131074, 917522, 0, 65536, 917523, 0, 65536, 917524, 0, 65536, 917525, 0, 65536, 917526, 0, 65536, 917527, 0, 65536, 917528, 0, 65536, 917529, 0, 65536, 917530, 0, 65536, 917531, 0, 65536, 917532, 0, 0, 917533, 0, 2, 917534, 0, 65536, 917535, 0, 0, 917536, 0, 65536, 917537, 0, 65536, 917538, 0, 65536, 917539, 0, 65536, 917540, 0, 65536, 917541, 0, 65536, 917542, 0, 65536, 917543, 0, 65536, 917544, 0, 65536, 917545, 0, 65536, 917546, 0, 65536, 917547, 0, 65536, 917548, 0, 65536, 917549, 0, 65536, 917550, 0, 65536, 983040, 0, 65536, 983041, 0, 65536, 983042, 0, 65536, 983043, 0, 65536, 983044, 0, 65536, 983045, 0, 65536, 983046, 0, 65536, 983047, 0, 65536, 983048, 0, 65536, 983049, 0, 65536, 983050, 0, 65536, 983051, 0, 65536, 983052, 0, 65536, 983053, 0, 65536, 983054, 0, 65536, 983055, 0, 65536, 983056, 0, 65536, 983057, 0, 65536, 983058, 0, 65536, 983059, 0, 65536, 983060, 0, 65536, 983061, 0, 65536, 983062, 0, 65536, 983063, 0, 65536, 983064, 0, 65536, 983065, 0, 65536, 983066, 0, 65536, 983067, 0, 65536, 983068, 0, 65536, 983069, 0, 65536, 983070, 0, 65536, 983071, 0, 65536, 983072, 0, 65536, 983073, 0, 65536, 983074, 0, 65536, 983075, 0, 65536, 983076, 0, 0, 983077, 0, 65536, 983078, 0, 65536, 983079, 0, 65536, 983080, 0, 65536, 983081, 0, 65536, 983082, 0, 65536, 983083, 0, 65536, 983084, 0, 65536, 983085, 0, 65536, 983086, 0, 65536, 1048576, 0, 65536, 1048577, 0, 65536, 1048578, 0, 2, 1048579, 0, 65536, 1048580, 0, 65536, 1048581, 0, 1, 1048582, 0, 65536, 1048583, 0, 65536, 1048584, 0, 65536, 1048585, 0, 65536, 1048586, 0, 65536, 1048587, 0, 65536, 1048588, 0, 65536, 1048589, 0, 65536, 1048590, 0, 65536, 1048591, 0, 65536, 1048592, 0, 65536, 1048593, 0, 65536, 1048594, 0, 65536, 1048595, 0, 1, 1048596, 0, 1, 1048597, 0, 65536, 1048598, 0, 65536, 1048599, 0, 65536, 1048600, 0, 65536, 1048601, 0, 0, 1048602, 0, 65536, 1048603, 0, 65536, 1048604, 0, 65536, 1048605, 0, 65536, 1048606, 0, 65536, 1048607, 0, 2, 1048608, 0, 65536, 1048609, 0, 65536, 1048610, 0, 65536, 1048611, 0, 65536, 1048612, 0, 65536, 1048613, 0, 65536, 1048614, 0, 65536, 1048615, 0, 65536, 1048616, 0, 65536, 1048617, 0, 65536, 1048618, 0, 65536, 1048619, 0, 65536, 1048620, 0, 65536, 1048621, 0, 65536, 1048622, 0, 65536, 1114112, 0, 65536, 1114113, 0, 65536, 1114114, 0, 65536, 1114115, 0, 65536, 1114116, 0, 65536, 1114117, 0, 65536, 1114118, 0, 65536, 1114119, 0, 65536, 1114120, 0, 65536, 1114121, 0, 65536, 1114122, 0, 65536, 1114123, 0, 65536, 1114124, 0, 65536, 1114125, 0, 65536, 1114126, 0, 65536, 1114127, 0, 65536, 1114128, 0, 0, 1114129, 0, 65536, 1114130, 0, 0, 1114131, 0, 65536, 1114132, 0, 65536, 1114133, 0, 65536, 1114134, 0, 0, 1114135, 0, 65536, 1114136, 0, 0, 1114137, 0, 65536, 1114138, 0, 1, 1114139, 0, 65536, 1114140, 0, 65536, 1114141, 0, 65536, 1114142, 0, 0, 1114143, 0, 65536, 1114144, 0, 65536, 1114145, 0, 65536, 1114146, 0, 65536, 1114147, 0, 65536, 1114148, 0, 65536, 1114149, 0, 65536, 1114150, 0, 65536, 1114151, 0, 65536, 1114152, 0, 65536, 1114153, 0, 65536, 1114154, 0, 65536, 1114155, 0, 65536, 1114156, 0, 65536, 1114157, 0, 65536, 1114158, 0, 65536, 1179648, 0, 65536, 1179649, 0, 65536, 1179650, 0, 65536, 1179651, 0, 65536, 1179652, 0, 65536, 1179653, 0, 65536, 1179654, 0, 65536, 1179655, 0, 65536, 1179656, 0, 65536, 1179657, 0, 65536, 1179658, 0, 65536, 1179659, 0, 65536, 1179660, 0, 65536, 1179661, 0, 65536, 1179662, 0, 65536, 1179663, 0, 65536, 1179664, 0, 65536, 1179665, 0, 65536, 1179666, 0, 65536, 1179667, 0, 65536, 1179668, 0, 65536, 1179669, 0, 65536, 1179670, 0, 65536, 1179671, 0, 65536, 1179672, 0, 65536, 1179673, 0, 65536, 1179674, 0, 65536, 1179675, 0, 65536, 1179676, 0, 65536, 1179677, 0, 65536, 1179678, 0, 65536, 1179679, 0, 65536, 1179680, 0, 65536, 1179681, 0, 65536, 1179682, 0, 65536, 1179683, 0, 65536, 1179684, 0, 65536, 1179685, 0, 65536, 1179686, 0, 65536, 1179687, 0, 65536, 1179688, 0, 65536, 1179689, 0, 0, 1179690, 0, 2, 1179691, 0, 65536, 1179692, 0, 65536, 1179693, 0, 65536, 1179694, 0, 65536, 1245184, 0, 65536, 1245185, 0, 65536, 1245186, 0, 65536, 1245187, 0, 65536, 1245188, 0, 65536, 1245189, 0, 65536, 1245190, 0, 65536, 1245191, 0, 65536, 1245192, 0, 65536, 1245193, 0, 65536, 1245194, 0, 65536, 1245195, 0, 65536, 1245196, 0, 65536, 1245197, 0, 65536, 1245198, 0, 65536, 1245199, 0, 65536, 1245200, 0, 65536, 1245201, 0, 65536, 1245202, 0, 65536, 1245203, 0, 0, 1245204, 0, 65536, 1245205, 0, 65536, 1245206, 0, 65536, 1245207, 0, 65536, 1245208, 0, 65536, 1245209, 0, 65536, 1245210, 0, 65536, 1245211, 0, 65536, 1245212, 0, 65536, 1245213, 0, 65536, 1245214, 0, 65536, 1245215, 0, 1, 1245216, 0, 65536, 1245217, 0, 65536, 1245218, 0, 65536, 1245219, 0, 65536, 1245220, 0, 65536, 1245221, 0, 65536, 1245222, 0, 65536, 1245223, 0, 65536, 1245224, 0, 65536, 1245225, 0, 65536, 1245226, 0, 65536, 1245227, 0, 65536, 1245228, 0, 65536, 1245229, 0, 65536, 1245230, 0, 65536, 1310720, 0, 65536, 1310721, 0, 65536, 1310722, 0, 65536, 1310723, 0, 65536, 1310724, 0, 65536, 1310725, 0, 0, 1310726, 0, 65536, 1310727, 0, 65536, 1310728, 0, 65536, 1310729, 0, 1, 1310730, 0, 65536, 1310731, 0, 65536, 1310732, 0, 65536, 1310733, 0, 65536, 1310734, 0, 2, 1310735, 0, 65536, 1310736, 0, 65536, 1310737, 0, 65536, 1310738, 0, 65536, 1310739, 0, 65536, 1310740, 0, 65536, 1310741, 0, 65536, 1310742, 0, 65536, 1310743, 0, 65536, 1310744, 0, 65536, 1310745, 0, 65536, 1310746, 0, 65536, 1310747, 0, 65536, 1310748, 0, 65536, 1310749, 0, 65536, 1310750, 0, 0, 1310751, 0, 65536, 1310752, 0, 65536, 1310753, 0, 65536, 1310754, 0, 65536, 1310755, 0, 1, 1310756, 0, 65536, 1310757, 0, 65536, 1310758, 0, 0, 1310759, 0, 65536, 1310760, 0, 65536, 1310761, 0, 65536, 1310762, 0, 65536, 1310763, 0, 65536, 1310764, 0, 65536, 1310765, 0, 65536, 1310766, 0, 65536, 1376256, 0, 65536, 1376257, 0, 65536, 1376258, 0, 65536, 1376259, 0, 65536, 1376260, 0, 1, 1376261, 0, 65536, 1376262, 0, 65536, 1376263, 0, 65536, 1376264, 0, 65536, 1376265, 0, 65536, 1376266, 0, 65536, 1376267, 0, 65536, 1376268, 0, 65536, 1376269, 0, 65536, 1376270, 0, 65536, 1376271, 0, 65536, 1376272, 0, 65536, 1376273, 0, 65536, 1376274, 0, 65536, 1376275, 0, 65536, 1376276, 0, 65536, 1376277, 0, 65536, 1376278, 0, 65536, 1376279, 0, 2, 1376280, 0, 65536, 1376281, 0, 65536, 1376282, 0, 65536, 1376283, 0, 65536, 1376284, 0, 65536, 1376285, 0, 65536, 1376286, 0, 65536, 1376287, 0, 65536, 1376288, 0, 65536, 1376289, 0, 65536, 1376290, 0, 65536, 1376291, 0, 0, 1376292, 0, 2, 1376293, 0, 65536, 1376294, 0, 65536, 1376295, 0, 65536, 1376296, 0, 65536, 1376297, 0, 65536, 1376298, 0, 65536, 1376299, 0, 65536, 1376300, 0, 65536, 1376301, 0, 65536, 1376302, 0, 65536, 1441792, 0, 65536, 1441793, 0, 2, 1441794, 0, 65536, 1441795, 0, 65536, 1441796, 0, 65536, 1441797, 0, 65536, 1441798, 0, 65536, 1441799, 0, 65536, 1441800, 0, 65536, 1441801, 0, 65536, 1441802, 0, 65536, 1441803, 0, 0, 1441804, 0, 65536, 1441805, 0, 65536, 1441806, 0, 65536, 1441807, 0, 65536, 1441808, 0, 65536, 1441809, 0, 65536, 1441810, 0, 65536, 1441811, 0, 65536, 1441812, 0, 65536, 1441813, 0, 65536, 1441814, 0, 65536, 1441815, 0, 1, 1441816, 0, 65536, 1441817, 0, 65536, 1441818, 0, 65536, 1441819, 0, 65536, 1441820, 0, 65536, 1441821, 0, 65536, 1441822, 0, 65536, 1441823, 0, 65536, 1441824, 0, 65536, 1441825, 0, 65536, 1441826, 0, 65536, 1441827, 0, 65536, 1441828, 0, 65536, 1441829, 0, 65536, 1441830, 0, 65536, 1441831, 0, 65536, 1441832, 0, 65536, 1441833, 0, 65536, 1441834, 0, 65536, 1441835, 0, 65536, 1441836, 0, 65536, 1441837, 0, 65536, 1441838, 0, 65536, 1507328, 0, 65536, 1507329, 0, 65536, 1507330, 0, 65536, 1507331, 0, 65536, 1507332, 0, 65536, 1507333, 0, 65536, 1507334, 0, 65536, 1507335, 0, 65536, 1507336, 0, 65536, 1507337, 0, 65536, 1507338, 0, 65536, 1507339, 0, 1, 1507340, 0, 65536, 1507341, 0, 65536, 1507342, 0, 65536, 1507343, 0, 65536, 1507344, 0, 65536, 1507345, 0, 65536, 1507346, 0, 65536, 1507347, 0, 65536, 1507348, 0, 65536, 1507349, 0, 65536, 1507350, 0, 65536, 1507351, 0, 65536, 1507352, 0, 65536, 1507353, 0, 65536, 1507354, 0, 65536, 1507355, 0, 65536, 1507356, 0, 65536, 1507357, 0, 65536, 1507358, 0, 1, 1507359, 0, 65536, 1507360, 0, 65536, 1507361, 0, 65536, 1507362, 0, 65536, 1507363, 0, 65536, 1507364, 0, 65536, 1507365, 0, 65536, 1507366, 0, 65536, 1507367, 0, 65536, 1507368, 0, 65536, 1507369, 0, 65536, 1507370, 0, 65536, 1507371, 0, 65536, 1507372, 0, 65536, 1507373, 0, 0, 1507374, 0, 65536, 1572864, 0, 65536, 1572865, 0, 65536, 1572866, 0, 65536, 1572867, 0, 65536, 1572868, 0, 65536, 1572869, 0, 65536, 1572870, 0, 65536, 1572871, 0, 65536, 1572872, 0, 65536, 1572873, 0, 65536, 1572874, 0, 65536, 1572875, 0, 65536, 1572876, 0, 65536, 1572877, 0, 65536, 1572878, 0, 0, 1572879, 0, 65536, 1572880, 0, 65536, 1572881, 0, 65536, 1572882, 0, 65536, 1572883, 0, 65536, 1572884, 0, 65536, 1572885, 0, 65536, 1572886, 0, 0, 1572887, 0, 65536, 1572888, 0, 65536, 1572889, 0, 65536, 1572890, 0, 65536, 1572891, 0, 65536, 1572892, 0, 65536, 1572893, 0, 65536, 1572894, 0, 65536, 1572895, 0, 65536, 1572896, 0, 65536, 1572897, 0, 65536, 1572898, 0, 2, 1572899, 0, 65536, 1572900, 0, 65536, 1572901, 0, 65536, 1572902, 0, 65536, 1572903, 0, 65536, 1572904, 0, 65536, 1572905, 0, 65536, 1572906, 0, 65536, 1572907, 0, 0, 1572908, 0, 65536, 1572909, 0, 65536, 1572910, 0, 65536, 1638400, 0, 65536, 1638401, 0, 65536, 1638402, 0, 65536, 1638403, 0, 65536, 1638404, 0, 65536, 1638405, 0, 65536, 1638406, 0, 65536, 1638407, 0, 65536, 1638408, 0, 65536, 1638409, 0, 65536, 1638410, 0, 65536, 1638411, 0, 65536, 1638412, 0, 65536, 1638413, 0, 65536, 1638414, 0, 65536, 1638415, 0, 65536, 1638416, 0, 65536, 1638417, 0, 65536, 1638418, 0, 65536, 1638419, 0, 65536, 1638420, 0, 65536, 1638421, 0, 65536, 1638422, 0, 65536, 1638423, 0, 65536, 1638424, 0, 65536, 1638425, 0, 65536, 1638426, 0, 65536, 1638427, 0, 65536, 1638428, 0, 65536, 1638429, 0, 65536, 1638430, 0, 65536, 1638431, 0, 65536, 1638432, 0, 65536, 1638433, 0, 65536, 1638434, 0, 65536, 1638435, 0, 65536, 1638436, 0, 65536, 1638437, 0, 65536, 1638438, 0, 65536, 1638439, 0, 65536, 1638440, 0, 65536, 1638441, 0, 65536, 1638442, 0, 65536, 1638443, 0, 65536, 1638444, 0, 65536, 1638445, 0, 65536, 1638446, 0, 65536 ) _sections_unfolded = [ "Cell" ] [node name="Props" type="TileMap" parent="." index="1"] mode = 0 tile_set = ExtResource( 2 ) cell_size = Vector2( 128, 128 ) cell_quadrant_size = 16 cell_custom_transform = Transform2D( 1, 0, 0, 1, 0, 0 ) cell_half_offset = 2 cell_tile_origin = 0 cell_y_sort = false cell_clip_uv = false collision_use_kinematic = false collision_friction = 1.0 collision_bounce = 0.0 collision_layer = 1 collision_mask = 1 occluder_light_mask = 1 format = 1 tile_data = PoolIntArray( 0, 4, 6, 1, 4, 131073, 2, 4, 1, 3, 4, 1, 4, 4, 1, 5, 4, 1, 6, 4, 131073, 7, 4, 1, 8, 4, 1, 9, 4, 131073, 10, 4, 1, 11, 4, 131073, 12, 4, 1, 13, 4, 131073, 14, 4, 131073, 15, 4, 1, 16, 4, 1, 17, 4, 131073, 18, 4, 131073, 19, 4, 131073, 20, 4, 65540, 21, 4, 131073, 22, 4, 131073, 23, 4, 1, 24, 4, 131073, 25, 4, 131073, 26, 4, 1, 27, 4, 131073, 28, 4, 131073, 29, 4, 1, 30, 4, 1, 31, 4, 1, 32, 4, 1, 33, 4, 131073, 34, 4, 131073, 35, 4, 1, 36, 4, 131073, 37, 4, 131073, 38, 4, 1, 39, 4, 1, 40, 4, 131073, 41, 4, 131073, 42, 4, 131073, 43, 4, 1, 44, 4, 1, 45, 4, 131073, 46, 4, 2, 65536, 4, 65536, 65556, 4, 65536, 65582, 4, 65536, 131072, 4, 65538, 131092, 4, 65536, 131118, 4, 65538, 196608, 4, 65536, 196628, 4, 65538, 196654, 4, 65536, 262144, 4, 65536, 262164, 4, 65536, 262190, 4, 65538, 327680, 4, 65536, 327700, 4, 131072, 327701, 4, 1, 327702, 4, 7, 327726, 4, 65538, 393216, 4, 65536, 393223, 2, 0, 393238, 4, 65539, 393262, 4, 65536, 458752, 4, 65538, 458798, 4, 65536, 524288, 4, 65536, 524306, 2, 0, 524334, 4, 65536, 589824, 4, 65536, 589870, 4, 65536, 655360, 4, 65536, 655406, 4, 65538, 720896, 4, 65538, 720942, 4, 65536, 786432, 4, 65538, 786454, 4, 3, 786478, 4, 65538, 851968, 4, 65536, 851984, 2, 0, 851988, 4, 0, 851989, 4, 131073, 851990, 4, 131074, 852014, 4, 65538, 917504, 4, 65538, 917524, 4, 65538, 917550, 4, 65538, 983040, 4, 4, 983041, 4, 131073, 983042, 4, 1, 983043, 4, 1, 983044, 4, 131073, 983045, 4, 1, 983046, 4, 131073, 983047, 4, 131073, 983048, 4, 131073, 983049, 4, 131073, 983050, 4, 1, 983051, 4, 1, 983052, 4, 131073, 983053, 4, 131073, 983054, 4, 131073, 983055, 4, 1, 983056, 4, 131073, 983057, 4, 131073, 983058, 4, 1, 983059, 4, 1, 983060, 4, 65543, 983086, 4, 65536, 1048576, 4, 65538, 1048622, 4, 65536, 1114112, 4, 65536, 1114127, 5, 0, 1114128, 5, 1, 1114129, 5, 1, 1114130, 5, 2, 1114158, 4, 65536, 1179648, 4, 65536, 1179663, 5, 65536, 1179664, 5, 65537, 1179665, 5, 65537, 1179666, 5, 65539, 1179667, 5, 2, 1179694, 4, 65538, 1245184, 4, 65536, 1245198, 5, 0, 1245199, 5, 65540, 1245200, 5, 65537, 1245201, 5, 65537, 1245202, 5, 65537, 1245203, 5, 65538, 1245230, 4, 65536, 1310720, 4, 65536, 1310734, 5, 65536, 1310735, 5, 65537, 1310736, 5, 65537, 1310737, 5, 65537, 1310738, 5, 65537, 1310739, 5, 65539, 1310740, 5, 2, 1310766, 4, 65536, 1376256, 4, 65536, 1376270, 5, 65536, 1376271, 5, 65537, 1376272, 5, 65537, 1376273, 5, 65537, 1376274, 5, 65537, 1376275, 5, 3, 1376276, 5, 131074, 1376302, 4, 65536, 1441792, 4, 65536, 1441806, 5, 65536, 1441807, 5, 65537, 1441808, 5, 3, 1441809, 5, 131073, 1441810, 5, 131073, 1441811, 5, 131074, 1441838, 4, 65538, 1507328, 4, 65538, 1507342, 5, 65536, 1507343, 5, 65537, 1507344, 5, 65538, 1507374, 4, 65538, 1572864, 4, 65538, 1572878, 5, 131072, 1572879, 5, 131073, 1572880, 5, 131074, 1572910, 4, 65536, 1638400, 4, 131072, 1638401, 4, 1, 1638402, 4, 1, 1638403, 4, 1, 1638404, 4, 1, 1638405, 4, 1, 1638406, 4, 131073, 1638407, 4, 131073, 1638408, 4, 131073, 1638409, 4, 1, 1638410, 4, 131073, 1638411, 4, 1, 1638412, 4, 131073, 1638413, 4, 131073, 1638414, 4, 131073, 1638415, 4, 1, 1638416, 4, 131073, 1638417, 4, 131073, 1638418, 4, 131073, 1638419, 4, 1, 1638420, 4, 1, 1638421, 4, 131073, 1638422, 4, 131073, 1638423, 4, 131073, 1638424, 4, 131073, 1638425, 4, 131073, 1638426, 4, 131073, 1638427, 4, 131073, 1638428, 4, 1, 1638429, 4, 131073, 1638430, 4, 1, 1638431, 4, 1, 1638432, 4, 1, 1638433, 4, 1, 1638434, 4, 131073, 1638435, 4, 1, 1638436, 4, 131073, 1638437, 4, 131073, 1638438, 4, 1, 1638439, 4, 131073, 1638440, 4, 131073, 1638441, 4, 1, 1638442, 4, 1, 1638443, 4, 131073, 1638444, 4, 1, 1638445, 4, 131073, 1638446, 4, 131074 ) _sections_unfolded = [ "Cell" ] [node name="Gap" parent="." index="2" instance=ExtResource( 3 )] position = Vector2( 1744, 944 ) [node name="Gap2" parent="." index="3" instance=ExtResource( 3 )] position = Vector2( 432, 1440 ) [node name="Gap3" parent="." index="4" instance=ExtResource( 3 )] position = Vector2( 4624, 2272 ) [node name="Gap4" parent="." index="5" instance=ExtResource( 3 )] position = Vector2( 5664, 1424 ) [node name="Gap5" parent="." index="6" instance=ExtResource( 3 )] position = Vector2( 3152, 1696 ) [node name="YSort" type="YSort" parent="." index="7"] editor/display_folded = true sort_enabled = true [node name="Porcupine" parent="YSort" index="0" instance=ExtResource( 4 )] position = Vector2( 576, 768 ) ARRIVE_DISTANCE = 6.0 DEFAULT_SLOW_RADIUS = 200.0 DEFAULT_MAX_SPEED = 300.0 MASS = 8.0 MAX_ROAM_SPEED = 200.0 MAX_FOLLOW_SPEED = 400.0 MAX_CHARGE_SPEED = 900.0 SPOT_RANGE = 460.0 FOLLOW_RANGE = 700.0 BUMP_RANGE = 90.0 CHARGE_RANGE = 340.0 PREPARE_TO_CHARGE_WAIT_TIME = 0.9 ROAM_RADIUS = 140.0 BUMP_DISTANCE = 60.0 BUMP_DURATION = 0.2 MAX_BUMP_HEIGHT = 50.0 BUMP_COOLDOWN_DURATION = 0.6 [node name="Porcupine2" parent="YSort" index="1" instance=ExtResource( 4 )] position = Vector2( 2176, 656 ) ARRIVE_DISTANCE = 6.0 DEFAULT_SLOW_RADIUS = 200.0 DEFAULT_MAX_SPEED = 300.0 MASS = 8.0 MAX_ROAM_SPEED = 200.0 MAX_FOLLOW_SPEED = 400.0 MAX_CHARGE_SPEED = 900.0 SPOT_RANGE = 460.0 FOLLOW_RANGE = 700.0 BUMP_RANGE = 90.0 CHARGE_RANGE = 340.0 PREPARE_TO_CHARGE_WAIT_TIME = 0.9 ROAM_RADIUS = 140.0 BUMP_DISTANCE = 60.0 BUMP_DURATION = 0.2 MAX_BUMP_HEIGHT = 50.0 BUMP_COOLDOWN_DURATION = 0.6 [node name="Porcupine3" parent="YSort" index="2" instance=ExtResource( 4 )] position = Vector2( 816, 1728 ) ARRIVE_DISTANCE = 6.0 DEFAULT_SLOW_RADIUS = 200.0 DEFAULT_MAX_SPEED = 300.0 MASS = 8.0 MAX_ROAM_SPEED = 200.0 MAX_FOLLOW_SPEED = 400.0 MAX_CHARGE_SPEED = 900.0 SPOT_RANGE = 460.0 FOLLOW_RANGE = 700.0 BUMP_RANGE = 90.0 CHARGE_RANGE = 340.0 PREPARE_TO_CHARGE_WAIT_TIME = 0.9 ROAM_RADIUS = 140.0 BUMP_DISTANCE = 60.0 BUMP_DURATION = 0.2 MAX_BUMP_HEIGHT = 50.0 BUMP_COOLDOWN_DURATION = 0.6 [node name="Porcupine4" parent="YSort" index="3" instance=ExtResource( 4 )] position = Vector2( 464, 2976 ) ARRIVE_DISTANCE = 6.0 DEFAULT_SLOW_RADIUS = 200.0 DEFAULT_MAX_SPEED = 300.0 MASS = 8.0 MAX_ROAM_SPEED = 200.0 MAX_FOLLOW_SPEED = 400.0 MAX_CHARGE_SPEED = 900.0 SPOT_RANGE = 460.0 FOLLOW_RANGE = 700.0 BUMP_RANGE = 90.0 CHARGE_RANGE = 340.0 PREPARE_TO_CHARGE_WAIT_TIME = 0.9 ROAM_RADIUS = 140.0 BUMP_DISTANCE = 60.0 BUMP_DURATION = 0.2 MAX_BUMP_HEIGHT = 50.0 BUMP_COOLDOWN_DURATION = 0.6 [node name="Porcupine5" parent="YSort" index="4" instance=ExtResource( 4 )] position = Vector2( 4752, 640 ) ARRIVE_DISTANCE = 6.0 DEFAULT_SLOW_RADIUS = 200.0 DEFAULT_MAX_SPEED = 300.0 MASS = 8.0 MAX_ROAM_SPEED = 200.0 MAX_FOLLOW_SPEED = 400.0 MAX_CHARGE_SPEED = 900.0 SPOT_RANGE = 460.0 FOLLOW_RANGE = 700.0 BUMP_RANGE = 90.0 CHARGE_RANGE = 340.0 PREPARE_TO_CHARGE_WAIT_TIME = 0.9 ROAM_RADIUS = 140.0 BUMP_DISTANCE = 60.0 BUMP_DURATION = 0.2 MAX_BUMP_HEIGHT = 50.0 BUMP_COOLDOWN_DURATION = 0.6 [node name="Nest" parent="YSort" index="5" instance=ExtResource( 5 )] position = Vector2( 1936, 1520 ) [node name="Nest2" parent="YSort" index="6" instance=ExtResource( 5 )] position = Vector2( 384, 912 ) [node name="Nest3" parent="YSort" index="7" instance=ExtResource( 5 )] position = Vector2( 1088, 2576 ) [node name="Seller" parent="YSort" index="8" instance=ExtResource( 6 )] position = Vector2( 3056, 1232 ) [node name="PlayerSpawningPoint" parent="." index="8" instance=ExtResource( 7 )] position = Vector2( 5440, 2896 ) [node name="Door" parent="." index="9" instance=ExtResource( 8 )] position = Vector2( 304, 432 ) scale = Vector2( 0.8125, 0.8125 ) map_path = "res://levels/Cave.tscn" ACTIVE_AT_START = true [node name="SecretDrop" type="Node2D" parent="." index="10"] position = Vector2( 448, 2560 ) [node name="Walls" type="StaticBody2D" parent="." index="11"] input_pickable = false collision_layer = 1 collision_mask = 1 constant_linear_velocity = Vector2( 0, 0 ) constant_angular_velocity = 0.0 friction = 1.0 bounce = 0.0 [node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Walls" index="0"] build_mode = 1 polygon = PoolVector2Array( 96, 2048, 2592, 2048, 2656, 2048, 2656, 1936, 2656, 1792, 2848, 1792, 2912, 1792, 2912, 1680, 2912, 1552, 2848, 1552, 2848, 1680, 2655.43, 1680, 2592, 1680, 2592, 1792, 2592, 1936, 96, 1936 ) [node name="CollisionPolygon2D2" type="CollisionPolygon2D" parent="Walls" index="1"] build_mode = 1 polygon = PoolVector2Array( 2912, 896, 2848, 896, 2848, 768, 2656, 768, 2592, 768, 2592, 656, 2592, 128, 96, 128, 96, 16, 2591.58, 16, 2656, 16, 2656, 128, 2656, 656, 2848, 656, 2912, 656, 2912, 768 ) [node name="CollisionPolygon2D3" type="CollisionPolygon2D" parent="Walls" index="2"] build_mode = 1 polygon = PoolVector2Array( 32, 16, 96, 16, 96, 3216, 5920, 3216, 5920, 3328, 96, 3328, 32, 3328, 32, 3216 ) [node name="CollisionPolygon2D4" type="CollisionPolygon2D" parent="Walls" index="3"] build_mode = 1 polygon = PoolVector2Array( 5984, 3328, 5920, 3328, 5920, 128, 2656, 128, 2656, 16, 5984, 16 ) ================================================ FILE: levels/Level.gd ================================================ extends Node export(bool) var fog = false func get_ysort_node(): return $YSort func initialize(): return ================================================ FILE: levels/TestLevel.tscn ================================================ [gd_scene load_steps=11 format=2] [ext_resource path="res://core/world/tilesets/outdoor/outdoor.tres" type="TileSet" id=1] [ext_resource path="res://levels/Level.gd" type="Script" id=2] [ext_resource path="res://core/world/PlayerSpawningPoint.tscn" type="PackedScene" id=3] [ext_resource path="res://core/world/Gap.tscn" type="PackedScene" id=4] [ext_resource path="res://core/world/Door.tscn" type="PackedScene" id=5] [ext_resource path="res://actors/characters/seller/Seller.tscn" type="PackedScene" id=6] [ext_resource path="res://monsters/mosquito/Nest.tscn" type="PackedScene" id=7] [ext_resource path="res://monsters/porcupine/Porcupine.tscn" type="PackedScene" id=8] [ext_resource path="res://core/world/Rock.tscn" type="PackedScene" id=9] [ext_resource path="res://core/inventory/items/Coins.tscn" type="PackedScene" id=10] [node name="TestLevel" type="TileMap"] mode = 0 tile_set = ExtResource( 1 ) cell_size = Vector2( 128, 128 ) cell_quadrant_size = 16 cell_custom_transform = Transform2D( 1, 0, 0, 1, 0, 0 ) cell_half_offset = 2 cell_tile_origin = 0 cell_y_sort = false cell_clip_uv = false collision_use_kinematic = true collision_friction = 1.0 collision_bounce = 0.0 collision_layer = 1 collision_mask = 1 occluder_light_mask = 1 format = 1 tile_data = PoolIntArray( 0, 0, 65536, 1, 0, 65536, 2, 1, 0, 3, 1, 2, 4, 0, 65536, 5, 0, 65536, 6, 0, 65536, 7, 0, 65536, 8, 0, 65536, 9, 0, 65536, 10, 0, 65536, 11, 0, 65536, 12, 0, 65536, 13, 0, 65536, 14, 0, 65536, 15, 0, 65536, 16, 0, 65536, 17, 0, 65536, 18, 0, 65536, 19, 0, 65536, 20, 0, 65536, 65536, 0, 65536, 65537, 0, 65536, 65538, 1, 65536, 65539, 1, 65538, 65540, 5, 0, 65541, 5, 2, 65542, 0, 65536, 65543, 5, 0, 65544, 5, 1, 65545, 5, 2, 65546, 0, 65536, 65547, 0, 65536, 65548, 0, 65536, 65549, 0, 65536, 65550, 0, 65536, 65551, 0, 65536, 65552, 0, 65536, 65553, 0, 65536, 65554, 0, 65536, 65555, 0, 65536, 65556, 0, 65536, 131072, 0, 65536, 131073, 0, 65536, 131074, 1, 65536, 131075, 1, 65538, 131076, 5, 65536, 131077, 5, 65539, 131078, 5, 1, 131079, 5, 65540, 131080, 5, 3, 131081, 5, 131074, 131082, 0, 65536, 131083, 0, 65536, 131084, 1, 0, 131085, 1, 1, 131086, 1, 2, 131087, 0, 65536, 131088, 0, 65536, 131089, 0, 65536, 131090, 0, 65536, 131091, 0, 65536, 131092, 0, 65536, 196608, 0, 65536, 196609, 0, 65536, 196610, 1, 65536, 196611, 1, 65538, 196612, 5, 65536, 196613, 5, 65537, 196614, 5, 65537, 196615, 5, 65537, 196616, 5, 65538, 196617, 0, 65536, 196618, 1, 0, 196619, 1, 1, 196620, 1, 65540, 196621, 1, 65537, 196622, 1, 65539, 196623, 1, 1, 196624, 1, 1, 196625, 1, 1, 196626, 1, 2, 196627, 0, 65536, 196628, 0, 65536, 262144, 0, 65536, 262145, 0, 65536, 262146, 1, 65536, 262147, 1, 65538, 262148, 5, 131072, 262149, 5, 131073, 262150, 5, 4, 262151, 5, 65537, 262152, 5, 65539, 262153, 5, 2, 262154, 1, 65536, 262155, 1, 65537, 262156, 1, 65537, 262157, 1, 65537, 262158, 1, 65537, 262159, 1, 65537, 262160, 1, 65537, 262161, 1, 65537, 262162, 1, 65538, 262163, 0, 65536, 262164, 0, 65536, 327680, 0, 65536, 327681, 0, 65536, 327682, 1, 65536, 327683, 1, 65539, 327684, 1, 2, 327685, 0, 65536, 327686, 5, 131072, 327687, 5, 131073, 327688, 5, 131073, 327689, 5, 131074, 327690, 1, 65536, 327691, 1, 65537, 327692, 1, 65537, 327693, 1, 65537, 327694, 1, 65537, 327695, 1, 65537, 327696, 1, 65537, 327697, 1, 65537, 327698, 1, 65538, 327699, 0, 65536, 327700, 0, 65536, 393216, 0, 65536, 393217, 0, 65536, 393218, 1, 131072, 393219, 1, 4, 393220, 1, 65539, 393221, 1, 2, 393222, 0, 65536, 393223, 0, 65536, 393224, 0, 65536, 393225, 0, 65536, 393226, 1, 65536, 393227, 1, 65537, 393228, 1, 65537, 393229, 1, 65537, 393230, 1, 65537, 393231, 1, 65537, 393232, 1, 65537, 393233, 1, 65537, 393234, 1, 65538, 393235, 0, 65536, 393236, 0, 65536, 458752, 0, 65536, 458753, 0, 65536, 458754, 0, 65536, 458755, 1, 131072, 458756, 1, 4, 458757, 1, 65539, 458758, 1, 1, 458759, 1, 1, 458760, 1, 1, 458761, 1, 1, 458762, 1, 65540, 458763, 1, 65537, 458764, 1, 65537, 458765, 1, 65537, 458766, 1, 3, 458767, 1, 131073, 458768, 1, 131073, 458769, 1, 4, 458770, 1, 65538, 458771, 0, 65536, 458772, 0, 65536, 524288, 0, 65536, 524289, 0, 65536, 524290, 0, 65536, 524291, 0, 65536, 524292, 1, 131072, 524293, 1, 131073, 524294, 1, 131073, 524295, 1, 131073, 524296, 1, 131073, 524297, 1, 4, 524298, 1, 3, 524299, 1, 131073, 524300, 1, 131073, 524301, 1, 131073, 524302, 1, 131074, 524303, 0, 65536, 524304, 0, 65536, 524305, 1, 131072, 524306, 1, 131074, 524307, 0, 65536, 524308, 0, 65536, 589824, 0, 65536, 589825, 0, 65536, 589826, 0, 65536, 589827, 0, 65536, 589828, 0, 65536, 589829, 0, 65536, 589830, 0, 65536, 589831, 0, 65536, 589832, 0, 65536, 589833, 1, 65536, 589834, 1, 65538, 589835, 0, 65536, 589836, 0, 65536, 589837, 0, 65536, 589838, 0, 65536, 589839, 0, 65536, 589840, 0, 65536, 589841, 0, 65536, 589842, 0, 65536, 589843, 0, 65536, 589844, 0, 65536, 655360, 0, 65536, 655361, 0, 65536, 655362, 0, 65536, 655363, 0, 65536, 655364, 0, 2, 655365, 0, 65536, 655366, 0, 65536, 655367, 0, 65536, 655368, 0, 65536, 655369, 1, 65536, 655370, 1, 65538, 655371, 0, 65536, 655372, 0, 65536, 655373, 0, 65536, 655374, 0, 65536, 655375, 0, 65536, 655376, 0, 1, 655377, 0, 65536, 655378, 0, 65536, 655379, 0, 65536, 655380, 0, 65536, 720896, 0, 65536, 720897, 0, 65536, 720898, 0, 65536, 720899, 0, 65536, 720900, 0, 65536, 720901, 0, 65536, 720902, 0, 65536, 720903, 0, 65536, 720904, 0, 65536, 720905, 1, 131072, 720906, 1, 131074, 720907, 0, 65536, 720908, 0, 65536, 720909, 0, 65536, 720910, 0, 65536, 720911, 0, 65536, 720912, 0, 65536, 720913, 0, 65536, 720914, 0, 65536, 720915, 0, 65536, 720916, 0, 65536 ) script = ExtResource( 2 ) _sections_unfolded = [ "Cell", "Collision" ] fog = false [node name="PlayerSpawningPoint" parent="." index="0" instance=ExtResource( 3 )] position = Vector2( 603.07, 1200 ) [node name="Gap" parent="." index="1" instance=ExtResource( 4 )] position = Vector2( 1658, 902 ) [node name="Door" parent="." index="2" instance=ExtResource( 5 )] position = Vector2( 2006, 722 ) scale = Vector2( 0.8125, 0.8125 ) map_path = "res://levels/Cave.tscn" ACTIVE_AT_START = true [node name="YSort" type="YSort" parent="." index="3"] sort_enabled = true [node name="Seller" parent="YSort" index="0" instance=ExtResource( 6 )] position = Vector2( 466, 1213 ) [node name="Nest" parent="YSort" index="1" instance=ExtResource( 7 )] position = Vector2( 1635, 455 ) [node name="Porcupine" parent="YSort" index="2" instance=ExtResource( 8 )] position = Vector2( 2086.01, 1288.82 ) ARRIVE_DISTANCE = 6.0 DEFAULT_SLOW_RADIUS = 200.0 DEFAULT_MAX_SPEED = 300.0 MASS = 8.0 MAX_ROAM_SPEED = 200.0 MAX_FOLLOW_SPEED = 400.0 MAX_CHARGE_SPEED = 900.0 SPOT_RANGE = 460.0 FOLLOW_RANGE = 700.0 BUMP_RANGE = 90.0 CHARGE_RANGE = 340.0 PREPARE_TO_CHARGE_WAIT_TIME = 0.9 ROAM_RADIUS = 140.0 BUMP_DISTANCE = 60.0 BUMP_DURATION = 0.2 MAX_BUMP_HEIGHT = 50.0 BUMP_COOLDOWN_DURATION = 0.6 [node name="Porcupine2" parent="YSort" index="3" instance=ExtResource( 8 )] position = Vector2( 2546.01, 728.82 ) ARRIVE_DISTANCE = 6.0 DEFAULT_SLOW_RADIUS = 200.0 DEFAULT_MAX_SPEED = 300.0 MASS = 8.0 MAX_ROAM_SPEED = 200.0 MAX_FOLLOW_SPEED = 400.0 MAX_CHARGE_SPEED = 900.0 SPOT_RANGE = 460.0 FOLLOW_RANGE = 700.0 BUMP_RANGE = 90.0 CHARGE_RANGE = 340.0 PREPARE_TO_CHARGE_WAIT_TIME = 0.9 ROAM_RADIUS = 140.0 BUMP_DISTANCE = 60.0 BUMP_DURATION = 0.2 MAX_BUMP_HEIGHT = 50.0 BUMP_COOLDOWN_DURATION = 0.6 [node name="Rock" parent="YSort" index="4" instance=ExtResource( 9 )] position = Vector2( 1162, 801 ) [node name="Coins" parent="YSort" index="5" instance=ExtResource( 10 )] position = Vector2( 472.412, 993.695 ) [node name="Coins2" parent="YSort" index="6" instance=ExtResource( 10 )] position = Vector2( 781.924, 811.246 ) [node name="Coins3" parent="YSort" index="7" instance=ExtResource( 10 )] position = Vector2( 1153.34, 1179.4 ) [node name="Coins4" parent="YSort" index="8" instance=ExtResource( 10 )] position = Vector2( 1062.11, 1485.65 ) ================================================ FILE: monsters/BossShakingCamera.gd ================================================ tool extends "res://actors/camera/ShakingCamera.gd" onready var tween = $Tween export(float) var AMPLITUDE_HIT_WALL = 30.0 var start_global_position = Vector2() onready var _start_amplitude = amplitude func _ready(): start_global_position = global_position func initialize(player): global_position = player.camera.global_position player.get_health_node().connect('damage_taken', self, '_on_Player_damage_taken') current = true func move_to_room_center(): tween.interpolate_property(self, 'global_position', global_position, start_global_position, 1.0, Tween.TRANS_QUART, Tween.EASE_IN) tween.start() yield(tween, "tween_completed") func _on_WildBoar_hit_wall(): amplitude = AMPLITUDE_HIT_WALL self.shake = true func _on_Player_damage_taken(new_health): amplitude = _start_amplitude self.shake = true ================================================ FILE: monsters/BossShakingCamera.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://actors/camera/ShakingCamera.tscn" type="PackedScene" id=1] [ext_resource path="res://monsters/BossShakingCamera.gd" type="Script" id=2] [node name="BossShakingCamera" instance=ExtResource( 1 )] script = ExtResource( 2 ) amplitude = 10.0 AMPLITUDE_HIT_WALL = 30.0 [node name="Tween" type="Tween" parent="." index="1"] repeat = false playback_process_mode = 1 playback_speed = 1.0 playback/active = false playback/repeat = false playback/speed = 1.0 ================================================ FILE: monsters/Monster.gd ================================================ extends KinematicBody2D signal died var state var active export(float) var ARRIVE_DISTANCE = 6.0 export(float) var DEFAULT_SLOW_RADIUS = 200.0 export(float) var DEFAULT_MAX_SPEED = 300.0 export(float) var MASS = 8.0 onready var stats = $Stats const Actor = preload("res://actors/Actor.gd") var target = null # Actor var start_position = Vector2() var velocity = Vector2() func _ready(): set_as_toplevel(true) start_position = global_position func initialize(target_actor): if not target_actor is Actor: return target = target_actor target.connect('died', self, '_on_target_died') set_active(true) func _on_target_died(): target = null func take_damage_from(damage_source): stats.take_damage(damage_source.damage) func set_active(value): active = value set_physics_process(value) $HitBox.set_active(value) $DamageSource.set_active(value) ================================================ FILE: monsters/Monster.tscn ================================================ [gd_scene load_steps=8 format=2] [ext_resource path="res://monsters/Monster.gd" type="Script" id=1] [ext_resource path="res://actors/health/Stats.tscn" type="PackedScene" id=2] [ext_resource path="res://actors/hit_box/HitBox.tscn" type="PackedScene" id=3] [ext_resource path="res://interface/gui/lifebar/InterfaceAnchor.tscn" type="PackedScene" id=4] [sub_resource type="Animation" id=1] resource_name = "SETUP" length = 0.01 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath("Skin:position") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 0, 0 ) ] } tracks/1/type = "value" tracks/1/path = NodePath("Skin:rotation_degrees") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ 0.0 ] } tracks/2/type = "value" tracks/2/path = NodePath("Skin:scale") tracks/2/interp = 1 tracks/2/loop_wrap = true tracks/2/imported = false tracks/2/enabled = true tracks/2/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 1, 1 ) ] } tracks/3/type = "value" tracks/3/path = NodePath("Skin:modulate") tracks/3/interp = 1 tracks/3/loop_wrap = true tracks/3/imported = false tracks/3/enabled = true tracks/3/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ) ] } tracks/4/type = "value" tracks/4/path = NodePath("Skin:visible") tracks/4/interp = 1 tracks/4/loop_wrap = true tracks/4/imported = false tracks/4/enabled = true tracks/4/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 1, "values": [ true ] } tracks/5/type = "value" tracks/5/path = NodePath("Skin/BodyPivot:modulate") tracks/5/interp = 1 tracks/5/loop_wrap = true tracks/5/imported = false tracks/5/enabled = true tracks/5/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ) ] } tracks/6/type = "value" tracks/6/path = NodePath("Skin/BodyPivot:position") tracks/6/interp = 1 tracks/6/loop_wrap = true tracks/6/imported = false tracks/6/enabled = true tracks/6/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 0, 0 ) ] } tracks/7/type = "value" tracks/7/path = NodePath("Skin/BodyPivot:rotation_degrees") tracks/7/interp = 1 tracks/7/loop_wrap = true tracks/7/imported = false tracks/7/enabled = true tracks/7/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ 0.0 ] } tracks/8/type = "value" tracks/8/path = NodePath("Skin/BodyPivot:scale") tracks/8/interp = 1 tracks/8/loop_wrap = true tracks/8/imported = false tracks/8/enabled = true tracks/8/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 1, 1 ) ] } [sub_resource type="Animation" id=2] resource_name = "die" length = 0.4 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath("Skin/BodyPivot:scale") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.4 ), "transitions": PoolRealArray( 0.27058, 1 ), "update": 0, "values": [ Vector2( 1, 1 ), Vector2( 0.1, 0.1 ) ] } tracks/1/type = "value" tracks/1/path = NodePath("Skin/BodyPivot:modulate") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0, 0.4 ), "transitions": PoolRealArray( 1, 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ] } [sub_resource type="Animation" id=3] resource_name = "stagger" length = 0.6 loop = false step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath("Skin/BodyPivot:modulate") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.05, 0.1, 0.15, 0.2, 0.5 ), "transitions": PoolRealArray( 1, 1, 1, 1, 1, 1 ), "update": 0, "values": [ Color( 1, 0, 0, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 0, 0, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 0, 0, 1 ), Color( 1, 1, 1, 1 ) ] } tracks/1/type = "value" tracks/1/path = NodePath("Skin/BodyPivot:scale") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 1, "values": [ Vector2( 1, 1 ) ] } [node name="Monster" type="KinematicBody2D" index="0"] input_pickable = false collision_layer = 1 collision_mask = 1 collision/safe_margin = 0.08 script = ExtResource( 1 ) ARRIVE_DISTANCE = 6.0 DEFAULT_SLOW_RADIUS = 200.0 DEFAULT_MAX_SPEED = 300.0 MASS = 8.0 [node name="Stats" parent="." index="0" instance=ExtResource( 2 )] [node name="HitBox" parent="." index="1" instance=ExtResource( 3 )] [node name="Skin" type="Position2D" parent="." index="2"] _sections_unfolded = [ "Visibility" ] [node name="BodyPivot" type="Position2D" parent="Skin" index="0"] _sections_unfolded = [ "Transform", "Visibility" ] [node name="AnimationPlayer" type="AnimationPlayer" parent="." index="3"] root_node = NodePath("..") autoplay = "" playback_process_mode = 1 playback_default_blend_time = 0.0 playback_speed = 1.0 anims/SETUP = SubResource( 1 ) anims/die = SubResource( 2 ) anims/stagger = SubResource( 3 ) blend_times = [ ] [node name="InterfaceAnchor" parent="." index="4" instance=ExtResource( 4 )] position = Vector2( 0, -150.219 ) ================================================ FILE: monsters/ObstacleDetector.gd ================================================ # Detects collisions with the environment using raycasts # If collisions happen, emits a signal with a list of collision points extends Node2D signal rays_collided var rays = [] const RAYS_COUNT = 12 const RAYS_RADIUS = 100 func _ready(): for i in range(RAYS_COUNT): var new_ray = RayCast2D.new() var angle = 2 * PI * i / RAYS_COUNT new_ray.cast_to = Vector2(cos(angle), sin(angle)) * RAYS_RADIUS add_child(new_ray) new_ray.add_exception(get_parent().get_parent()) new_ray.enabled = true new_ray.collision_mask = 2 func _physics_process(delta): var collision_points = [] for ray in get_children(): if not ray.is_colliding(): continue collision_points.append(ray.get_collision_point()) if collision_points == []: return emit_signal('rays_collided', collision_points) ================================================ FILE: monsters/bosses/wild_boar/WildBoar.gd ================================================ extends "res://monsters/Monster.gd" signal hit_wall() onready var state_machine = $StateMachine onready var lifebar = $BossLifebar onready var health_node = $Stats onready var tween_node = $Tween var start_global_position func _ready(): visible = false set_invincible(true) start_global_position = global_position lifebar.initialize(health_node) func start(): lifebar.appear() state_machine.start() func _on_Health_health_depleted(): set_invincible(true) lifebar.disappear() func _on_Health_health_changed(new_health): tween_node.interpolate_property($Pivot, 'scale', Vector2(0.92, 1.12), Vector2(1.0, 1.0), 0.3, Tween.TRANS_ELASTIC, Tween.EASE_IN_OUT) tween_node.interpolate_property($Pivot/Body, 'modulate', Color('#ff48de'), Color('#ffffff'), 0.2, Tween.TRANS_QUINT, Tween.EASE_IN) tween_node.start() match state_machine.phase: 1: if new_health < 100: state_machine.phase = 2 2: if new_health < 50: state_machine.phase = 3 func set_particles_active(value): $DustPuffsLarge.emitting = value func set_invincible(value): $CollisionPolygon2D.disabled = value $HitBox/CollisionShape2D.disabled = value $DamageSource/CollisionShape2D.disabled = value $DamageSource.monitorable = not value func take_damage_from(attacker): health_node.take_damage(attacker.damage) func _on_Die_finished(): state_machine.set_active(false) emit_signal('died') queue_free() func _on_target_died(): ._on_target_died() state_machine.change_phase(4) state_machine.go_to_next_state() func _on_Sprint_hit_wall(): emit_signal('hit_wall') ================================================ FILE: monsters/bosses/wild_boar/WildBoar.tscn ================================================ [gd_scene load_steps=35 format=2] [ext_resource path="res://monsters/bosses/wild_boar/WildBoar.gd" type="Script" id=1] [ext_resource path="res://vfx/particles/dust_puffs/DustPuffsLarge.tscn" type="PackedScene" id=2] [ext_resource path="res://monsters/bosses/wild_boar/sprites/front.png" type="Texture" id=3] [ext_resource path="res://monsters/bosses/wild_boar/sprites/wild_boar_stomp_2.png" type="Texture" id=4] [ext_resource path="res://monsters/bosses/wild_boar/sprites/wild_boar_stomp_1.png" type="Texture" id=5] [ext_resource path="res://actors/health/Stats.tscn" type="PackedScene" id=6] [ext_resource path="res://monsters/bosses/wild_boar/WildBoarFSM.gd" type="Script" id=7] [ext_resource path="res://monsters/bosses/wild_boar/states/Spawn.gd" type="Script" id=8] [ext_resource path="res://monsters/bosses/wild_boar/states/roam/RoamSequence.gd" type="Script" id=9] [ext_resource path="res://monsters/bosses/wild_boar/states/roam/Wait.gd" type="Script" id=10] [ext_resource path="res://monsters/bosses/wild_boar/states/roam/MoveToRandomPosition.gd" type="Script" id=11] [ext_resource path="res://utils/state/Sequence.gd" type="Script" id=12] [ext_resource path="res://monsters/bosses/wild_boar/states/charge/Prepare.gd" type="Script" id=13] [ext_resource path="res://monsters/bosses/wild_boar/states/charge/Sprint.gd" type="Script" id=14] [ext_resource path="res://monsters/bosses/wild_boar/states/charge/BumpWildBoar.gd" type="Script" id=15] [ext_resource path="res://monsters/bosses/wild_boar/states/ReturnToCenter.gd" type="Script" id=16] [ext_resource path="res://monsters/bosses/wild_boar/states/stomp/Stomp.gd" type="Script" id=17] [ext_resource path="res://monsters/bosses/wild_boar/states/Die.gd" type="Script" id=18] [ext_resource path="res://vfx/particles/explosions/Explosion.tscn" type="PackedScene" id=19] [ext_resource path="res://actors/DamageSource.tscn" type="PackedScene" id=20] [ext_resource path="res://actors/hit_box/HitBox.tscn" type="PackedScene" id=21] [ext_resource path="res://interface/gui/boss/BossLifebar.tscn" type="PackedScene" id=22] [sub_resource type="Animation" id=1] resource_name = "SETUP" length = 0.05 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath("Pivot/Body:position") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 3.57628e-007, 17.6051 ) ] } tracks/1/type = "value" tracks/1/path = NodePath("Pivot/Body:rotation_degrees") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ 0.0 ] } tracks/2/type = "value" tracks/2/path = NodePath("Pivot/Body:scale") tracks/2/interp = 1 tracks/2/loop_wrap = true tracks/2/imported = false tracks/2/enabled = true tracks/2/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 1, 1 ) ] } tracks/3/type = "value" tracks/3/path = NodePath("Pivot/Body:modulate") tracks/3/interp = 1 tracks/3/loop_wrap = true tracks/3/imported = false tracks/3/enabled = true tracks/3/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ) ] } tracks/4/type = "value" tracks/4/path = NodePath("Pivot/Body:modulate") tracks/4/interp = 1 tracks/4/loop_wrap = true tracks/4/imported = false tracks/4/enabled = true tracks/4/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ) ] } tracks/5/type = "value" tracks/5/path = NodePath("Pivot/Body:texture") tracks/5/interp = 1 tracks/5/loop_wrap = true tracks/5/imported = false tracks/5/enabled = true tracks/5/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 1, "values": [ ExtResource( 3 ) ] } [sub_resource type="Animation" id=2] resource_name = "bump" length = 1.4 loop = false step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath("Pivot/Body:position") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.3, 0.55, 0.7, 0.85, 0.95, 1.05, 1.1, 1.15 ), "transitions": PoolRealArray( 0.225072, 1.67946, 0.367583, 1, 0.367583, 1, 0.367583, 1, 0.367583 ), "update": 0, "values": [ Vector2( 3.57628e-007, 17.6051 ), Vector2( 0, -37.6635 ), Vector2( 3.57628e-007, 17.6051 ), Vector2( 0, -6.75531 ), Vector2( 3.57628e-007, 17.6051 ), Vector2( 0, 8.69879 ), Vector2( 3.57628e-007, 17.6051 ), Vector2( 0, 17.8458 ), Vector2( 3.57628e-007, 17.6051 ) ] } [sub_resource type="Animation" id=3] length = 3.0 loop = false step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath("Pivot/Body:modulate") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.15, 0.3, 1.25, 1.6, 2.05, 2.25, 2.3, 2.35, 2.4, 2.45, 2.6, 2.75, 2.95 ), "transitions": PoolRealArray( 0.307901, 2.62585, 1, 0.307901, 2.62585, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ), Color( 10, 10, 10, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 1 ), Color( 10, 10, 10, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 0.296875, 0.296875, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 0.296875, 0.296875, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 0.296875, 0.296875, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ] } tracks/1/type = "value" tracks/1/path = NodePath("Pivot/Body:scale") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0, 0.5, 2.25, 2.6, 2.7, 2.9 ), "transitions": PoolRealArray( 1, 1, 1, 1, 2.94246, 1 ), "update": 0, "values": [ Vector2( 1, 1 ), Vector2( 1, 1 ), Vector2( 1, 1 ), Vector2( 1, 1 ), Vector2( 0.812022, 1.23284 ), Vector2( 2.7717, 0.0452506 ) ] } [sub_resource type="Animation" id=4] length = 0.01 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath("Pivot/Body:position") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 3.57628e-007, 17.6051 ) ] } [sub_resource type="Animation" id=5] resource_name = "move" length = 0.3 loop = true step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath("Pivot/Body:position") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.15 ), "transitions": PoolRealArray( 0.367583, 1.73627 ), "update": 0, "values": [ Vector2( 3.57628e-007, 17.6051 ), Vector2( 0, 0.113144 ) ] } [sub_resource type="Animation" id=6] resource_name = "prepare" length = 1.3 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath("Pivot/Body:scale") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.8 ), "transitions": PoolRealArray( 1, 1 ), "update": 0, "values": [ Vector2( 1, 1 ), Vector2( 1.08725, 0.772716 ) ] } [sub_resource type="Animation" id=7] resource_name = "spawn" length = 3.1 loop = false step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath("Pivot/Body:position") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.5, 2.9 ), "transitions": PoolRealArray( 1, 1, 1 ), "update": 0, "values": [ Vector2( -477.666, -688.279 ), Vector2( -477.666, -688.279 ), Vector2( 0, 0 ) ] } tracks/1/type = "value" tracks/1/path = NodePath("Pivot:position") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0, 0.5, 0.65, 0.8, 0.95, 1.1, 1.25, 1.4, 1.55, 1.7, 1.85, 2, 2.15, 2.3, 2.45, 2.6, 2.75, 2.9 ), "transitions": PoolRealArray( 1, 0.342967, 2.00422, 0.342967, 2.00422, 0.342967, 2.00422, 0.342967, 2.00422, 0.342967, 2.00422, 0.342967, 2.00422, 0.342967, 2.00422, 0.342967, 2.00422, 0.342967 ), "update": 0, "values": [ Vector2( 0, 0 ), Vector2( 0, 0 ), Vector2( 0, -45 ), Vector2( 0, 0 ), Vector2( 0, -45 ), Vector2( 0, 0 ), Vector2( 0, -45 ), Vector2( 0, 0 ), Vector2( 0, -45 ), Vector2( 0, 0 ), Vector2( 0, -45 ), Vector2( 0, 0 ), Vector2( 0, -45 ), Vector2( 0, 0 ), Vector2( 0, -45 ), Vector2( 0, 0 ), Vector2( 0, -45 ), Vector2( 0, 0 ) ] } tracks/2/type = "value" tracks/2/path = NodePath(".:visible") tracks/2/interp = 1 tracks/2/loop_wrap = true tracks/2/imported = false tracks/2/enabled = true tracks/2/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 1, "values": [ true ] } [sub_resource type="Animation" id=8] length = 0.9 loop = false step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath("Pivot/Body:position") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 3.57628e-007, 17.6051 ) ] } tracks/1/type = "value" tracks/1/path = NodePath("Pivot/Body:rotation_degrees") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ 0.0 ] } [sub_resource type="Animation" id=9] length = 0.1 loop = true step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath("Pivot/Body:scale") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.05 ), "transitions": PoolRealArray( 0.550489, 0.550489 ), "update": 0, "values": [ Vector2( 1, 1 ), Vector2( 1.08725, 0.772716 ) ] } [sub_resource type="Animation" id=10] length = 0.3 loop = false step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath("Pivot/Body:modulate") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.05, 0.1, 0.15, 0.2, 0.3 ), "transitions": PoolRealArray( 1, 1, 1, 1, 1, 1 ), "update": 0, "values": [ Color( 1, 0.296875, 0.296875, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 0.296875, 0.296875, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 0.296875, 0.296875, 1 ), Color( 1, 1, 1, 1 ) ] } [sub_resource type="Animation" id=11] resource_name = "stomp" length = 3.0 loop = false step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath("Pivot/Body:position") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.25, 0.3, 1, 1.1, 1.2 ), "transitions": PoolRealArray( 1, 1, 1, 1, 1, 1 ), "update": 0, "values": [ Vector2( 3.57628e-007, 17.6051 ), Vector2( 0, 23.1995 ), Vector2( 3.57628e-007, 17.6051 ), Vector2( 3.57628e-007, 17.6051 ), Vector2( 0.260636, 30.418 ), Vector2( 3.57628e-007, 17.6051 ) ] } tracks/1/type = "value" tracks/1/path = NodePath("Pivot/Body:rotation_degrees") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0, 0.3, 0.45, 0.65, 0.85, 1 ), "transitions": PoolRealArray( 1, 1, 1, 1, 1, 1 ), "update": 0, "values": [ 0.0, 0.0, -4.36329, 1.8451, -4.4684, 0.333169 ] } tracks/2/type = "value" tracks/2/path = NodePath("Pivot/Body:scale") tracks/2/interp = 1 tracks/2/loop_wrap = true tracks/2/imported = false tracks/2/enabled = true tracks/2/keys = { "times": PoolRealArray( 0, 0.25, 0.3, 1, 1.1, 1.2 ), "transitions": PoolRealArray( 1, 1, 1, 1, 1, 1 ), "update": 0, "values": [ Vector2( 1, 1 ), Vector2( 1.14791, 0.896572 ), Vector2( 1, 1 ), Vector2( 1, 1 ), Vector2( 1.16872, 0.836578 ), Vector2( 1, 1 ) ] } tracks/3/type = "value" tracks/3/path = NodePath("Pivot/Body:texture") tracks/3/interp = 1 tracks/3/loop_wrap = true tracks/3/imported = false tracks/3/enabled = true tracks/3/keys = { "times": PoolRealArray( 0, 0.3, 1.1, 1.25 ), "transitions": PoolRealArray( 1, 1, 1, 1 ), "update": 1, "values": [ ExtResource( 4 ), ExtResource( 5 ), ExtResource( 4 ), ExtResource( 3 ) ] } tracks/4/type = "method" tracks/4/path = NodePath("StateMachine/Stomp") tracks/4/interp = 1 tracks/4/loop_wrap = true tracks/4/imported = false tracks/4/enabled = true tracks/4/keys = { "times": PoolRealArray( 1.15 ), "transitions": PoolRealArray( 1 ), "values": [ { "args": [ ], "method": "stomp" } ] } [sub_resource type="CircleShape2D" id=12] custom_solver_bias = 0.0 radius = 50.0 [node name="WildBoar" type="KinematicBody2D" index="0" groups=[ "monster", ]] input_pickable = false collision_layer = 1 collision_mask = 2 collision/safe_margin = 0.08 script = ExtResource( 1 ) _sections_unfolded = [ "Transform", "Visibility", "Z Index" ] __meta__ = { "_edit_group_": true } ARRIVE_DISTANCE = 6.0 DEFAULT_SLOW_RADIUS = 200.0 DEFAULT_MAX_SPEED = 300.0 MASS = 1.4 [node name="DustPuffsLarge" parent="." index="0" instance=ExtResource( 2 )] emitting = false [node name="AnimationPlayer" type="AnimationPlayer" parent="." index="1"] root_node = NodePath("..") autoplay = "" playback_process_mode = 1 playback_default_blend_time = 0.0 playback_speed = 1.0 anims/SETUP = SubResource( 1 ) anims/bump = SubResource( 2 ) anims/die = SubResource( 3 ) anims/idle = SubResource( 4 ) anims/move = SubResource( 5 ) anims/prepare = SubResource( 6 ) anims/spawn = SubResource( 7 ) anims/spot = SubResource( 8 ) anims/sprint = SubResource( 9 ) anims/stagger = SubResource( 10 ) anims/stomp = SubResource( 11 ) blend_times = [ ] [node name="Tween" type="Tween" parent="." index="2"] repeat = false playback_process_mode = 1 playback_speed = 1.0 playback/active = false playback/repeat = false playback/speed = 1.0 [node name="Stats" parent="." index="3" instance=ExtResource( 6 )] max_health = 120 [node name="StateMachine" type="Node" parent="." index="4"] script = ExtResource( 7 ) active = false phase = 1 [node name="Spawn" type="Node" parent="StateMachine" index="0"] script = ExtResource( 8 ) [node name="RoamSequence" type="Node" parent="StateMachine" index="1"] script = ExtResource( 9 ) [node name="Wait" type="Node" parent="StateMachine/RoamSequence" index="0"] editor/display_folded = true script = ExtResource( 10 ) [node name="Timer" type="Timer" parent="StateMachine/RoamSequence/Wait" index="0"] process_mode = 1 wait_time = 1.0 one_shot = true autostart = false [node name="MoveTo" type="Node" parent="StateMachine/RoamSequence" index="1"] script = ExtResource( 11 ) ARRIVE_DISTANCE = 6.0 SLOW_RADIUS = 200.0 MASS = 4.0 MAX_SPEED = 300.0 ROAM_RADIUS = 150.0 [node name="ChargeSequence" type="Node" parent="StateMachine" index="2"] script = ExtResource( 12 ) [node name="Prepare" type="Node" parent="StateMachine/ChargeSequence" index="0"] script = ExtResource( 13 ) [node name="Sprint" type="Node" parent="StateMachine/ChargeSequence" index="1"] script = ExtResource( 14 ) SPEED = 1000.0 MAX_DISTANCE = 1200.0 [node name="Bump" type="Node" parent="StateMachine/ChargeSequence" index="2"] script = ExtResource( 15 ) SPEED = 100.0 [node name="ReturnToCenter" type="Node" parent="StateMachine/ChargeSequence" index="3"] script = ExtResource( 16 ) MASS = 4.0 SLOW_RADIUS = 200.0 MAX_SPEED = 300.0 ARRIVE_DISTANCE = 6.0 [node name="Stomp" type="Node" parent="StateMachine" index="3"] editor/display_folded = true script = ExtResource( 17 ) [node name="ExplodeTimer" type="Timer" parent="StateMachine/Stomp" index="0"] process_mode = 1 wait_time = 0.2 one_shot = false autostart = false [node name="Die" type="Node" parent="StateMachine" index="4"] editor/display_folded = true script = ExtResource( 18 ) MAX_RADIUS = 180.0 Explosion = ExtResource( 19 ) [node name="ExplodeTimer" type="Timer" parent="StateMachine/Die" index="0"] process_mode = 1 wait_time = 0.15 one_shot = false autostart = false [node name="Pivot" type="Position2D" parent="." index="5"] _sections_unfolded = [ "Transform", "Visibility", "Z Index" ] [node name="Body" type="Sprite" parent="Pivot" index="0"] position = Vector2( -477.666, -688.279 ) rotation = 0.0058149 texture = ExtResource( 3 ) offset = Vector2( -1.98642, -55.6066 ) _sections_unfolded = [ "Offset", "Transform", "Visibility", "Z Index" ] [node name="DamageSource" parent="." index="6" instance=ExtResource( 20 )] position = Vector2( 0, -27.075 ) monitorable = false damage = 4 [node name="CollisionShape2D" type="CollisionShape2D" parent="DamageSource" index="0"] position = Vector2( 0, -17.075 ) shape = SubResource( 12 ) [node name="HitBox" parent="." index="7" instance=ExtResource( 21 )] collision_layer = 8 collision_mask = 16 [node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="." index="8"] position = Vector2( 0, 21.5742 ) build_mode = 0 polygon = PoolVector2Array( -36, -96, 36, -96, 36, -24, -36, -24 ) _sections_unfolded = [ "Visibility" ] [node name="BossLifebar" parent="." index="9" instance=ExtResource( 22 )] margin_top = -153.0 margin_bottom = -60.0 boss_name = "Wild Boar" [connection signal="animation_finished" from="AnimationPlayer" to="StateMachine" method="_on_animation_finished"] [connection signal="health_changed" from="Stats" to="." method="_on_Health_health_changed"] [connection signal="health_depleted" from="Stats" to="StateMachine" method="_on_Health_health_depleted"] [connection signal="health_depleted" from="Stats" to="." method="_on_Health_health_depleted"] [connection signal="charge_direction_set" from="StateMachine/ChargeSequence/Sprint" to="StateMachine/ChargeSequence/Bump" method="_on_Sprint_charge_direction_set"] [connection signal="hit_wall" from="StateMachine/ChargeSequence/Sprint" to="." method="_on_Sprint_hit_wall"] [connection signal="finished" from="StateMachine/Die" to="." method="_on_Die_finished"] [connection signal="timeout" from="StateMachine/Die/ExplodeTimer" to="StateMachine/Die" method="_on_ExplodeTimer_timeout"] ================================================ FILE: monsters/bosses/wild_boar/WildBoarFSM.gd ================================================ extends "res://utils/state/StateMachine.gd" signal phase_changed(number) var sequence_cycles = 0 export(int, 1, 3) var phase = 1 func _ready(): for child in get_children(): child.connect("finished", self, "go_to_next_state") func initialize(): change_phase(phase) func _on_active_state_finished(): go_to_next_state() func go_to_next_state(state_override=null): if not active: return current_state.exit() current_state = _decide_on_next_state() if state_override == null else state_override emit_signal("state_changed", current_state) current_state.enter() func _decide_on_next_state(): # Battle start if current_state == null: return $Spawn if current_state == $Spawn: return $RoamSequence if phase == 1: if current_state == $RoamSequence: sequence_cycles += 1 if sequence_cycles < 2: return $RoamSequence else: sequence_cycles = 0 return $Stomp if current_state == $Stomp: return $RoamSequence elif phase == 2: if current_state == $RoamSequence: return $Stomp if current_state == $Stomp: if sequence_cycles < 2: sequence_cycles += 1 return $Stomp else: sequence_cycles = 0 return $ChargeSequence if current_state == $ChargeSequence: return $RoamSequence elif phase == 3: if current_state == $RoamSequence: return $Stomp if current_state == $Stomp: if sequence_cycles < 2: sequence_cycles += 1 return $Stomp else: sequence_cycles = 0 return $ChargeSequence if current_state == $ChargeSequence: if sequence_cycles < 2: sequence_cycles += 1 return $ChargeSequence else: sequence_cycles = 0 return $Stomp elif phase == 4: return $RoamSequence func change_phase(new_phase): phase = new_phase var anim_player = owner.get_node('AnimationPlayer') match new_phase: 1: anim_player.playback_speed = 1.0 2: anim_player.playback_speed = 1.4 3: anim_player.playback_speed = 1.8 4: anim_player.playback_speed = 1.0 emit_signal("phase_changed", new_phase) func _on_Health_health_depleted(): go_to_next_state($Die) ================================================ FILE: monsters/bosses/wild_boar/debug/BossStatesDisplayer.gd ================================================ tool extends Panel func _ready(): set_as_toplevel(true) func _on_WildBoar_state_changed(new_state_name): $State.text = new_state_name func _on_WildBoar_phase_changed(new_phase_name): $Phase.text = "Phase: " + new_phase_name ================================================ FILE: monsters/bosses/wild_boar/debug/StatesStackDiplayer.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://debug/states_stack_displayer.gd" type="Script" id=1] [ext_resource path="res://debug/fonts/stack_state_displayer_font.tres" type="DynamicFont" id=2] [node name="StatesStackDiplayer" type="Panel"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_right = 210.0 margin_bottom = 170.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 script = ExtResource( 1 ) __meta__ = { "_edit_group_": true } [node name="Title" type="Label" parent="." index="0"] anchor_left = 0.5 anchor_top = 0.0 anchor_right = 0.5 anchor_bottom = 0.0 margin_left = -105.0 margin_right = 105.0 margin_bottom = 40.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 custom_fonts/font = ExtResource( 2 ) text = "Player" align = 1 valign = 1 uppercase = true percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "custom_fonts" ] [node name="States" type="Label" parent="." index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 20.0 margin_top = 50.0 margin_right = 190.0 margin_bottom = 170.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 custom_fonts/font = ExtResource( 2 ) text = "Jump Test" align = 1 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "custom_fonts" ] [node name="Numbers" type="Label" parent="." index="2"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 20.0 margin_top = 50.0 margin_right = 190.0 margin_bottom = 170.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 custom_fonts/font = ExtResource( 2 ) text = "1. 2." percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "custom_fonts" ] ================================================ FILE: monsters/bosses/wild_boar/debug/StatesStackDisplayer.gd ================================================ tool extends Panel func _ready(): set_as_toplevel(true) func _on_Player_state_changed(states_stack): var states_names = '' var numbers = '' var index = 0 for state in states_stack: states_names += state.get_name() + '\n' numbers += str(index) + '\n' index += 1 $States.text = states_names $Numbers.text = numbers ================================================ FILE: monsters/bosses/wild_boar/sprites/front.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/front.png-057d3dd7010286ac73782a3387387e0a.stex" metadata={ "vram_texture": false } [deps] source_file="res://monsters/bosses/wild_boar/sprites/front.png" dest_files=[ "res://.import/front.png-057d3dd7010286ac73782a3387387e0a.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: monsters/bosses/wild_boar/sprites/wild_boar_stomp_1.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/wild_boar_stomp_1.png-d07b8919e74a2c01fc887ee3913e97cc.stex" metadata={ "vram_texture": false } [deps] source_file="res://monsters/bosses/wild_boar/sprites/wild_boar_stomp_1.png" dest_files=[ "res://.import/wild_boar_stomp_1.png-d07b8919e74a2c01fc887ee3913e97cc.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: monsters/bosses/wild_boar/sprites/wild_boar_stomp_2.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/wild_boar_stomp_2.png-17bc22f03cf0802ac3e65515e42132c8.stex" metadata={ "vram_texture": false } [deps] source_file="res://monsters/bosses/wild_boar/sprites/wild_boar_stomp_2.png" dest_files=[ "res://.import/wild_boar_stomp_2.png-17bc22f03cf0802ac3e65515e42132c8.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: monsters/bosses/wild_boar/states/Die.gd ================================================ extends "res://utils/state/State.gd" export(float) var MAX_RADIUS = 300.0 export(PackedScene) var Explosion func enter(): owner.get_node('AnimationPlayer').play('die') $ExplodeTimer.start() func _on_ExplodeTimer_timeout(): spawn_explosion() func spawn_explosion(): var explosion_node = Explosion.instance() explosion_node.position = owner.position + calculate_random_offset() add_child(explosion_node) func calculate_random_offset(): randomize() var random_angle = randf() * 2 * PI randomize() var random_radius = (randf() * MAX_RADIUS) / 2 + MAX_RADIUS / 2 return Vector2(cos(random_angle) * random_radius, sin(random_angle) * random_radius) func _on_animation_finished(anim_name): $ExplodeTimer.stop() assert(anim_name == 'die') get_tree().create_timer(0.6).connect("timeout", self, 'emit_signal', ['finished']) ================================================ FILE: monsters/bosses/wild_boar/states/Follow.gd ================================================ extends "res://utils/state/State.gd" func enter(): owner.get_node('AnimationPlayer').play('stomp') func _on_animation_finished(anim_name): emit_signal('finished') ================================================ FILE: monsters/bosses/wild_boar/states/ReturnToCenter.gd ================================================ extends "res://utils/state/State.gd" export(float) var MASS = 4.0 export(float) var SLOW_RADIUS = 200.0 export(float) var MAX_SPEED = 300.0 export(float) var ARRIVE_DISTANCE = 6.0 var velocity = Vector2() func enter(): owner.get_node('AnimationPlayer').play('move') func update(delta): velocity = Steering.arrive_to(velocity, owner.global_position, owner.start_global_position, MASS, SLOW_RADIUS, MAX_SPEED) owner.move_and_slide(velocity) if owner.global_position.distance_to(owner.start_global_position) < ARRIVE_DISTANCE: emit_signal('finished') ================================================ FILE: monsters/bosses/wild_boar/states/Spawn.gd ================================================ extends "res://utils/state/State.gd" func enter(): owner.set_invincible(true) owner.get_node('AnimationPlayer').play('spawn') func exit(): owner.set_invincible(false) func _on_animation_finished(anim_name): assert(anim_name == 'spawn') emit_signal('finished') ================================================ FILE: monsters/bosses/wild_boar/states/charge/BumpWildBoar.gd ================================================ extends "res://utils/state/State.gd" export(float) var SPEED = 60.0 var direction = Vector2(-1.0, 0.0) func enter(): owner.get_node('AnimationPlayer').play('bump') owner.get_node('Pivot/Body').scale = Vector2(1.0, 1.0) func update(delta): owner.move_and_slide(direction * SPEED) func _on_animation_finished(anim_name): emit_signal('finished') func _on_Sprint_charge_direction_set(charge_direction): direction = -charge_direction ================================================ FILE: monsters/bosses/wild_boar/states/charge/Prepare.gd ================================================ extends "res://utils/state/State.gd" func enter(): owner.get_node('AnimationPlayer').play('prepare') func _on_animation_finished(anim_name): emit_signal('finished') ================================================ FILE: monsters/bosses/wild_boar/states/charge/Sprint.gd ================================================ extends "res://utils/state/State.gd" signal charge_direction_set(direction) signal hit_wall() export(float) var SPEED = 1000.0 export(float) var MAX_DISTANCE = 1200.0 var direction = Vector2() var distance = 0.0 const DirectionalRock = preload("res://vfx/particles/rocks/DirectionalRock.tscn") const PlayerController = preload("res://actors/player/PlayerController.gd") func enter(): distance = 0.0 direction = (owner.target.global_position - owner.global_position).normalized() owner.get_node('AnimationPlayer').play('sprint') owner.set_particles_active(true) func exit(): owner.set_particles_active(false) func update(delta): var velocity = SPEED * direction owner.move_and_slide(velocity) distance += velocity.length() * delta if owner.get_slide_count() > 0: var collision = owner.get_slide_collision(0) if not collision.collider is PlayerController: spawn_rock_particles(collision) emit_signal('hit_wall') emit_signal('charge_direction_set', direction) emit_signal('finished') elif distance > MAX_DISTANCE: emit_signal('charge_direction_set', Vector2()) func spawn_rock_particles(collision): var rock_particles = DirectionalRock.instance() add_child(rock_particles) rock_particles.initialize(collision.position, collision.normal.angle()) ================================================ FILE: monsters/bosses/wild_boar/states/roam/MoveToRandomPosition.gd ================================================ extends "res://utils/state/State.gd" export(float) var ARRIVE_DISTANCE = 6.0 export(float) var SLOW_RADIUS = 200.0 export(float) var MASS = 4.0 export(float) var MAX_SPEED = 300.0 export(float) var ROAM_RADIUS = 150.0 var target_position = Vector2() var start_position = Vector2() var velocity = Vector2() func enter(): start_position = get_parent().start_position target_position = calculate_new_target_position() owner.get_node('AnimationPlayer').play('move') func update(delta): velocity = Steering.arrive_to(velocity, owner.global_position, target_position, MASS, SLOW_RADIUS, MAX_SPEED) owner.move_and_slide(velocity) if owner.get_slide_count() > 0: emit_signal('finished') elif owner.global_position.distance_to(target_position) < ARRIVE_DISTANCE: emit_signal('finished') func calculate_new_target_position(): randomize() var random_angle = randf() * 2 * PI randomize() var random_radius = (randf() * ROAM_RADIUS) / 2 + ROAM_RADIUS / 2 return start_position + Vector2(cos(random_angle) * random_radius, sin(random_angle) * random_radius) ================================================ FILE: monsters/bosses/wild_boar/states/roam/RoamSequence.gd ================================================ extends "res://utils/state/Sequence.gd" var start_position = Vector2() func enter(): start_position = owner.global_position .enter() func exit(): .exit() func update(delta): .update(delta) ================================================ FILE: monsters/bosses/wild_boar/states/roam/Wait.gd ================================================ extends "res://utils/state/State.gd" func enter(): owner.get_node('AnimationPlayer').play('idle') $Timer.start() func update(delta): if $Timer.time_left <= 0.0: emit_signal('finished') func exit(): $Timer.stop() ================================================ FILE: monsters/bosses/wild_boar/states/stomp/GroundExplosion.gd ================================================ extends "res://actors/DamageSource.gd" func _ready(): $AnimationPlayer.play('explode') func _physics_process(delta): position = position ================================================ FILE: monsters/bosses/wild_boar/states/stomp/GroundExplosion.tscn ================================================ [gd_scene load_steps=6 format=2] [ext_resource path="res://actors/DamageSource.tscn" type="PackedScene" id=1] [ext_resource path="res://monsters/bosses/wild_boar/states/stomp/GroundExplosion.gd" type="Script" id=2] [ext_resource path="res://core/inventory/items/usable/scroll_fireball/fireball/particles/explosions/Explosion.tscn" type="PackedScene" id=3] [sub_resource type="CircleShape2D" id=1] custom_solver_bias = 0.0 radius = 45.1559 [sub_resource type="Animation" id=2] resource_name = "explode" length = 0.5 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath("CollisionShape2D:disabled") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.4 ), "transitions": PoolRealArray( 1, 1 ), "update": 1, "values": [ false, true ] } tracks/1/type = "value" tracks/1/path = NodePath("Explosion:emitting") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0, 0.4 ), "transitions": PoolRealArray( 0, 0 ), "update": 1, "values": [ true, false ] } tracks/2/type = "method" tracks/2/path = NodePath(".") tracks/2/interp = 1 tracks/2/loop_wrap = true tracks/2/imported = false tracks/2/enabled = true tracks/2/keys = { "times": PoolRealArray( 0.4 ), "transitions": PoolRealArray( 1 ), "values": [ { "args": [ ], "method": "queue_free" } ] } [node name="GroundExplosion" instance=ExtResource( 1 )] script = ExtResource( 2 ) [node name="CollisionShape2D" type="CollisionShape2D" parent="." index="0"] shape = SubResource( 1 ) disabled = true [node name="Explosion" parent="." index="1" instance=ExtResource( 3 )] [node name="AnimationPlayer" type="AnimationPlayer" parent="." index="2"] root_node = NodePath("..") autoplay = "" playback_process_mode = 1 playback_default_blend_time = 0.0 playback_speed = 1.0 anims/explode = SubResource( 2 ) blend_times = [ ] ================================================ FILE: monsters/bosses/wild_boar/states/stomp/Stomp.gd ================================================ extends "res://utils/state/State.gd" var explosion_scene = preload("GroundExplosion.tscn") var explosion_count = 0 var direction = Vector2() func _ready(): $ExplodeTimer.connect("timeout", self, "_on_ExplodeTimer_timeout") func enter(): explosion_count = 0 owner.get_node('AnimationPlayer').play('stomp') func _on_animation_finished(anim_name): $ExplodeTimer.stop() emit_signal('finished') func stomp(): direction = (owner.target.position - owner.global_position).normalized() $ExplodeTimer.start() explode() func _on_ExplodeTimer_timeout(): explode() func explode(): explosion_count += 1 var new_explosion = explosion_scene.instance() new_explosion.position = owner.position + explosion_count * direction * 80.0 self.add_child(new_explosion) ================================================ FILE: monsters/bosses/wild_boar/states/stomp/Stomp.tscn ================================================ [gd_scene load_steps=2 format=2] [ext_resource path="res://monsters/bosses/wild_boar/states/stomp/Stomp.gd" type="Script" id=1] [node name="Stomp" type="Node"] script = ExtResource( 1 ) [node name="ExplodeTimer" type="Timer" parent="." index="0"] process_mode = 1 wait_time = 0.2 one_shot = false autostart = false ================================================ FILE: monsters/exclamation-mark.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/exclamation-mark.png-71455c01c46e91dfa6565f7fa57a362a.stex" metadata={ "vram_texture": false } [deps] source_file="res://monsters/exclamation-mark.png" dest_files=[ "res://.import/exclamation-mark.png-71455c01c46e91dfa6565f7fa57a362a.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: monsters/exclamation-mark.svg.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/exclamation-mark.svg-17d593f918361282d38491dd92cc9311.stex" [deps] source_file="res://monsters/exclamation-mark.svg" source_md5="8148dc8f2a7d33524acc8429e13b1cf5" dest_files=[ "res://.import/exclamation-mark.svg-17d593f918361282d38491dd92cc9311.stex" ] dest_md5="3647bb80cc90a5818d62bf39516420e2" [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: monsters/mosquito/Mosquito.gd ================================================ extends '../Monster.gd' enum { IDLE, RETURN, SPOT, FOLLOW, DIE} export(float) var FOLLOW_RANGE = 300.0 export(float) var MAX_FLY_SPEED = 360.0 func _ready(): _change_state(IDLE) func _change_state(new_state): match new_state: IDLE: pass DIE: queue_free() emit_signal('died') state = new_state func _physics_process(delta): var current_state = state match current_state: IDLE: if not target: return if position.distance_to(target.position) <= FOLLOW_RANGE: _change_state(FOLLOW) FOLLOW: if not target: return if position.distance_to(target.position) > FOLLOW_RANGE: _change_state(RETURN) return velocity = Steering.follow(velocity, position, target.position, MAX_FLY_SPEED) move_and_slide(velocity) rotation = velocity.angle() RETURN: velocity = Steering.arrive_to(velocity, position, start_position) move_and_slide(velocity) rotation = velocity.angle() if position.distance_to(start_position) < ARRIVE_DISTANCE: _change_state(IDLE) func _on_DamageSource_area_entered(area): _change_state(DIE) func _on_Stats_damage_taken(new_health): _change_state(DIE) ================================================ FILE: monsters/mosquito/Mosquito.tscn ================================================ [gd_scene load_steps=9 format=2] [ext_resource path="res://monsters/mosquito/Mosquito.gd" type="Script" id=1] [ext_resource path="res://actors/health/Stats.tscn" type="PackedScene" id=2] [ext_resource path="res://actors/hit_box/HitBox.tscn" type="PackedScene" id=3] [ext_resource path="res://actors/DamageSource.tscn" type="PackedScene" id=4] [ext_resource path="res://monsters/exclamation-mark.png" type="Texture" id=5] [ext_resource path="res://monsters/mosquito/mosquito.png" type="Texture" id=6] [sub_resource type="CircleShape2D" id=1] custom_solver_bias = 0.0 radius = 38.4768 [sub_resource type="CircleShape2D" id=2] custom_solver_bias = 0.0 radius = 24.9469 [node name="Mosquito" type="KinematicBody2D" groups=[ "character", ]] position = Vector2( -1.98642, 0.817726 ) input_pickable = false collision_layer = 2 collision_mask = 1 collision/safe_margin = 0.08 script = ExtResource( 1 ) _sections_unfolded = [ "Collision", "Z Index" ] ARRIVE_DISTANCE = 6.0 DEFAULT_SLOW_RADIUS = 200.0 DEFAULT_MAX_SPEED = 300.0 MASS = 8.0 FOLLOW_RANGE = 300.0 MAX_FLY_SPEED = 360.0 [node name="Stats" parent="." index="0" instance=ExtResource( 2 )] max_health = 1 [node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="." index="1"] position = Vector2( -3.01358, 49.1823 ) build_mode = 0 polygon = PoolVector2Array( -18.0136, -69.4669, -18.0136, -29.4669, 31.9864, -29.4669, 31.9864, -69.4669 ) disabled = true _sections_unfolded = [ "Transform" ] [node name="HitBox" parent="." index="2" instance=ExtResource( 3 )] editor/display_folded = true collision_layer = 8 collision_mask = 16 [node name="CollisionShape2D" parent="HitBox" index="0"] position = Vector2( 6, -2.42273 ) shape = SubResource( 1 ) [node name="DamageSource" parent="." index="3" instance=ExtResource( 4 )] editor/display_folded = true monitoring = true _sections_unfolded = [ "Audio Bus", "Collision" ] damage = 3 [node name="CollisionShape2D" type="CollisionShape2D" parent="DamageSource" index="0"] position = Vector2( 6, 0 ) shape = SubResource( 2 ) [node name="BodyPivot" type="Position2D" parent="." index="4"] editor/display_folded = true z_index = 2 _sections_unfolded = [ "Transform", "Visibility", "Z Index" ] [node name="exclamation-mark" type="Sprite" parent="BodyPivot" index="0"] self_modulate = Color( 1, 1, 1, 0 ) position = Vector2( 74.8139, -90 ) rotation = 0.253141 texture = ExtResource( 5 ) _sections_unfolded = [ "Visibility" ] [node name="Sprite" type="Sprite" parent="BodyPivot" index="1"] position = Vector2( 1.40846, -1.88954 ) texture = ExtResource( 6 ) offset = Vector2( 15.695, 0.889542 ) [node name="Timer" type="Timer" parent="." index="5"] process_mode = 1 wait_time = 1.0 one_shot = false autostart = false [node name="RayCast2D" type="RayCast2D" parent="." index="6"] visible = false enabled = false exclude_parent = true cast_to = Vector2( 0, 50 ) collision_mask = 1 [connection signal="damage_taken" from="Stats" to="." method="_on_Stats_damage_taken"] [connection signal="area_entered" from="DamageSource" to="." method="_on_DamageSource_area_entered"] [editable path="HitBox"] ================================================ FILE: monsters/mosquito/Nest.gd ================================================ extends Node2D export(int) var MAX_MOSQUITO_COUNT = 2 var Mosquito = preload("Mosquito.tscn") onready var timer = $SpawnTimer onready var collider = $SpawnArea/CollisionShape2D onready var mosquitos = $Mosquitos var target func initialize(actor): target = actor func _on_SpawnTimer_timeout(): if mosquitos.get_child_count() < MAX_MOSQUITO_COUNT: spawn_mosquito() func spawn_mosquito(): var new_mosquito = Mosquito.instance() new_mosquito.global_position = calculate_random_spawn_position() new_mosquito.initialize(target) mosquitos.add_child(new_mosquito) func calculate_random_spawn_position(): var spawn_radius = collider.shape.radius var random_angle = randf() * 2 * PI var random_radius = randf() * spawn_radius / 2 + spawn_radius / 2 return collider.global_position + Vector2(cos(random_angle) * random_radius, sin(random_angle) * random_radius) ================================================ FILE: monsters/mosquito/Nest.tscn ================================================ [gd_scene load_steps=5 format=2] [ext_resource path="res://monsters/mosquito/Nest.gd" type="Script" id=1] [ext_resource path="res://monsters/mosquito/nest.png" type="Texture" id=2] [sub_resource type="CircleShape2D" id=1] custom_solver_bias = 0.0 radius = 40.0 [sub_resource type="GDScript" id=2] script/source = "extends Timer func _ready(): wait_time = randf() *1.5 + 2.0 " [node name="Nest" type="Node2D" index="0" groups=[ "monster", ]] position = Vector2( 468, 202 ) script = ExtResource( 1 ) MAX_MOSQUITO_COUNT = 2 [node name="Sprite" type="Sprite" parent="." index="0"] position = Vector2( 0, 10 ) texture = ExtResource( 2 ) [node name="SpawnArea" type="Area2D" parent="." index="1"] input_pickable = true gravity_vec = Vector2( 0, 1 ) gravity = 98.0 linear_damp = 0.1 angular_damp = 1.0 monitoring = false monitorable = false audio_bus_override = false audio_bus_name = "Master" [node name="CollisionShape2D" type="CollisionShape2D" parent="SpawnArea" index="0"] position = Vector2( 0, -6.43921 ) shape = SubResource( 1 ) [node name="SpawnTimer" type="Timer" parent="." index="2"] process_mode = 1 wait_time = 2.0 one_shot = false autostart = true script = SubResource( 2 ) [node name="Mosquitos" type="Node" parent="." index="3"] [connection signal="timeout" from="SpawnTimer" to="." method="_on_SpawnTimer_timeout"] ================================================ FILE: monsters/mosquito/mosquito.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/mosquito.png-321e9de6070b983093d0eeac1e99b420.stex" metadata={ "vram_texture": false } [deps] source_file="res://monsters/mosquito/mosquito.png" dest_files=[ "res://.import/mosquito.png-321e9de6070b983093d0eeac1e99b420.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: monsters/mosquito/nest.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/nest.png-b3e74c0f42f31be173ab28e91ca5d1a6.stex" metadata={ "vram_texture": false } [deps] source_file="res://monsters/mosquito/nest.png" dest_files=[ "res://.import/nest.png-b3e74c0f42f31be173ab28e91ca5d1a6.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: monsters/porcupine/Porcupine.gd ================================================ extends '../Monster.gd' enum { IDLE, ROAM, RETURN, SPOT, FOLLOW, STAGGER, PREPARE_TO_CHARGE, CHARGE, BUMP, BUMP_COOLDOWN, HIT_PLAYER_COOLDOWN, DIE, DEAD} export(float) var MAX_ROAM_SPEED = 200.0 export(float) var MAX_FOLLOW_SPEED = 400.0 export(float) var MAX_CHARGE_SPEED = 900.0 export(float) var SPOT_RANGE = 460.0 export(float) var FOLLOW_RANGE = 700.0 export(float) var BUMP_RANGE = 90.0 export(float) var CHARGE_RANGE = 340.0 export(float) var PREPARE_TO_CHARGE_WAIT_TIME = 0.9 onready var timer = $Timer onready var body_pivot = $BodyPivot onready var dust_puffs = $DustPuffs onready var anim_player = $AnimationPlayer onready var tween = $Tween var charge_direction = Vector2() var charge_distance = 0.0 export(float) var ROAM_RADIUS = 140.0 var roam_target_position = Vector2() var roam_slow_radius = 0.0 export(float) var BUMP_DISTANCE = 60.0 export(float) var BUMP_DURATION = 0.2 export(float) var MAX_BUMP_HEIGHT = 50.0 export(float) var BUMP_COOLDOWN_DURATION = 0.6 func initialize(target_actor): .initialize(target_actor) tween.connect('tween_completed', self, '_on_tween_completed') anim_player.connect('animation_finished', self, '_on_animation_finished') timer.connect('timeout', self, '_on_Timer_timeout') _change_state(IDLE) func _change_state(new_state): if not active: return match state: IDLE: timer.stop() CHARGE: dust_puffs.emitting = false match new_state: IDLE: randomize() timer.wait_time = randf() * 2 + 1.0 timer.start() ROAM: randomize() var random_angle = randf() * 2 * PI randomize() var random_radius = (randf() * ROAM_RADIUS) / 2 + ROAM_RADIUS / 2 roam_target_position = start_position + Vector2(cos(random_angle) * random_radius, sin(random_angle) * random_radius) roam_slow_radius = roam_target_position.distance_to(start_position) / 2 STAGGER: anim_player.play("stagger") SPOT: anim_player.play('spot') PREPARE_TO_CHARGE: timer.wait_time = PREPARE_TO_CHARGE_WAIT_TIME timer.start() CHARGE: if not target: return charge_direction = (target.position - position).normalized() charge_distance = 0.0 dust_puffs.emitting = true BUMP: anim_player.stop() var bump_direction = - velocity.normalized() tween.interpolate_property(self, 'position', position, position + BUMP_DISTANCE * bump_direction, BUMP_DURATION, Tween.TRANS_LINEAR, Tween.EASE_IN) tween.interpolate_method(self, '_animate_bump_height', 0, 1, BUMP_DURATION, Tween.TRANS_LINEAR, Tween.EASE_IN) tween.start() BUMP_COOLDOWN: randomize() get_tree().create_timer(BUMP_COOLDOWN_DURATION).connect('timeout', self, '_change_state', [FOLLOW]) DEAD: anim_player.play("die") set_active(false) yield(anim_player, "animation_finished") queue_free() state = new_state func _physics_process(delta): var current_state = state match current_state: IDLE: if not target: return if position.distance_to(target.position) < SPOT_RANGE: _change_state(SPOT) ROAM: velocity = Steering.arrive_to(velocity, position, roam_target_position, roam_slow_radius, MAX_ROAM_SPEED) move_and_slide(velocity) if position.distance_to(roam_target_position) < ARRIVE_DISTANCE: _change_state(IDLE) if not target: return elif position.distance_to(target.position) < SPOT_RANGE: _change_state(SPOT) RETURN: velocity = Steering.arrive_to(velocity, position, start_position, roam_slow_radius, MAX_ROAM_SPEED) move_and_slide(velocity) if position.distance_to(start_position) < ARRIVE_DISTANCE: _change_state(IDLE) elif not target: return elif position.distance_to(target.position) < SPOT_RANGE: _change_state(SPOT) FOLLOW: if not target: _change_state(RETURN) return velocity = Steering.follow(velocity, position, target.position, MAX_FOLLOW_SPEED) move_and_slide(velocity) if position.distance_to(target.position) < CHARGE_RANGE: _change_state(PREPARE_TO_CHARGE) if position.distance_to(target.position) > FOLLOW_RANGE: _change_state(RETURN) CHARGE: if charge_distance > 800.0 or not target: _change_state(BUMP_COOLDOWN) return velocity = charge_direction * MAX_CHARGE_SPEED charge_distance += velocity.length() * delta move_and_slide(velocity) if get_slide_count() > 0: _change_state(BUMP) func _on_animation_finished(anim_name): match anim_name: 'spot': _change_state(FOLLOW) 'stagger': _change_state(IDLE) func _animate_bump_height(progress): body_pivot.position.y = -pow(sin(progress * PI), 0.4) * MAX_BUMP_HEIGHT func _on_tween_completed(object, key): _change_state(BUMP_COOLDOWN) func _on_Timer_timeout(): match state: IDLE: _change_state(ROAM) PREPARE_TO_CHARGE: _change_state(CHARGE) func _on_Stats_damage_taken(new_health): _change_state(STAGGER) func _on_Stats_health_depleted(): _change_state(DEAD) ================================================ FILE: monsters/porcupine/Porcupine.tscn ================================================ [gd_scene load_steps=16 format=2] [ext_resource path="res://monsters/porcupine/Porcupine.gd" type="Script" id=1] [ext_resource path="res://actors/health/Stats.tscn" type="PackedScene" id=2] [ext_resource path="res://actors/hit_box/HitBox.tscn" type="PackedScene" id=3] [ext_resource path="res://actors/DamageSource.tscn" type="PackedScene" id=4] [ext_resource path="res://monsters/porcupine/porcupine.png" type="Texture" id=5] [ext_resource path="res://monsters/exclamation-mark.png" type="Texture" id=6] [ext_resource path="res://vfx/particles/dust_puffs/DustPuffs.tscn" type="PackedScene" id=7] [ext_resource path="res://interface/gui/lifebar/InterfaceAnchor.tscn" type="PackedScene" id=8] [sub_resource type="Animation" id=1] resource_name = "SETUP" length = 0.01 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath("BodyPivot/Body:position") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 3.57628e-007, 17.6051 ) ] } tracks/1/type = "value" tracks/1/path = NodePath("BodyPivot/Body:rotation_degrees") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ 0.0 ] } tracks/2/type = "value" tracks/2/path = NodePath("BodyPivot/Body:scale") tracks/2/interp = 1 tracks/2/loop_wrap = true tracks/2/imported = false tracks/2/enabled = true tracks/2/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 1, 1 ) ] } tracks/3/type = "value" tracks/3/path = NodePath("BodyPivot/Body:modulate") tracks/3/interp = 1 tracks/3/loop_wrap = true tracks/3/imported = false tracks/3/enabled = true tracks/3/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ) ] } tracks/4/type = "value" tracks/4/path = NodePath("BodyPivot/Body:modulate") tracks/4/interp = 1 tracks/4/loop_wrap = true tracks/4/imported = false tracks/4/enabled = true tracks/4/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ) ] } [sub_resource type="Animation" id=2] resource_name = "die" length = 0.7 loop = false step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath("BodyPivot/Body:modulate") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.05, 0.1, 0.15, 0.2, 0.35, 0.5, 0.7 ), "transitions": PoolRealArray( 1, 1, 1, 1, 1, 1, 1, 1 ), "update": 0, "values": [ Color( 1, 0.296875, 0.296875, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 0.296875, 0.296875, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 0.296875, 0.296875, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ] } tracks/1/type = "value" tracks/1/path = NodePath("BodyPivot/Body:scale") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0, 0.35, 0.45, 0.65 ), "transitions": PoolRealArray( 1, 1, 2.94246, 1 ), "update": 0, "values": [ Vector2( 1, 1 ), Vector2( 1, 1 ), Vector2( 0.812022, 1.23284 ), Vector2( 2.7717, 0.0452506 ) ] } [sub_resource type="Animation" id=3] resource_name = "idle" length = 1.0 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath("BodyPivot/Body:position") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 3.57628e-007, 17.6051 ) ] } [sub_resource type="Animation" id=4] resource_name = "spot" length = 0.9 loop = false step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath("BodyPivot/Body:position") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ Vector2( 3.57628e-007, 17.6051 ) ] } tracks/1/type = "value" tracks/1/path = NodePath("BodyPivot/Body:rotation_degrees") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ 0.0 ] } tracks/2/type = "value" tracks/2/path = NodePath("BodyPivot/exclamation-mark:visible") tracks/2/interp = 1 tracks/2/loop_wrap = true tracks/2/imported = false tracks/2/enabled = true tracks/2/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 1, "values": [ true ] } tracks/3/type = "value" tracks/3/path = NodePath("BodyPivot/exclamation-mark:position") tracks/3/interp = 1 tracks/3/loop_wrap = true tracks/3/imported = false tracks/3/enabled = true tracks/3/keys = { "times": PoolRealArray( 0, 0.2, 0.25 ), "transitions": PoolRealArray( 0.382544, 1, 1 ), "update": 0, "values": [ Vector2( 54.0852, -65 ), Vector2( 74.1273, -90 ), Vector2( 74.8139, -90 ) ] } tracks/4/type = "value" tracks/4/path = NodePath("BodyPivot/exclamation-mark:rotation_degrees") tracks/4/interp = 1 tracks/4/loop_wrap = true tracks/4/imported = false tracks/4/enabled = true tracks/4/keys = { "times": PoolRealArray( 0, 0.2, 0.25 ), "transitions": PoolRealArray( 0.382544, 1, 1 ), "update": 0, "values": [ 3.97992, 12.3991, 14.5039 ] } tracks/5/type = "value" tracks/5/path = NodePath("BodyPivot/exclamation-mark:scale") tracks/5/interp = 1 tracks/5/loop_wrap = true tracks/5/imported = false tracks/5/enabled = true tracks/5/keys = { "times": PoolRealArray( 0, 0.2, 0.25 ), "transitions": PoolRealArray( 0.382544, 1, 1 ), "update": 0, "values": [ Vector2( 0.315916, 0.315916 ), Vector2( 1.05264, 1.05264 ), Vector2( 1, 1 ) ] } tracks/6/type = "value" tracks/6/path = NodePath("BodyPivot/exclamation-mark:self_modulate") tracks/6/interp = 1 tracks/6/loop_wrap = true tracks/6/imported = false tracks/6/enabled = true tracks/6/keys = { "times": PoolRealArray( 0, 0.5, 0.7 ), "transitions": PoolRealArray( 1, 1, 1 ), "update": 0, "values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ] } [sub_resource type="Animation" id=5] length = 0.5 loop = false step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath("BodyPivot/Body:modulate") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.05, 0.1, 0.15, 0.2, 0.4 ), "transitions": PoolRealArray( 1, 1, 1, 1, 1, 1 ), "update": 0, "values": [ Color( 1, 0.296875, 0.296875, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 0.296875, 0.296875, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 0.296875, 0.296875, 1 ), Color( 1, 1, 1, 1 ) ] } [sub_resource type="Animation" id=6] length = 0.3 loop = true step = 0.05 tracks/0/type = "value" tracks/0/path = NodePath("BodyPivot/Body:position") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.15 ), "transitions": PoolRealArray( 0.367583, 1.73627 ), "update": 0, "values": [ Vector2( 3.57628e-007, 17.6051 ), Vector2( 0, 0.113144 ) ] } [sub_resource type="CircleShape2D" id=7] custom_solver_bias = 0.0 radius = 35.906 [node name="Porcupine" type="KinematicBody2D" groups=[ "monster", ]] position = Vector2( -1.98642, 0.817726 ) input_pickable = false collision_layer = 2 collision_mask = 3 collision/safe_margin = 0.08 script = ExtResource( 1 ) _sections_unfolded = [ "Collision", "Z Index" ] [node name="AnimationPlayer" type="AnimationPlayer" parent="." index="0"] root_node = NodePath("..") autoplay = "" playback_process_mode = 1 playback_default_blend_time = 0.0 playback_speed = 1.0 anims/SETUP = SubResource( 1 ) anims/die = SubResource( 2 ) anims/idle = SubResource( 3 ) anims/spot = SubResource( 4 ) anims/stagger = SubResource( 5 ) anims/walk = SubResource( 6 ) blend_times = [ ] [node name="Tween" type="Tween" parent="." index="1"] repeat = false playback_process_mode = 1 playback_speed = 1.0 playback/active = false playback/repeat = false playback/speed = 1.0 [node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="." index="2"] position = Vector2( 0, 48.6492 ) build_mode = 0 polygon = PoolVector2Array( -36, -96, 36, -96, 36, -24, -36, -24 ) [node name="Stats" parent="." index="3" instance=ExtResource( 2 )] max_health = 5 [node name="HitBox" parent="." index="4" instance=ExtResource( 3 )] collision_layer = 8 collision_mask = 16 [node name="DamageSource" parent="." index="5" instance=ExtResource( 4 )] editor/display_folded = true [node name="CollisionShape2D" type="CollisionShape2D" parent="DamageSource" index="0"] position = Vector2( -1.19209e-007, -14 ) shape = SubResource( 7 ) [node name="BodyPivot" type="Position2D" parent="." index="6"] editor/display_folded = true z_index = 2 _sections_unfolded = [ "Transform", "Visibility", "Z Index" ] [node name="Body" type="Sprite" parent="BodyPivot" index="0"] position = Vector2( 3.57628e-007, 17.6051 ) texture = ExtResource( 5 ) offset = Vector2( 0.0850579, -32.8777 ) _sections_unfolded = [ "Visibility" ] [node name="exclamation-mark" type="Sprite" parent="BodyPivot" index="1"] self_modulate = Color( 1, 1, 1, 0 ) position = Vector2( 74.8139, -90 ) rotation = 0.253141 texture = ExtResource( 6 ) _sections_unfolded = [ "Visibility" ] [node name="Timer" type="Timer" parent="." index="7"] process_mode = 1 wait_time = 1.0 one_shot = false autostart = false [node name="DustPuffs" parent="." index="8" instance=ExtResource( 7 )] emitting = false [node name="InterfaceAnchor" parent="." index="9" instance=ExtResource( 8 )] position = Vector2( 0, -106.219 ) _sections_unfolded = [ "Transform" ] [connection signal="damage_taken" from="Stats" to="." method="_on_Stats_damage_taken"] [connection signal="health_depleted" from="Stats" to="." method="_on_Stats_health_depleted"] ================================================ FILE: monsters/porcupine/porcupine.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/porcupine.png-8034b65048f25f0e61302d6bff865dcc.stex" metadata={ "vram_texture": false } [deps] source_file="res://monsters/porcupine/porcupine.png" dest_files=[ "res://.import/porcupine.png-8034b65048f25f0e61302d6bff865dcc.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: project.godot ================================================ ; Engine configuration file. ; It's best edited using the editor UI and not directly, ; since the parameters that go here are not all obvious. ; ; Format: ; [section] ; section goes between [] ; param=value ; assign values to parameters config_version=4 _global_script_classes=[ { "base": "Control", "class": "Menu", "language": "GDScript", "path": "res://interface/menus/Menu.gd" } ] _global_script_class_icons={ "Menu": "" } [Colors] blue="#2196F3" pink="#C23A61" purple="#6200EA" yellow="#FFCA28" [application] config/name="Make Pro 2D Games with Godot" run/main_scene="res://Demo.tscn" config/icon="res://icon.png" run/debug=true [autoload] Steering="*res://utils/autoload/Steering.gd" ItemDatabase="*res://core/inventory/ItemDatabase.tscn" [display] window/size/width=1920 window/size/height=1080 window/size/fullscreen=true window/stretch/mode="2d" window/stretch/aspect="keep" [input] fire={ "deadzone": 0.5, "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":82,"unicode":0,"echo":false,"script":null) , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":2,"pressure":0.0,"pressed":false,"script":null) ] } run={ "deadzone": 0.5, "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777237,"unicode":0,"echo":false,"script":null) , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":7,"pressure":0.0,"pressed":false,"script":null) ] } jump={ "deadzone": 0.5, "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"unicode":0,"echo":false,"script":null) , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":0,"pressure":0.0,"pressed":false,"script":null) ] } simulate_damage={ "deadzone": 0.5, "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":88,"unicode":0,"echo":false,"script":null) ] } attack={ "deadzone": 0.5, "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":70,"unicode":0,"echo":false,"script":null) ] } pause={ "deadzone": 0.5, "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777217,"unicode":0,"echo":false,"script":null) , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":11,"pressure":0.0,"pressed":false,"script":null) ] } toggle_fullscreen={ "deadzone": 0.5, "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":true,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777254,"unicode":0,"echo":false,"script":null) ] } discrete_move_left={ "deadzone": 0.5, "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":65,"unicode":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777231,"unicode":0,"echo":false,"script":null) ] } discrete_move_right={ "deadzone": 0.5, "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":68,"unicode":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777233,"unicode":0,"echo":false,"script":null) ] } discrete_move_down={ "deadzone": 0.5, "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":83,"unicode":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777234,"unicode":0,"echo":false,"script":null) ] } discrete_move_up={ "deadzone": 0.5, "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":87,"unicode":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777232,"unicode":0,"echo":false,"script":null) ] } joy_move_left={ "deadzone": 0.5, "events": [ Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null) ] } joy_move_right={ "deadzone": 0.5, "events": [ Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null) ] } joy_move_up={ "deadzone": 0.5, "events": [ Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":-1.0,"script":null) ] } joy_move_down={ "deadzone": 0.5, "events": [ Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":1.0,"script":null) ] } [layer_names] 2d_physics/layer_1="motion" 2d_physics/layer_2="environment" 2d_physics/layer_3="hitbox_characters" 2d_physics/layer_4="hitbox_monsters" 2d_physics/layer_5="weapon" 2d_physics/layer_6="damager_area" 2d_physics/layer_7="collectibles" 2d_physics/layer_8="collector" [rendering] quality/2d/use_pixel_snap=true environment/default_environment="res://default_env.tres" ================================================ FILE: utils/autoload/Steering.gd ================================================ extends Node const DEFAULT_MASS = 2.0 const DEFAULT_SLOW_RADIUS = 200.0 const DEFAULT_MAX_SPEED = 300.0 func arrive_to(velocity, position, target_position, mass=DEFAULT_MASS, slow_radius=DEFAULT_SLOW_RADIUS, max_speed=DEFAULT_MAX_SPEED): """ Calculates and returns a new velocity with the arrive steering behavior arrived based on an existing velocity (Vector2), the object's current and target positions (Vector2) """ var distance_to_target = position.distance_to(target_position) var desired_velocity = (target_position - position).normalized() * max_speed if distance_to_target < slow_radius: desired_velocity *= (distance_to_target / slow_radius) * .75 + .25 var steering = (desired_velocity - velocity) / mass return velocity + steering func follow(velocity, position, target_position, max_speed, mass=DEFAULT_MASS): var desired_velocity = (target_position - position).normalized() * max_speed # var push = calculate_avoid_force(desired_velocity) # var steering = (desired_velocity - velocity + push) / mass var steering = (desired_velocity - velocity) / mass return velocity + steering ================================================ FILE: utils/debug/ControlsPanel.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://utils/debug/TopLevelUI.gd" type="Script" id=1] [ext_resource path="res://interface/fonts/source_code_pro_explanations.tres" type="DynamicFont" id=2] [node name="ControlsPanel" type="Panel" index="0"] anchor_left = 1.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 0.0 margin_left = -220.0 margin_bottom = 170.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 script = ExtResource( 1 ) [node name="Keys" type="Label" parent="." index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 margin_left = 10.0 margin_top = 10.0 margin_right = -10.0 margin_bottom = -10.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 custom_fonts/font = ExtResource( 2 ) text = "Shoot: Attack: Stagger: Jump: Sprint:" percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "BBCode", "custom_fonts" ] [node name="Keys2" type="Label" parent="." index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 margin_left = 10.0 margin_top = 10.0 margin_right = -10.0 margin_bottom = -10.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 custom_fonts/font = ExtResource( 2 ) text = "R F X Space Shift" align = 2 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "BBCode", "custom_fonts" ] ================================================ FILE: utils/debug/Explanations.tscn ================================================ [gd_scene load_steps=4 format=2] [ext_resource path="res://interface/fonts/source_code_pro_explanations_bold.tres" type="DynamicFont" id=1] [ext_resource path="res://interface/fonts/source_code_pro_explanations.tres" type="DynamicFont" id=2] [ext_resource path="res://utils/debug/TopLevelUI.gd" type="Script" id=3] [node name="Explanations" type="RichTextLabel"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 margin_left = 10.0 margin_top = -370.0 margin_right = -10.0 margin_bottom = -730.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 custom_fonts/bold_font = ExtResource( 1 ) custom_fonts/normal_font = ExtResource( 2 ) bbcode_enabled = true bbcode_text = "This example shows how to apply the State programming pattern in GDscript, including Hierarchical States, and a pushdown automaton. States are common in games. You can use the pattern to: 1. Separate each behavior and transitions between behaviors, thus make scripts shorter and easier to manage 2. Respect the Single Responsibility Principle. Each State object represents [b]one[/b] action 3. Improve your code's structure. Look at the scene tree and FileSystem tab: without looking at the code, you'll know what the Player can or cannot do. You can read more about States in the excellent [url=http://gameprogrammingpatterns.com/state.html]Game Programming Patterns ebook[/url]." visible_characters = -1 percent_visible = 1.0 meta_underlined = true tab_size = 4 text = "This example shows how to apply the State programming pattern in GDscript, including Hierarchical States, and a pushdown automaton. States are common in games. You can use the pattern to: 1. Separate each behavior and transitions between behaviors, thus make scripts shorter and easier to manage 2. Respect the Single Responsibility Principle. Each State object represents one action 3. Improve your code's structure. Look at the scene tree and FileSystem tab: without looking at the code, you'll know what the Player can or cannot do. You can read more about States in the excellent Game Programming Patterns ebook." scroll_active = true scroll_following = false selection_enabled = false override_selected_font_color = false script = ExtResource( 3 ) _sections_unfolded = [ "BBCode", "custom_fonts" ] __meta__ = { "_edit_lock_": true } ================================================ FILE: utils/debug/StatesStackDiplayer.tscn ================================================ [gd_scene load_steps=4 format=2] [ext_resource path="res://utils/debug/StatesStackDisplayer.gd" type="Script" id=1] [ext_resource path="res://interface/fonts/SourceCodePro-Bold.ttf" type="DynamicFontData" id=2] [sub_resource type="DynamicFont" id=1] size = 20 use_mipmaps = false use_filter = true font_data = ExtResource( 2 ) _sections_unfolded = [ "Font", "Settings" ] [node name="StatesStackDiplayer" type="Panel"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_right = 210.0 margin_bottom = 170.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 script = ExtResource( 1 ) __meta__ = { "_edit_group_": true } [node name="Title" type="Label" parent="." index="0"] anchor_left = 0.5 anchor_top = 0.0 anchor_right = 0.5 anchor_bottom = 0.0 margin_left = -105.0 margin_right = 105.0 margin_bottom = 40.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 custom_fonts/font = SubResource( 1 ) text = "Pushown" align = 1 valign = 1 uppercase = true percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "custom_fonts" ] [node name="States" type="Label" parent="." index="1"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 20.0 margin_top = 50.0 margin_right = 190.0 margin_bottom = 170.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 custom_fonts/font = SubResource( 1 ) text = "Jump Test" align = 1 percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "custom_fonts" ] [node name="Numbers" type="Label" parent="." index="2"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 20.0 margin_top = 50.0 margin_right = 190.0 margin_bottom = 170.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 2 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 4 custom_fonts/font = SubResource( 1 ) text = "1. 2." percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 _sections_unfolded = [ "custom_fonts" ] ================================================ FILE: utils/debug/StatesStackDisplayer.gd ================================================ tool extends Panel func _ready(): set_as_toplevel(true) func _on_Player_state_changed(states_stack): var states_names = '' var numbers = '' var index = 0 for state in states_stack: states_names += state.get_name() + '\n' numbers += str(index) + '\n' index += 1 $States.text = states_names $Numbers.text = numbers ================================================ FILE: utils/debug/TopLevelUI.gd ================================================ tool extends Control func _ready(): set_as_toplevel(true) ================================================ FILE: utils/state/Sequence.gd ================================================ """ Sequence is a State that delegates calls to one of its children at the time, in the tree order It automates the creation of new sequences of behaviors, a bit as in a behavior tree, although in this case each sub-state has to finish its job To tell the state machine when a sequence is over """ extends 'State.gd' var state_active = null func _ready(): for child in get_children(): child.connect('finished', self, '_on_state_active_finished') if child.owner != owner: child.set_owner(owner) func enter(): state_active = get_child(0) state_active.enter() func exit(): state_active = null func update(delta): state_active.update(delta) func _on_animation_finished(anim_name): state_active._on_animation_finished(anim_name) func _on_state_active_finished(): go_to_next_state_in_sequence() func go_to_next_state_in_sequence(): state_active.exit() var new_state_index = (state_active.get_index() + 1) % get_child_count() if new_state_index == 0: emit_signal('finished') return state_active = get_child(new_state_index) state_active.enter() ================================================ FILE: utils/state/Sequence.tscn ================================================ [gd_scene load_steps=2 format=2] [ext_resource path="res://utils/state/Sequence.gd" type="Script" id=1] [node name="Sequence" type="Node" index="0"] script = ExtResource( 1 ) ================================================ FILE: utils/state/State.gd ================================================ """ Base interface for all states: it doesn't do anything in itself but forces us to pass the right arguments to the methods below and makes sure every State object had all of these methods. """ extends Node signal finished(next_state_name) func enter(): return func exit(): return func handle_input(event): return func update(delta): return func _on_animation_finished(anim_name): return ================================================ FILE: utils/state/StateMachine.gd ================================================ """ Base interface for a generic state machine It handles initializing, setting the machine active or not delegating _physics_process, _input calls to the State nodes, and changing the current/active state. """ extends Node signal state_changed(current_state) var states_map = {} var states_stack = [] var current_state = null export(bool) var active = false setget set_active func _ready(): states_stack.push_front(get_child(0)) current_state = states_stack[0] if active: start() func start(): current_state.enter() set_active(true) func set_active(value): active = value set_physics_process(value) set_process_input(value) if not active: states_stack = [] current_state = null func _unhandled_input(event): current_state.handle_input(event) func _physics_process(delta): current_state.update(delta) func _on_animation_finished(anim_name): if not active: return current_state._on_animation_finished(anim_name) func _change_state(state_name): if not active: return current_state.exit() if state_name == "previous": states_stack.pop_front() else: states_stack[0] = states_map[state_name] current_state = states_stack[0] emit_signal("state_changed", current_state) current_state.enter() ================================================ FILE: utils/state/StateMachine.tscn ================================================ [gd_scene load_steps=2 format=2] [ext_resource path="res://utils/state/StateMachine.gd" type="Script" id=1] [node name="StateMachine" type="Node" index="0"] script = ExtResource( 1 ) START_STATE = null ================================================ FILE: vfx/Fog.gd ================================================ extends ColorRect func _on_LevelLoader_loaded(level): visible = level.fog ================================================ FILE: vfx/TransitionColor.gd ================================================ extends ColorRect onready var anim_player = $AnimationPlayer func fade_to_color(): show() anim_player.play("to_color") yield(anim_player, "animation_finished") hide() func fade_from_color(): show() anim_player.play("to_transparent") yield(anim_player, "animation_finished") hide() ================================================ FILE: vfx/TransitionColor.tscn ================================================ [gd_scene load_steps=6 format=2] [ext_resource path="res://vfx/transition.material" type="Material" id=1] [ext_resource path="res://vfx/TransitionColor.gd" type="Script" id=2] [sub_resource type="Animation" id=1] resource_name = "_SETUP" length = 0.01 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath(".:material:shader_param/cutoff") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0 ), "transitions": PoolRealArray( 1 ), "update": 0, "values": [ 0.0 ] } [sub_resource type="Animation" id=3] resource_name = "to_color" length = 0.7 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath(".:material:shader_param/cutoff") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.7 ), "transitions": PoolRealArray( 0.27058, 0.307901 ), "update": 0, "values": [ 1.0, 0.0 ] } tracks/1/type = "value" tracks/1/path = NodePath(".:material:shader_param/smooth_size") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0, 0.7 ), "transitions": PoolRealArray( 0.27058, 1 ), "update": 0, "values": [ 0.941, 0.161 ] } [sub_resource type="Animation" id=2] resource_name = "to_transparent" length = 0.7 loop = false step = 0.1 tracks/0/type = "value" tracks/0/path = NodePath(".:material:shader_param/cutoff") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/imported = false tracks/0/enabled = true tracks/0/keys = { "times": PoolRealArray( 0, 0.7 ), "transitions": PoolRealArray( 0.307901, 1 ), "update": 0, "values": [ 0.0, 1.0 ] } tracks/1/type = "value" tracks/1/path = NodePath(".:material:shader_param/smooth_size") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = { "times": PoolRealArray( 0, 0.7 ), "transitions": PoolRealArray( 1, 1 ), "update": 0, "values": [ 0.161, 0.941 ] } [node name="TransitionColor" type="ColorRect"] material = ExtResource( 1 ) anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 anchor_bottom = 1.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 color = Color( 1, 1, 1, 1 ) script = ExtResource( 2 ) _sections_unfolded = [ "Material" ] [node name="AnimationPlayer" type="AnimationPlayer" parent="." index="0"] root_node = NodePath("..") autoplay = "" playback_process_mode = 1 playback_default_blend_time = 0.0 playback_speed = 1.0 anims/_SETUP = SubResource( 1 ) anims/to_color = SubResource( 3 ) anims/to_transparent = SubResource( 2 ) blend_times = [ ] _sections_unfolded = [ "Playback Options" ] ================================================ FILE: vfx/fog.shader ================================================ shader_type canvas_item; uniform vec4 color : hint_color = vec4(0.35, 0.48, 0.95, 1.0); uniform float noise_scale = 20.0; uniform float alpha_power = 2.0; uniform int OCTAVES = 1; float rand(vec2 coord){ return fract(sin(dot(coord, vec2(56, 78)) * 1000.0) * 1000.0); } float noise(vec2 coord){ vec2 i = floor(coord); vec2 f = fract(coord); // 4 corners of a rectangle surrounding our point float a = rand(i); float b = rand(i + vec2(1.0, 0.0)); float c = rand(i + vec2(0.0, 1.0)); float d = rand(i + vec2(1.0, 1.0)); vec2 cubic = f * f * (3.0 - 2.0 * f); return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y; } float fbm(vec2 coord){ float value = 0.0; float scale = 0.5; for(int i = 0; i < OCTAVES; i++){ value += noise(coord) * scale; coord *= 2.0; scale *= 0.5; } return value; } void fragment() { vec2 coord = UV * noise_scale; vec2 motion = vec2( fbm(coord + vec2(TIME * -0.5, TIME * 0.5)) ); float final = fbm(coord + motion); COLOR = vec4(color.rgb, pow(final, alpha_power) * color.a); } ================================================ FILE: vfx/masks/curtain.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/curtain.png-3af2c44df15fd54790d255ef204f96fe.stex" metadata={ "vram_texture": false } [deps] source_file="res://vfx/masks/curtain.png" dest_files=[ "res://.import/curtain.png-3af2c44df15fd54790d255ef204f96fe.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: vfx/particles/SelfDestructingParticles.gd ================================================ extends Particles2D func start(): emitting = true yield(get_tree().create_timer(lifetime * speed_scale * 1.2), "timeout") queue_free() ================================================ FILE: vfx/particles/assets/gradient_ramps/fire_to_black.tres ================================================ [gd_resource type="Gradient" format=2] [resource] offsets = PoolRealArray( 0, 0.0358056, 0.480818, 0.915601, 1 ) colors = PoolColorArray( 1, 0.773438, 0, 0, 1, 0.726563, 0, 1, 1, 0.304688, 0, 1, 0.160156, 0.115112, 0.115112, 1, 0, 0, 0, 0 ) ================================================ FILE: vfx/particles/assets/gradient_ramps/sparkles.tres ================================================ [gd_resource type="Gradient" format=2] [resource] offsets = PoolRealArray( 0, 0.0613811, 0.84399, 1 ) colors = PoolColorArray( 1, 0.846985, 0.148438, 0, 1, 0.820313, 0, 1, 1, 0.398438, 0, 1, 0.964844, 0, 0, 0 ) ================================================ FILE: vfx/particles/assets/gradient_ramps/sparkles_small.tres ================================================ [gd_resource type="Gradient" format=2] [resource] offsets = PoolRealArray( 0, 0.0971867, 0.751918, 1 ) colors = PoolColorArray( 0.980469, 0.878616, 0.413635, 0, 1, 0.820313, 0, 1, 1, 0.257813, 0, 1, 0, 0, 0, 0 ) ================================================ FILE: vfx/particles/dust_charge/DustCharge.tscn ================================================ [gd_scene load_steps=9 format=2] [ext_resource path="res://dust_charge/puffs.png" type="Texture" id=1] [sub_resource type="Gradient" id=1] offsets = PoolRealArray( 0, 0.0710059, 0.887574, 1 ) colors = PoolColorArray( 0.834469, 0.650242, 0.192065, 0, 0.84375, 0.699554, 0.316406, 1, 0.824219, 0.595778, 0.0547333, 1, 0.826506, 0.607932, 0.0853797, 0 ) [sub_resource type="GradientTexture" id=2] flags = 4 gradient = SubResource( 1 ) width = 2048 [sub_resource type="Curve" id=3] min_value = -0.2 max_value = 0.2 bake_resolution = 100 _data = [ Vector2( 0, 0.0277257 ), 0.0, 0.0, 0, 0, Vector2( 1, -0.0310864 ), 0.0, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=4] flags = 4 width = 2048 curve = SubResource( 3 ) [sub_resource type="Curve" id=5] min_value = 0.0 max_value = 1.0 bake_resolution = 100 _data = [ Vector2( 0, 0.166992 ), 0.0, 0.0, 0, 0, Vector2( 0.378064, 1 ), 0.0, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=6] flags = 4 width = 2048 curve = SubResource( 5 ) [sub_resource type="ParticlesMaterial" id=7] render_priority = 0 trail_divisor = 1 emission_shape = 0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 45.0 flatness = 0.0 gravity = Vector3( 0, 0, 0 ) initial_velocity = 100.0 initial_velocity_random = 0.0 angular_velocity = 0.0 angular_velocity_random = 0.0 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = 0.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 0.0 tangential_accel_random = 0.0 damping = 0.0 damping_random = 0.0 angle = 360.0 angle_random = 1.0 scale = 0.8 scale_random = 0.2 scale_curve = SubResource( 6 ) color_ramp = SubResource( 2 ) hue_variation = 0.0 hue_variation_random = 1.0 hue_variation_curve = SubResource( 4 ) anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 1.0 anim_offset_random = 1.0 anim_loop = false _sections_unfolded = [ "Color", "Hue Variation" ] [node name="DustCharge" type="Particles2D" index="0"] position = Vector2( 1, 3 ) rotation = -1.5708 emitting = true amount = 16 lifetime = 1.0 one_shot = false preprocess = 0.0 speed_scale = 2.0 explosiveness = 0.2 randomness = 0.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -400, -400, 800, 800 ) local_coords = false draw_order = 1 process_material = SubResource( 7 ) texture = ExtResource( 1 ) normal_map = null h_frames = 2 v_frames = 1 _sections_unfolded = [ "Drawing", "Process Material", "Textures", "Time", "Transform" ] ================================================ FILE: vfx/particles/dust_charge/DustChargeLarge.tscn ================================================ [gd_scene load_steps=9 format=2] [ext_resource path="res://dust_charge/DustCharge.tscn" type="PackedScene" id=1] [sub_resource type="Gradient" id=1] offsets = PoolRealArray( 0, 0.0710059, 0.887574, 1 ) colors = PoolColorArray( 0.834469, 0.650242, 0.192065, 0, 0.84375, 0.699554, 0.316406, 1, 0.824219, 0.595778, 0.0547333, 1, 0.826506, 0.607932, 0.0853797, 0 ) [sub_resource type="GradientTexture" id=2] flags = 4 gradient = SubResource( 1 ) width = 2048 [sub_resource type="Curve" id=3] min_value = -0.2 max_value = 0.2 bake_resolution = 100 _data = [ Vector2( 0, 0.0277257 ), 0.0, 0.0, 0, 0, Vector2( 1, -0.0310864 ), 0.0, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=4] flags = 4 width = 2048 curve = SubResource( 3 ) [sub_resource type="Curve" id=5] min_value = 0.0 max_value = 1.0 bake_resolution = 100 _data = [ Vector2( 0, 0.166992 ), 0.0, 0.0, 0, 0, Vector2( 0.378064, 1 ), 0.0, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=6] flags = 4 width = 2048 curve = SubResource( 5 ) [sub_resource type="ParticlesMaterial" id=7] render_priority = 0 trail_divisor = 1 emission_shape = 0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 60.0 flatness = 0.0 gravity = Vector3( 0, 0, 0 ) initial_velocity = 160.0 initial_velocity_random = 0.7 angular_velocity = 0.0 angular_velocity_random = 0.0 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = 0.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 0.0 tangential_accel_random = 0.0 damping = 0.0 damping_random = 0.0 angle = 360.0 angle_random = 1.0 scale = 1.4 scale_random = 0.3 scale_curve = SubResource( 6 ) color_ramp = SubResource( 2 ) hue_variation = 0.0 hue_variation_random = 1.0 hue_variation_curve = SubResource( 4 ) anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 1.0 anim_offset_random = 1.0 anim_loop = false _sections_unfolded = [ "Color", "Hue Variation", "Initial Velocity", "Scale", "Spread" ] [node name="DustChargeLarge" index="0" instance=ExtResource( 1 )] amount = 40 lifetime = 1.4 explosiveness = 0.1 randomness = 0.6 process_material = SubResource( 7 ) ================================================ FILE: vfx/particles/dust_charge/puffs.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/puffs.png-5a8f7bae06bf0d22084af1f35563a1df.stex" metadata={ "vram_texture": false } [deps] source_file="res://vfx/particles/dust_charge/puffs.png" dest_files=[ "res://.import/puffs.png-5a8f7bae06bf0d22084af1f35563a1df.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: vfx/particles/dust_puffs/DustPuffs.tscn ================================================ [gd_scene load_steps=9 format=2] [ext_resource path="res://vfx/particles/dust_charge/puffs.png" type="Texture" id=1] [sub_resource type="Gradient" id=1] offsets = PoolRealArray( 0, 0.0710059, 0.887574, 1 ) colors = PoolColorArray( 0.834469, 0.650242, 0.192065, 0, 0.84375, 0.699554, 0.316406, 1, 0.824219, 0.595778, 0.0547333, 1, 0.826506, 0.607932, 0.0853797, 0 ) [sub_resource type="GradientTexture" id=2] flags = 4 gradient = SubResource( 1 ) width = 2048 [sub_resource type="Curve" id=3] min_value = -0.2 max_value = 0.2 bake_resolution = 100 _data = [ Vector2( 0, 0.0277257 ), 0.0, 0.0, 0, 0, Vector2( 1, -0.0310864 ), 0.0, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=4] flags = 4 width = 2048 curve = SubResource( 3 ) [sub_resource type="Curve" id=5] min_value = 0.0 max_value = 1.0 bake_resolution = 100 _data = [ Vector2( 0, 0.166992 ), 0.0, 0.0, 0, 0, Vector2( 0.378064, 1 ), 0.0, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=6] flags = 4 width = 2048 curve = SubResource( 5 ) [sub_resource type="ParticlesMaterial" id=7] render_priority = 0 trail_divisor = 1 emission_shape = 0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 45.0 flatness = 0.0 gravity = Vector3( 0, 0, 0 ) initial_velocity = 100.0 initial_velocity_random = 0.0 angular_velocity = 0.0 angular_velocity_random = 0.0 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = 0.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 0.0 tangential_accel_random = 0.0 damping = 0.0 damping_random = 0.0 angle = 360.0 angle_random = 1.0 scale = 0.8 scale_random = 0.2 scale_curve = SubResource( 6 ) color_ramp = SubResource( 2 ) hue_variation = 0.0 hue_variation_random = 1.0 hue_variation_curve = SubResource( 4 ) anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 1.0 anim_offset_random = 1.0 anim_loop = false _sections_unfolded = [ "Color", "Hue Variation" ] [node name="DustPuffs" type="Particles2D" index="0"] position = Vector2( 1, 3 ) rotation = -1.5708 emitting = true amount = 16 lifetime = 1.0 one_shot = false preprocess = 0.0 speed_scale = 2.0 explosiveness = 0.2 randomness = 0.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -400, -400, 800, 800 ) local_coords = false draw_order = 1 process_material = SubResource( 7 ) texture = ExtResource( 1 ) normal_map = null h_frames = 2 v_frames = 1 _sections_unfolded = [ "Drawing", "Process Material", "Textures", "Time", "Transform" ] ================================================ FILE: vfx/particles/dust_puffs/DustPuffsLarge.tscn ================================================ [gd_scene load_steps=9 format=2] [ext_resource path="res://vfx/particles/dust_puffs/DustPuffs.tscn" type="PackedScene" id=1] [sub_resource type="Gradient" id=1] offsets = PoolRealArray( 0, 0.0710059, 0.887574, 1 ) colors = PoolColorArray( 0.834469, 0.650242, 0.192065, 0, 0.84375, 0.699554, 0.316406, 1, 0.824219, 0.595778, 0.0547333, 1, 0.826506, 0.607932, 0.0853797, 0 ) [sub_resource type="GradientTexture" id=2] flags = 4 gradient = SubResource( 1 ) width = 2048 [sub_resource type="Curve" id=3] min_value = -0.2 max_value = 0.2 bake_resolution = 100 _data = [ Vector2( 0, 0.0277257 ), 0.0, 0.0, 0, 0, Vector2( 1, -0.0310864 ), 0.0, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=4] flags = 4 width = 2048 curve = SubResource( 3 ) [sub_resource type="Curve" id=5] min_value = 0.0 max_value = 1.0 bake_resolution = 100 _data = [ Vector2( 0, 0.166992 ), 0.0, 0.0, 0, 0, Vector2( 0.378064, 1 ), 0.0, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=6] flags = 4 width = 2048 curve = SubResource( 5 ) [sub_resource type="ParticlesMaterial" id=7] render_priority = 0 trail_divisor = 1 emission_shape = 0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 60.0 flatness = 0.0 gravity = Vector3( 0, 0, 0 ) initial_velocity = 160.0 initial_velocity_random = 0.7 angular_velocity = 0.0 angular_velocity_random = 0.0 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = 0.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 0.0 tangential_accel_random = 0.0 damping = 0.0 damping_random = 0.0 angle = 360.0 angle_random = 1.0 scale = 1.4 scale_random = 0.3 scale_curve = SubResource( 6 ) color_ramp = SubResource( 2 ) hue_variation = 0.0 hue_variation_random = 1.0 hue_variation_curve = SubResource( 4 ) anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 1.0 anim_offset_random = 1.0 anim_loop = false _sections_unfolded = [ "Color", "Hue Variation", "Initial Velocity", "Scale", "Spread" ] [node name="DustPuffsLarge" index="0" instance=ExtResource( 1 )] amount = 40 lifetime = 1.4 explosiveness = 0.1 randomness = 0.6 process_material = SubResource( 7 ) ================================================ FILE: vfx/particles/dust_puffs/DustRun.tscn ================================================ [gd_scene load_steps=8 format=2] [ext_resource path="res://vfx/particles/dust_puffs/puff_stylized.png" type="Texture" id=1] [ext_resource path="res://vfx/particles/SelfDestructingParticles.gd" type="Script" id=2] [sub_resource type="Gradient" id=1] offsets = PoolRealArray( 0, 0.0602007, 0.769231, 1 ) colors = PoolColorArray( 0.308594, 0.233027, 0.144653, 0, 0.574219, 0.435676, 0.273651, 1, 0.598236, 0.472648, 0.325774, 1, 0.596078, 0.470588, 0.32549, 0 ) [sub_resource type="GradientTexture" id=2] flags = 4 gradient = SubResource( 1 ) width = 256 [sub_resource type="Curve" id=3] min_value = 0.0 max_value = 1.0 bake_resolution = 100 _data = [ Vector2( 0, 0.349609 ), 0.0, 1.47649, 0, 0, Vector2( 0.908748, 1 ), 0.0, 0.0, 0, 0, Vector2( 1, 0.628906 ), -4.5017, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=4] flags = 4 width = 2048 curve = SubResource( 3 ) [sub_resource type="ParticlesMaterial" id=5] render_priority = 0 trail_divisor = 1 emission_shape = 1 emission_sphere_radius = 10.0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 120.0 flatness = 1.0 gravity = Vector3( 0, 0, 0 ) initial_velocity = 30.0 initial_velocity_random = 0.4 angular_velocity = 120.0 angular_velocity_random = 0.7 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = -10.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 0.0 tangential_accel_random = 0.0 damping = 0.0 damping_random = 0.0 angle = 360.0 angle_random = 1.0 scale = 0.6 scale_random = 0.1 scale_curve = SubResource( 4 ) color_ramp = SubResource( 2 ) hue_variation = 0.0 hue_variation_random = 0.0 anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 1.0 anim_offset_random = 1.0 anim_loop = false _sections_unfolded = [ "Color", "Scale" ] [node name="DustRun" type="Particles2D" index="0"] show_behind_parent = true position = Vector2( 1, 0 ) rotation = -1.5708 emitting = false amount = 12 lifetime = 1.0 one_shot = true preprocess = 0.0 speed_scale = 2.0 explosiveness = 0.95 randomness = 1.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -400, -400, 800, 800 ) local_coords = false draw_order = 0 process_material = SubResource( 5 ) texture = ExtResource( 1 ) normal_map = null h_frames = 1 v_frames = 1 script = ExtResource( 2 ) _sections_unfolded = [ "Drawing", "Material", "Process Material", "Textures", "Time", "Transform", "Visibility", "Z Index" ] ================================================ FILE: vfx/particles/dust_puffs/DustWalk.tscn ================================================ [gd_scene load_steps=4 format=2] [ext_resource path="res://vfx/particles/dust_puffs/dust_puffs_particle.tres" type="Material" id=1] [ext_resource path="res://vfx/particles/dust_puffs/puff_stylized.png" type="Texture" id=2] [ext_resource path="res://vfx/particles/SelfDestructingParticles.gd" type="Script" id=3] [node name="DustWalk" type="Particles2D" index="0"] show_behind_parent = true position = Vector2( 1, 0 ) rotation = -1.5708 emitting = false amount = 8 lifetime = 1.0 one_shot = true preprocess = 0.0 speed_scale = 1.4 explosiveness = 0.95 randomness = 0.3 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -400, -400, 800, 800 ) local_coords = false draw_order = 0 process_material = ExtResource( 1 ) texture = ExtResource( 2 ) normal_map = null h_frames = 1 v_frames = 1 script = ExtResource( 3 ) _sections_unfolded = [ "Drawing", "Material", "Time", "Transform", "Visibility" ] ================================================ FILE: vfx/particles/dust_puffs/dust_puffs_particle.tres ================================================ [gd_resource type="ParticlesMaterial" load_steps=5 format=2] [sub_resource type="Gradient" id=1] offsets = PoolRealArray( 0, 0.112532, 0.869565, 1 ) colors = PoolColorArray( 0.308594, 0.233027, 0.144653, 0, 0.574219, 0.435676, 0.273651, 1, 0.598236, 0.472648, 0.325774, 1, 0.596078, 0.470588, 0.32549, 0 ) [sub_resource type="GradientTexture" id=2] gradient = SubResource( 1 ) width = 256 [sub_resource type="Curve" id=3] _data = [ Vector2( 0, 0.349609 ), 0.0, 1.47649, 0, 0, Vector2( 0.908748, 1 ), 0.0, 0.0, 0, 0, Vector2( 1, 0.628906 ), -4.5017, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=4] curve = SubResource( 3 ) [resource] emission_shape = 1 emission_sphere_radius = 5.0 flag_disable_z = true spread = 120.0 flatness = 1.0 gravity = Vector3( 0, 0, 0 ) initial_velocity = 30.0 initial_velocity_random = 0.4 angular_velocity = 120.0 angular_velocity_random = 0.7 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = -10.0 angle = 360.0 angle_random = 1.0 scale = 0.5 scale_curve = SubResource( 4 ) color_ramp = SubResource( 2 ) anim_offset = 1.0 anim_offset_random = 1.0 ================================================ FILE: vfx/particles/dust_puffs/puff_stylized.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/puff_stylized.png-76fe5696970602731dcc9616af628ed6.stex" metadata={ "vram_texture": false } [deps] source_file="res://vfx/particles/dust_puffs/puff_stylized.png" dest_files=[ "res://.import/puff_stylized.png-76fe5696970602731dcc9616af628ed6.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: vfx/particles/dust_puffs/puffs.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/puffs.png-647a0897f9b56787d9f19dffab574e9f.stex" metadata={ "vram_texture": false } [deps] source_file="res://vfx/particles/dust_puffs/puffs.png" dest_files=[ "res://.import/puffs.png-647a0897f9b56787d9f19dffab574e9f.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: vfx/particles/explosions/Explosion.gd ================================================ extends Particles2D func _ready(): get_tree().create_timer(lifetime).connect('timeout', self, 'stop_emitting') get_tree().create_timer(lifetime * 2.0).connect('timeout', self, 'queue_free') func stop_emitting(): emitting = false ================================================ FILE: vfx/particles/explosions/Explosion.tscn ================================================ [gd_scene load_steps=10 format=2] [ext_resource path="res://vfx/particles/dust_charge/puffs.png" type="Texture" id=1] [ext_resource path="res://vfx/particles/explosions/Explosion.gd" type="Script" id=2] [sub_resource type="Gradient" id=1] offsets = PoolRealArray( 0.226293, 0.545259, 0.898707, 1 ) colors = PoolColorArray( 0.953125, 0.907313, 0.785583, 1, 0.953125, 0.850099, 0.0111694, 1, 0.921875, 0.450078, 0.219666, 1, 0.826506, 0.607932, 0.0853797, 0 ) [sub_resource type="GradientTexture" id=2] flags = 4 gradient = SubResource( 1 ) width = 2048 [sub_resource type="Curve" id=3] min_value = -0.2 max_value = 0.2 bake_resolution = 100 _data = [ Vector2( 0, 0.0277257 ), 0.0, 0.0, 0, 0, Vector2( 1, -0.0310864 ), 0.0, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=4] flags = 4 width = 2048 curve = SubResource( 3 ) [sub_resource type="Curve" id=5] min_value = 0.0 max_value = 1.0 bake_resolution = 100 _data = [ Vector2( 0, 0.166992 ), 0.0, 1.80027, 0, 0, Vector2( 1, 1 ), 0.121391, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=6] flags = 4 width = 2048 curve = SubResource( 5 ) [sub_resource type="ParticlesMaterial" id=7] render_priority = 0 trail_divisor = 1 emission_shape = 1 emission_sphere_radius = 20.0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 180.0 flatness = 0.0 gravity = Vector3( 0, 0, 0 ) initial_velocity = 160.0 initial_velocity_random = 0.6 angular_velocity = 0.0 angular_velocity_random = 0.0 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = 0.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 0.0 tangential_accel_random = 0.0 damping = 0.0 damping_random = 0.0 angle = 360.0 angle_random = 1.0 scale = 1.0 scale_random = 0.6 scale_curve = SubResource( 6 ) color_ramp = SubResource( 2 ) hue_variation = 0.0 hue_variation_random = 1.0 hue_variation_curve = SubResource( 4 ) anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 1.0 anim_offset_random = 1.0 anim_loop = false _sections_unfolded = [ "Color", "Emission Shape", "Gravity", "Initial Velocity", "Scale", "Spread" ] [node name="Explosion" type="Particles2D" index="0"] position = Vector2( 13.6701, 0 ) rotation = -1.5708 z_index = 20 emitting = true amount = 80 lifetime = 0.3 one_shot = false preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.4 randomness = 1.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -400, -400, 800, 800 ) local_coords = false draw_order = 1 process_material = SubResource( 7 ) texture = ExtResource( 1 ) normal_map = null h_frames = 2 v_frames = 1 script = ExtResource( 2 ) _sections_unfolded = [ "Drawing", "Process Material", "Time", "Transform", "Z Index" ] ================================================ FILE: vfx/particles/explosions/ExplosionFlash.tscn ================================================ [gd_scene load_steps=10 format=2] [ext_resource path="res://vfx/particles/explosions/circle.png" type="Texture" id=1] [ext_resource path="res://explosions/explosion.gd" type="Script" id=2] [sub_resource type="Gradient" id=1] offsets = PoolRealArray( 0, 0.0946746, 0.414201, 0.650888, 0.87574, 1 ) colors = PoolColorArray( 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 ) [sub_resource type="GradientTexture" id=2] flags = 4 gradient = SubResource( 1 ) width = 2048 [sub_resource type="Curve" id=3] min_value = -0.2 max_value = 0.2 bake_resolution = 100 _data = [ Vector2( 0, 0.0277257 ), 0.0, 0.0, 0, 0, Vector2( 1, -0.0310864 ), 0.0, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=4] flags = 4 width = 2048 curve = SubResource( 3 ) [sub_resource type="Curve" id=5] min_value = 0.0 max_value = 1.0 bake_resolution = 100 _data = [ Vector2( 0, 0.790039 ), 0.0, -0.433343, 0, 0, Vector2( 0.413238, 0.811523 ), 0.775457, 3.68342, 0, 0, Vector2( 1, 1 ), 0.121391, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=6] flags = 4 width = 2048 curve = SubResource( 5 ) [sub_resource type="ParticlesMaterial" id=7] render_priority = 0 trail_divisor = 1 emission_shape = 1 emission_sphere_radius = 44.04 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 180.0 flatness = 0.0 gravity = Vector3( 0, 0, 0 ) initial_velocity = 200.0 initial_velocity_random = 0.0 angular_velocity = 0.0 angular_velocity_random = 0.0 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = 0.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 0.0 tangential_accel_random = 0.0 damping = 1.0 damping_random = 0.0 angle = 360.0 angle_random = 1.0 scale = 1.0 scale_random = 0.4 scale_curve = SubResource( 6 ) color_ramp = SubResource( 2 ) hue_variation = 0.0 hue_variation_random = 1.0 hue_variation_curve = SubResource( 4 ) anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 1.0 anim_offset_random = 1.0 anim_loop = false _sections_unfolded = [ "Color", "Damping", "Emission Shape", "Flags", "Initial Velocity", "Scale", "Spread" ] [node name="ExplosionFlash" type="Particles2D" index="0"] z_index = 20 emitting = false amount = 10 lifetime = 0.6 one_shot = true preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.3 randomness = 1.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -400, -400, 800, 800 ) local_coords = false draw_order = 1 process_material = SubResource( 7 ) texture = ExtResource( 1 ) normal_map = null h_frames = 1 v_frames = 1 script = ExtResource( 2 ) _sections_unfolded = [ "Drawing", "Process Material", "Textures", "Time" ] ================================================ FILE: vfx/particles/explosions/circle.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/circle.png-206ef6dbbb41f3edbef77fad323ed599.stex" metadata={ "vram_texture": false } [deps] source_file="res://vfx/particles/explosions/circle.png" dest_files=[ "res://.import/circle.png-206ef6dbbb41f3edbef77fad323ed599.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: vfx/particles/fiery_cloud/FieryCloud.tscn ================================================ [gd_scene load_steps=17 format=2] [ext_resource path="res://assets/gradient_ramps/fire_to_black.tres" type="Gradient" id=1] [ext_resource path="res://dust_charge/puffs.png" type="Texture" id=2] [ext_resource path="res://fiery_cloud/fiery_cloud.gd" type="Script" id=3] [ext_resource path="res://assets/gradient_ramps/sparkles_small.tres" type="Gradient" id=4] [ext_resource path="res://explosions/circle.png" type="Texture" id=5] [ext_resource path="res://assets/gradient_ramps/sparkles.tres" type="Gradient" id=6] [sub_resource type="GradientTexture" id=1] flags = 4 gradient = ExtResource( 1 ) width = 2048 [sub_resource type="Curve" id=2] min_value = 0.0 max_value = 1.6 bake_resolution = 100 _data = [ Vector2( 0.00254472, 0.414062 ), 0.0, 0.0, 0, 0, Vector2( 0.195613, 0.650391 ), 1.7438, 1.7438, 0, 0, Vector2( 1, 1.59062 ), 4.80181, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=3] flags = 4 width = 2048 curve = SubResource( 2 ) [sub_resource type="ParticlesMaterial" id=4] render_priority = 0 trail_divisor = 1 emission_shape = 0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 120.0 flatness = 0.0 gravity = Vector3( 0, 0, 0 ) initial_velocity = 120.0 initial_velocity_random = 0.0 angular_velocity = 0.0 angular_velocity_random = 0.0 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = 0.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 0.0 tangential_accel_random = 0.0 damping = 0.0 damping_random = 0.0 angle = 360.0 angle_random = 1.0 scale = 0.4 scale_random = 1.0 scale_curve = SubResource( 3 ) color_ramp = SubResource( 1 ) hue_variation = 0.0 hue_variation_random = 0.0 anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 0.0 anim_offset_random = 0.0 anim_loop = false _sections_unfolded = [ "Angle", "Color", "Scale" ] [sub_resource type="GradientTexture" id=5] flags = 4 gradient = ExtResource( 4 ) width = 2048 [sub_resource type="Curve" id=6] min_value = 0.0 max_value = 1.0 bake_resolution = 100 _data = [ Vector2( 0, 0.399763 ), 0.0, 0.0, 0, 0, Vector2( 1, 1 ), 0.0, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=7] flags = 4 width = 2048 curve = SubResource( 6 ) [sub_resource type="ParticlesMaterial" id=8] render_priority = 0 trail_divisor = 1 emission_shape = 1 emission_sphere_radius = 24.0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 120.0 flatness = 0.0 gravity = Vector3( 0, 200, 0 ) initial_velocity = 200.0 initial_velocity_random = 0.6 angular_velocity = 0.0 angular_velocity_random = 0.0 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = 0.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 100.0 tangential_accel_random = 0.0 damping = 0.0 damping_random = 0.0 angle = 0.0 angle_random = 0.0 scale = 0.04 scale_random = 0.0 scale_curve = SubResource( 7 ) color_ramp = SubResource( 5 ) hue_variation = 0.0 hue_variation_random = 0.0 anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 0.0 anim_offset_random = 0.0 anim_loop = false _sections_unfolded = [ "Color", "Emission Shape", "Gravity", "Initial Velocity", "Scale", "Spread", "Tangential Accel" ] [sub_resource type="GradientTexture" id=9] flags = 4 gradient = ExtResource( 6 ) width = 2048 [sub_resource type="ParticlesMaterial" id=10] render_priority = 0 trail_divisor = 1 emission_shape = 1 emission_sphere_radius = 24.0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 120.0 flatness = 0.0 gravity = Vector3( 0, 200, 0 ) initial_velocity = 200.0 initial_velocity_random = 0.6 angular_velocity = 0.0 angular_velocity_random = 0.0 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = 0.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 100.0 tangential_accel_random = 0.0 damping = 0.0 damping_random = 0.0 angle = 0.0 angle_random = 0.0 scale = 0.04 scale_random = 0.0 scale_curve = SubResource( 7 ) color_ramp = SubResource( 9 ) hue_variation = 0.0 hue_variation_random = 0.0 anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 0.0 anim_offset_random = 0.0 anim_loop = false _sections_unfolded = [ "Color" ] [node name="FieryCloud" type="Particles2D" index="0"] emitting = false amount = 40 lifetime = 0.6 one_shot = false preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.0 randomness = 0.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -400, -400, 800, 800 ) local_coords = false draw_order = 1 process_material = SubResource( 4 ) texture = ExtResource( 2 ) normal_map = null h_frames = 2 v_frames = 1 script = ExtResource( 3 ) _sections_unfolded = [ "Drawing", "Process Material", "Time" ] TIME_SCALE = 2.0 RADIUS = 160.0 OFFSET = Vector2( 0, 0 ) active = false [node name="SmallSparkles" type="Particles2D" parent="." index="0"] visible = false rotation = -1.61079 emitting = true amount = 40 lifetime = 1.0 one_shot = false preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.2 randomness = 1.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -400, -400, 800, 800 ) local_coords = false draw_order = 0 process_material = SubResource( 8 ) texture = ExtResource( 5 ) normal_map = null h_frames = 1 v_frames = 1 _sections_unfolded = [ "Drawing", "Process Material", "Textures" ] [node name="TinySparkles" type="Particles2D" parent="." index="1"] visible = false rotation = -1.61079 emitting = true amount = 60 lifetime = 1.0 one_shot = false preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.2 randomness = 1.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -400, -400, 800, 800 ) local_coords = false draw_order = 0 process_material = SubResource( 10 ) texture = ExtResource( 2 ) normal_map = null h_frames = 2 v_frames = 1 _sections_unfolded = [ "Drawing", "Process Material", "Textures" ] ================================================ FILE: vfx/particles/fiery_cloud/Fireball.tscn ================================================ [gd_scene load_steps=17 format=2] [ext_resource path="res://assets/gradient_ramps/fire_to_black.tres" type="Gradient" id=1] [ext_resource path="res://dust_charge/puffs.png" type="Texture" id=2] [ext_resource path="res://fiery_cloud/fiery_cloud.gd" type="Script" id=3] [ext_resource path="res://assets/gradient_ramps/sparkles_small.tres" type="Gradient" id=4] [ext_resource path="res://explosions/circle.png" type="Texture" id=5] [ext_resource path="res://assets/gradient_ramps/sparkles.tres" type="Gradient" id=6] [sub_resource type="GradientTexture" id=1] flags = 4 gradient = ExtResource( 1 ) width = 2048 [sub_resource type="Curve" id=2] min_value = 0.0 max_value = 3.0 bake_resolution = 100 _data = [ Vector2( 0, 0.645313 ), 0.0, 2.139, 0, 0, Vector2( 1, 2.55371 ), 2.94849, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=3] flags = 4 width = 2048 curve = SubResource( 2 ) [sub_resource type="ParticlesMaterial" id=4] render_priority = 0 trail_divisor = 1 emission_shape = 1 emission_sphere_radius = 10.0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 180.0 flatness = 0.0 gravity = Vector3( 0, 98, 0 ) initial_velocity = 120.0 initial_velocity_random = 0.0 angular_velocity = 0.0 angular_velocity_random = 0.0 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = 0.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 0.0 tangential_accel_random = 0.0 damping = 0.0 damping_random = 0.0 angle = 360.0 angle_random = 1.0 scale = 0.4 scale_random = 1.0 scale_curve = SubResource( 3 ) color_ramp = SubResource( 1 ) hue_variation = 0.0 hue_variation_random = 0.0 anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 0.0 anim_offset_random = 0.0 anim_loop = false _sections_unfolded = [ "Color", "Emission Shape", "Hue Variation", "Scale", "Spread", "Trail" ] [sub_resource type="GradientTexture" id=5] flags = 4 gradient = ExtResource( 4 ) width = 2048 [sub_resource type="Curve" id=6] min_value = 0.0 max_value = 1.0 bake_resolution = 100 _data = [ Vector2( 0, 0.399763 ), 0.0, 0.0, 0, 0, Vector2( 1, 1 ), 0.0, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=7] flags = 4 width = 2048 curve = SubResource( 6 ) [sub_resource type="ParticlesMaterial" id=8] render_priority = 0 trail_divisor = 1 emission_shape = 1 emission_sphere_radius = 24.0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 120.0 flatness = 0.0 gravity = Vector3( 0, 500, 0 ) initial_velocity = 200.0 initial_velocity_random = 0.6 angular_velocity = 0.0 angular_velocity_random = 0.0 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = 0.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 100.0 tangential_accel_random = 0.0 damping = 0.0 damping_random = 0.0 angle = 0.0 angle_random = 0.0 scale = 0.04 scale_random = 0.0 scale_curve = SubResource( 7 ) color_ramp = SubResource( 5 ) hue_variation = 0.0 hue_variation_random = 0.0 anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 0.0 anim_offset_random = 0.0 anim_loop = false _sections_unfolded = [ "Color", "Gravity", "Tangential Accel" ] [sub_resource type="GradientTexture" id=9] flags = 4 gradient = ExtResource( 6 ) width = 2048 [sub_resource type="ParticlesMaterial" id=10] render_priority = 0 trail_divisor = 1 emission_shape = 1 emission_sphere_radius = 24.0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 120.0 flatness = 0.0 gravity = Vector3( 0, 450, 0 ) initial_velocity = 200.0 initial_velocity_random = 0.6 angular_velocity = 0.0 angular_velocity_random = 0.0 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = 0.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 100.0 tangential_accel_random = 0.0 damping = 0.0 damping_random = 0.0 angle = 0.0 angle_random = 0.0 scale = 0.04 scale_random = 0.0 scale_curve = SubResource( 7 ) color_ramp = SubResource( 9 ) hue_variation = 0.0 hue_variation_random = 0.0 anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 0.0 anim_offset_random = 0.0 anim_loop = false _sections_unfolded = [ "Color", "Gravity" ] [node name="Fireball" type="Particles2D" index="0"] position = Vector2( 274.321, -72.4055 ) emitting = true amount = 120 lifetime = 0.8 one_shot = false preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.0 randomness = 1.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -400, -400, 800, 800 ) local_coords = false draw_order = 1 process_material = SubResource( 4 ) texture = ExtResource( 2 ) normal_map = null h_frames = 2 v_frames = 1 script = ExtResource( 3 ) _sections_unfolded = [ "Process Material", "Textures", "Time", "Transform" ] TIME_SCALE = 3.0 RADIUS = 300.0 OFFSET = Vector2( 400, 200 ) active = true [node name="SmallSparkles" type="Particles2D" parent="." index="0"] rotation = -1.61079 emitting = true amount = 40 lifetime = 1.0 one_shot = false preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.2 randomness = 1.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -400, -400, 800, 800 ) local_coords = false draw_order = 0 process_material = SubResource( 8 ) texture = ExtResource( 5 ) normal_map = null h_frames = 1 v_frames = 1 _sections_unfolded = [ "Drawing", "Process Material", "Textures" ] [node name="TinySparkles" type="Particles2D" parent="." index="1"] rotation = -1.61079 emitting = true amount = 60 lifetime = 1.0 one_shot = false preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.2 randomness = 1.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -400, -400, 800, 800 ) local_coords = false draw_order = 0 process_material = SubResource( 10 ) texture = ExtResource( 2 ) normal_map = null h_frames = 2 v_frames = 1 _sections_unfolded = [ "Drawing", "Process Material", "Textures" ] ================================================ FILE: vfx/particles/fiery_cloud/FireryCloud.gd ================================================ tool extends Particles2D export(float) var TIME_SCALE = 1.0 export(float) var RADIUS = 200.0 export(Vector2) var OFFSET = Vector2() export(bool) var active = false setget set_active var time = 0.0 func _process(delta): time += delta var time_scaled = TIME_SCALE * time position = Vector2( cos(time_scaled) * RADIUS, sin(time_scaled) * RADIUS ) position += OFFSET func set_active(value): active = value set_process(active) if not active: position = Vector2() ================================================ FILE: vfx/particles/rocks/DirectionalRock.tscn ================================================ [gd_scene load_steps=5 format=2] [ext_resource path="res://vfx/particles/rocks/rocks_particle.tres" type="Material" id=1] [ext_resource path="res://vfx/particles/rocks/rocks.png" type="Texture" id=2] [ext_resource path="res://vfx/particles/rocks/crumbs_particle.tres" type="Material" id=3] [sub_resource type="GDScript" id=1] script/source = "extends Particles2D func initialize(position, angle): global_position = position rotation = angle yield(get_tree().create_timer(lifetime / speed_scale), \"timeout\") queue_free() " [node name="DirectionalRock" type="Particles2D"] modulate = Color( 0.691406, 0.486124, 0.132339, 1 ) rotation = -1.5708 emitting = false amount = 20 lifetime = 0.7 one_shot = true preprocess = 0.0 speed_scale = 1.5 explosiveness = 0.9 randomness = 0.9 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -100, -100, 200, 200 ) local_coords = false draw_order = 0 process_material = ExtResource( 1 ) texture = ExtResource( 2 ) normal_map = null h_frames = 1 v_frames = 1 script = SubResource( 1 ) _sections_unfolded = [ "Material", "Process Material", "Time", "Visibility" ] [node name="Pebbles2" type="Particles2D" parent="." index="0"] self_modulate = Color( 0.744278, 0.768273, 0.832031, 1 ) show_behind_parent = true scale = Vector2( 1.3383, 1.50043 ) emitting = true amount = 20 lifetime = 0.7 one_shot = false preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.8 randomness = 0.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -100, -100, 200, 200 ) local_coords = false draw_order = 0 process_material = ExtResource( 3 ) texture = ExtResource( 2 ) normal_map = null h_frames = 1 v_frames = 1 _sections_unfolded = [ "Process Material", "Time", "Visibility" ] [node name="Pebbles" type="Particles2D" parent="." index="1"] show_behind_parent = true scale = Vector2( 1.01931, 1.27982 ) emitting = true amount = 20 lifetime = 0.7 one_shot = false preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.8 randomness = 0.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -100, -100, 200, 200 ) local_coords = false draw_order = 0 process_material = ExtResource( 3 ) texture = ExtResource( 2 ) normal_map = null h_frames = 1 v_frames = 1 _sections_unfolded = [ "Process Material", "Time", "Visibility" ] ================================================ FILE: vfx/particles/rocks/crumbs.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/crumbs.png-0cfbcc76d6de4ba75de4c089e6c455de.stex" metadata={ "vram_texture": false } [deps] source_file="res://vfx/particles/rocks/crumbs.png" dest_files=[ "res://.import/crumbs.png-0cfbcc76d6de4ba75de4c089e6c455de.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: vfx/particles/rocks/crumbs_particle.tres ================================================ [gd_resource type="ParticlesMaterial" load_steps=3 format=2] [sub_resource type="Curve" id=1] min_value = 0.0 max_value = 1.0 bake_resolution = 100 _data = [ Vector2( 0, 1 ), 0.0, -5.56082, 0, 0, Vector2( 0.502916, 0 ), 0.0, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=2] flags = 4 width = 2048 curve = SubResource( 1 ) [resource] render_priority = 0 trail_divisor = 1 emission_shape = 0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 180.0 flatness = 0.0 gravity = Vector3( 0, 200, 0 ) initial_velocity = 140.0 initial_velocity_random = 0.4 angular_velocity = 180.0 angular_velocity_random = 1.0 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = -60.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 0.0 tangential_accel_random = 0.0 damping = 80.0 damping_random = 0.0 angle = 0.0 angle_random = 1.0 scale = 0.15 scale_random = 0.3 scale_curve = SubResource( 2 ) color = Color( 0.816406, 0.816406, 0.816406, 1 ) hue_variation = 1.0 hue_variation_random = 0.0 anim_speed = 0.0 anim_speed_random = 0.0 anim_offset = 0.0 anim_offset_random = 0.0 anim_loop = false _sections_unfolded = [ "Color", "Emission Shape", "Trail" ] ================================================ FILE: vfx/particles/rocks/rocks.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/rocks.png-55d7ebb59a35e3e8e667f24e321f9c1b.stex" metadata={ "vram_texture": false } [deps] source_file="res://vfx/particles/rocks/rocks.png" dest_files=[ "res://.import/rocks.png-55d7ebb59a35e3e8e667f24e321f9c1b.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: vfx/particles/rocks/rocks_particle.tres ================================================ [gd_resource type="ParticlesMaterial" load_steps=9 format=2] [sub_resource type="Curve" id=1] min_value = 0.0 max_value = 200.0 bake_resolution = 100 _data = [ Vector2( 0, 0 ), 0.0, 53.531, 0, 0, Vector2( 0.249193, 0 ), -8.39704, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=2] flags = 4 width = 2048 curve = SubResource( 1 ) [sub_resource type="Gradient" id=3] offsets = PoolRealArray( 0.881657, 1 ) colors = PoolColorArray( 1, 1, 1, 1, 1, 1, 1, 0 ) [sub_resource type="GradientTexture" id=4] flags = 4 gradient = SubResource( 3 ) width = 2048 [sub_resource type="Curve" id=5] min_value = -200.0 max_value = 200.0 bake_resolution = 100 _data = [ Vector2( 0, 1 ), 0.0, 0.0, 0, 0, Vector2( 1, -55.8594 ), 0.0, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=6] flags = 4 width = 2048 curve = SubResource( 5 ) [sub_resource type="Curve" id=7] min_value = 0.0 max_value = 1.0 bake_resolution = 100 _data = [ Vector2( 0, 0.446289 ), 0.0, 8.58244, 0, 0, Vector2( 0.410727, 1 ), -1.18141, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=8] flags = 4 width = 32 curve = SubResource( 7 ) [resource] render_priority = 0 trail_divisor = 1 emission_shape = 0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 30.0 flatness = 0.0 gravity = Vector3( 0, 500, 0 ) initial_velocity = 500.0 initial_velocity_random = 0.5 angular_velocity = 360.0 angular_velocity_random = 0.53 orbit_velocity = 0.0 orbit_velocity_random = 0.0 linear_accel = 0.0 linear_accel_random = 0.0 linear_accel_curve = SubResource( 6 ) radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 0.0 tangential_accel_random = 0.0 damping = 100.0 damping_random = 0.0 angle = 0.0 angle_random = 1.0 scale = 0.1 scale_random = 0.7 scale_curve = SubResource( 8 ) color_ramp = SubResource( 4 ) hue_variation = 1.0 hue_variation_random = 0.02 anim_speed = 0.0 anim_speed_random = 0.0 anim_speed_curve = SubResource( 2 ) anim_offset = 0.0 anim_offset_random = 0.0 anim_loop = false _sections_unfolded = [ "Color", "Scale" ] ================================================ FILE: vfx/particles/smoke/EnemySmokeScreen.tscn ================================================ [gd_scene load_steps=3 format=2] [ext_resource path="res://vfx/particles/smoke/smoke_screen_particle.tres" type="Material" id=1] [ext_resource path="res://vfx/particles/smoke/smoke.png" type="Texture" id=2] [node name="EnemySmokeScreen" type="Particles2D" index="0"] self_modulate = Color( 0.90831, 0.918911, 0.941406, 1 ) emitting = false amount = 10 lifetime = 0.9 one_shot = true preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.8 randomness = 1.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -100, -100, 200, 200 ) local_coords = false draw_order = 0 process_material = ExtResource( 1 ) texture = ExtResource( 2 ) normal_map = null h_frames = 1 v_frames = 1 _sections_unfolded = [ "Drawing", "Process Material", "Textures", "Time" ] [node name="SmokeDarker" type="Particles2D" parent="." index="0"] self_modulate = Color( 0.632904, 0.671685, 0.726563, 1 ) show_behind_parent = true scale = Vector2( 1.20092, 1.32186 ) emitting = false amount = 20 lifetime = 0.7 one_shot = true preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.8 randomness = 0.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -100, -100, 200, 200 ) local_coords = true draw_order = 0 process_material = ExtResource( 1 ) texture = ExtResource( 2 ) normal_map = null h_frames = 1 v_frames = 1 _sections_unfolded = [ "Material", "Process Material", "Textures", "Time", "Visibility" ] [node name="SmokeGrey" type="Particles2D" parent="." index="1"] self_modulate = Color( 0.789703, 0.828256, 0.882813, 1 ) show_behind_parent = true scale = Vector2( 1.05668, 1.05668 ) emitting = false amount = 20 lifetime = 0.8 one_shot = true preprocess = 0.0 speed_scale = 1.0 explosiveness = 0.8 randomness = 0.0 fixed_fps = 0 fract_delta = true visibility_rect = Rect2( -100, -100, 200, 200 ) local_coords = true draw_order = 0 process_material = ExtResource( 1 ) texture = ExtResource( 2 ) normal_map = null h_frames = 1 v_frames = 1 _sections_unfolded = [ "Material", "Process Material", "Textures", "Time", "Visibility" ] ================================================ FILE: vfx/particles/smoke/ParticlesPlayer.gd ================================================ extends Particles2D func play(): emitting = true for child in get_children(): if not child.get_class() == "Particles2D": continue child.emitting = true ================================================ FILE: vfx/particles/smoke/smoke.png.import ================================================ [remap] importer="texture" type="StreamTexture" path="res://.import/smoke.png-510677d7daa804cf41c380a0acf068c5.stex" metadata={ "vram_texture": false } [deps] source_file="res://vfx/particles/smoke/smoke.png" dest_files=[ "res://.import/smoke.png-510677d7daa804cf41c380a0acf068c5.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=true flags/mipmaps=false flags/anisotropic=false flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false process/invert_color=false stream=false size_limit=0 detect_3d=true svg/scale=1.0 ================================================ FILE: vfx/particles/smoke/smoke_screen_particle.tres ================================================ [gd_resource type="ParticlesMaterial" load_steps=5 format=2] [sub_resource type="Gradient" id=1] offsets = PoolRealArray( 0.912387, 1 ) colors = PoolColorArray( 1, 1, 1, 1, 1, 1, 1, 0 ) [sub_resource type="GradientTexture" id=2] flags = 4 gradient = SubResource( 1 ) width = 2048 [sub_resource type="Curve" id=3] min_value = 0.0 max_value = 1.0 bake_resolution = 100 _data = [ Vector2( 0, 0.136789 ), 0.0, 3.12433, 0, 0, Vector2( 0.469416, 1 ), 0.0, 0.0, 0, 0, Vector2( 0.998443, 0.728062 ), -0.801458, 0.0, 0, 0 ] [sub_resource type="CurveTexture" id=4] flags = 4 width = 2048 curve = SubResource( 3 ) [resource] render_priority = 0 trail_divisor = 1 emission_shape = 1 emission_sphere_radius = 12.0 flag_align_y = false flag_rotate_y = false flag_disable_z = true spread = 180.0 flatness = 0.0 gravity = Vector3( 0, -20, 0 ) initial_velocity = 40.0 initial_velocity_random = 0.2 angular_velocity = 80.0 angular_velocity_random = 0.0 orbit_velocity = 0.0 orbit_velocity_random = 1.0 linear_accel = 0.0 linear_accel_random = 0.0 radial_accel = 0.0 radial_accel_random = 0.0 tangential_accel = 20.0 tangential_accel_random = 0.0 damping = 0.0 damping_random = 0.4 angle = 360.0 angle_random = 1.0 scale = 0.4 scale_random = 0.6 scale_curve = SubResource( 4 ) color_ramp = SubResource( 2 ) hue_variation = 0.0 hue_variation_random = 0.0 anim_speed = 1.0 anim_speed_random = 0.5 anim_offset = 0.0 anim_offset_random = 0.0 anim_loop = false _sections_unfolded = [ "Scale" ] ================================================ FILE: vfx/transition.shader ================================================ shader_type canvas_item; render_mode unshaded; uniform float cutoff : hint_range(0.0, 1.0); uniform float smooth_size : hint_range(0.0, 1.0); uniform sampler2D mask : hint_albedo; uniform vec4 color : hint_color; void fragment() { float value = texture(mask, UV).r; float alpha = smoothstep(cutoff, cutoff + smooth_size, value * (1.0 - smooth_size) + smooth_size); COLOR = vec4(color.rgb, alpha); }