Merge branch 'develop'

This commit is contained in:
Dan 2026-02-21 11:59:02 +00:00
commit 40bec3d8aa
617 changed files with 21570 additions and 2 deletions

7
.gitignore vendored
View file

@ -1,2 +1,9 @@
# Godot 4+ specific ignores
.godot/
.vscode/
build/
resources/concept art/
resources/textures/beehive.png~

View file

@ -0,0 +1,207 @@
## Core utility class to handle all refactoring logic
const EditorUtil := preload("res://addons/anim_player_refactor/lib/editor_util.gd")
var _editor_plugin: EditorPlugin
var _undo_redo: EditorUndoRedoManager
func _init(editor_plugin: EditorPlugin) -> void:
_editor_plugin = editor_plugin
_undo_redo = editor_plugin.get_undo_redo()
# Nodes
func rename_node_path(anim_player: AnimationPlayer, old: NodePath, new: NodePath):
if old == new:
return
_undo_redo.create_action("Refactor node tracks", UndoRedo.MERGE_ALL, anim_player)
_foreach_animation(anim_player, func(animation: Animation):
for i in animation.get_track_count():
var path := animation.track_get_path(i)
var node_path := path.get_concatenated_names()
if node_path == old.get_concatenated_names():
var new_path := new.get_concatenated_names() + ":" + path.get_concatenated_subnames()
animation.track_set_path(i, NodePath(new_path))
_undo_redo.add_do_property(animation, "tracks/%d/path" % i, new_path)
_undo_redo.add_undo_property(animation, "tracks/%d/path" % i, path)
)
_undo_redo.commit_action()
func remove_node_path(anim_player: AnimationPlayer, node_path: NodePath):
_undo_redo.create_action("Remove node tracks", UndoRedo.MERGE_ALL, anim_player)
_foreach_animation_restore(anim_player, _undo_redo, func(animation: Animation):
var removed_tracks = 0
for i in range(animation.get_track_count() - 1, -1, -1):
var path = animation.track_get_path(i)
if NodePath(path.get_concatenated_names()) == node_path:
removed_tracks += 1
_undo_redo.add_do_method(animation, &'remove_track', i)
return removed_tracks
)
_undo_redo.commit_action()
# Tracks
func rename_track_path(anim_player: AnimationPlayer, old: NodePath, new: NodePath):
if old == new:
return
_undo_redo.create_action("Refactor track paths", UndoRedo.MERGE_ALL, anim_player)
_foreach_animation(anim_player, func(animation: Animation):
for i in animation.get_track_count():
var path = animation.track_get_path(i)
if path == old:
animation.track_set_path(i, new)
_undo_redo.add_do_property(animation, "tracks/%d/path" % i, new)
_undo_redo.add_undo_property(animation, "tracks/%d/path" % i, old)
)
_undo_redo.commit_action()
func remove_track_path(anim_player: AnimationPlayer, property_path: NodePath):
_undo_redo.create_action("Remove tracks", UndoRedo.MERGE_ALL, anim_player)
_foreach_animation_restore(anim_player, _undo_redo, func(animation: Animation):
var removed_tracks = 0
for i in range(animation.get_track_count() - 1, -1, -1):
var path = animation.track_get_path(i)
if path == property_path:
removed_tracks += 1
_undo_redo.add_do_method(animation, &'remove_track', i)
return removed_tracks
)
_undo_redo.commit_action()
# Method tracks
func rename_method(anim_player, old: NodePath, new: NodePath):
if old == new:
return
var node_path := NodePath(old.get_concatenated_names())
var old_method := old.get_concatenated_subnames()
var new_method := new.get_concatenated_subnames()
_undo_redo.create_action("Rename method keys", UndoRedo.MERGE_ALL, anim_player)
_foreach_animation(anim_player, func(animation: Animation):
for i in animation.get_track_count():
if (animation.track_get_type(i) == Animation.TYPE_METHOD and animation.track_get_path(i) == node_path):
for j in animation.track_get_key_count(i):
var name := animation.method_track_get_name(i, j)
if name == old_method:
var old_method_params := {
"method": old_method,
"args": animation.method_track_get_params(i, j)
}
var method_params := {
"method": new_method,
"args": animation.method_track_get_params(i, j)
}
_undo_redo.add_do_method(animation, &'track_set_key_value', i, j, method_params)
_undo_redo.add_undo_method(animation, &'track_set_key_value', i, j, old_method_params)
)
_undo_redo.commit_action()
func remove_method(anim_player: AnimationPlayer, method_path: NodePath):
_undo_redo.create_action("Remove method keys", UndoRedo.MERGE_ALL, anim_player)
_foreach_animation_restore(anim_player, _undo_redo, func(animation: Animation):
for i in animation.get_track_count():
if (
animation.track_get_type(i) == Animation.TYPE_METHOD
and StringName(animation.track_get_path(i)) == method_path.get_concatenated_names()
):
for j in range(animation.track_get_key_count(i) - 1, -1, -1):
var name := animation.method_track_get_name(i, j)
if name == method_path.get_concatenated_subnames():
_undo_redo.add_do_method(animation, &'track_remove_key', i, j)
return 0
)
_undo_redo.commit_action()
# Root
func change_root(anim_player: AnimationPlayer, new_path: NodePath):
var current_root: Node = anim_player.get_node(anim_player.root_node)
var new_root: Node = anim_player.get_node_or_null(new_path)
if new_root == null:
return
_undo_redo.create_action("Change animation player root", UndoRedo.MERGE_ALL, anim_player)
_foreach_animation(anim_player, func(animation: Animation):
for i in animation.get_track_count():
var path := animation.track_get_path(i)
var node := current_root.get_node_or_null(NodePath(path.get_concatenated_names()))
if node == null:
push_warning("Invalid path: %s. Skipping root change." % path)
continue
var updated_path = str(new_root.get_path_to(node)) + ":" + path.get_concatenated_subnames()
_undo_redo.add_do_property(animation, "tracks/%d/path" % i, updated_path)
_undo_redo.add_undo_property(animation, "tracks/%d/path" % i, path)
)
_undo_redo.add_do_property(anim_player, "root_node", new_path)
_undo_redo.add_undo_property(anim_player, "root_node", anim_player.root_node)
_undo_redo.commit_action()
# Helper methods
## Iterates over all animations in the animation player
static func _foreach_animation(anim_player: AnimationPlayer, callback: Callable):
for lib_name in anim_player.get_animation_library_list():
var lib := anim_player.get_animation_library(lib_name)
for animation_name in lib.get_animation_list():
var animation := lib.get_animation(animation_name)
callback.call(animation)
## Iterates over all animations in the animation player and adds a full revert to the undo stack
## Useful for do actions that remove tracks
static func _foreach_animation_restore(anim_player: AnimationPlayer, undo_redo: EditorUndoRedoManager, callback: Callable):
for lib_name in anim_player.get_animation_library_list():
var lib := anim_player.get_animation_library(lib_name)
for animation_name in lib.get_animation_list():
var animation := lib.get_animation(animation_name)
var old_anim := animation.duplicate(true)
var removed_tracked = callback.call(animation)
for i in range(animation.get_track_count() - 1 - removed_tracked, -1, -1):
undo_redo.add_undo_method(animation, &'remove_track', i)
for i in range(old_anim.get_track_count()):
undo_redo.add_undo_method(old_anim, &'copy_track', i, animation)
undo_redo.add_undo_reference(old_anim)

View file

@ -0,0 +1,64 @@
# Utility class for parsing and hacking the editor
## Find menu button to add option to
static func find_animation_menu_button(node: Node) -> MenuButton:
var animation_editor := find_editor_control_with_class(node, "AnimationPlayerEditor")
if animation_editor:
return find_editor_control_with_class(
animation_editor,
"MenuButton",
func(node): return node.text == "Animation"
)
return null
## General utility to find a control in the editor using an iterative search
static func find_editor_control_with_class(
base: Control,
p_class_name: StringName,
condition := func(node: Node): return true
) -> Node:
if base.get_class() == p_class_name and condition.call(base):
return base
for child in base.get_children():
if not child is Control:
continue
var found = find_editor_control_with_class(child, p_class_name)
if found:
return found
return null
# Finds the active animation player (either pinned or selected)
static func find_active_anim_player(base_control: Control, scene_tree: Tree) -> AnimationPlayer:
var find_anim_player_recursive: Callable
var pin_icon := scene_tree.get_theme_icon("Pin", "EditorIcons")
var stack: Array[TreeItem] = []
stack.append(scene_tree.get_root())
while not stack.is_empty():
var current := stack.pop_back() as TreeItem
# Check for pin icon
for i in current.get_button_count(0):
if current.get_button(0, i) == pin_icon:
var node := base_control.get_node_or_null(current.get_metadata(0))
if node is AnimationPlayer:
return node
if current.is_selected(0):
var node := base_control.get_node_or_null(current.get_metadata(0))
if node is AnimationPlayer:
return node
for i in range(current.get_child_count() - 1, -1, -1):
stack.push_back(current.get_child(i))
return null

View file

@ -0,0 +1,7 @@
[plugin]
name="Animation Player Refactor"
description="Refactoring tools for AnimationPlayer libraries. Adds \"Refactor\" menu option under AnimationPlayer > Animation."
author="poohcom1"
version="0.1.4"
script="plugin.gd"

View file

@ -0,0 +1,144 @@
@tool
extends EditorPlugin
const RefactorDialogue := preload("scenes/refactor_dialogue/refactor_dialogue.gd")
const AnimPlayerInspectorButton := preload("scenes/inspector_button/inspector_button.gd")
const EditorUtil := preload("lib/editor_util.gd")
var activate_button: AnimPlayerInspectorButton
var refactor_dialogue: RefactorDialogue
var anim_menu_button: MenuButton
var _last_anim_player: AnimationPlayer
const SCENE_TREE_IDX := 0
var _scene_tree: Tree
func _enter_tree() -> void:
# Create dialogue
refactor_dialogue = load("res://addons/anim_player_refactor/scenes/refactor_dialogue/refactor_dialogue.tscn").instantiate()
get_editor_interface().get_base_control().add_child(refactor_dialogue)
refactor_dialogue.init(self)
# Create menu button
_add_refactor_option(func():
refactor_dialogue.popup_centered()
refactor_dialogue.reset_size()
)
func _exit_tree() -> void:
if refactor_dialogue and refactor_dialogue.is_inside_tree():
get_editor_interface().get_base_control().remove_child(refactor_dialogue)
refactor_dialogue.queue_free()
_remove_refactor_option()
func _handles(object: Object) -> bool:
if object is AnimationPlayer:
_last_anim_player = object
return false
# Editor methods
func get_anim_player() -> AnimationPlayer:
# Check for pinned animation
if not _scene_tree:
var _scene_tree_editor = EditorUtil.find_editor_control_with_class(
get_editor_interface().get_base_control(),
"SceneTreeEditor"
)
if not _scene_tree_editor:
push_error("[Animation Refactor] Could not find scene tree editor. Please report this.")
return null
_scene_tree = _scene_tree_editor.get_child(SCENE_TREE_IDX)
if not _scene_tree:
push_error("[Animation Refactor] Could not find scene tree editor. Please report this.")
return null
var found_anim := EditorUtil.find_active_anim_player(
get_editor_interface().get_base_control(),
_scene_tree
)
if found_anim:
return found_anim
# Get latest edited
return _last_anim_player
# Plugin buttons
const TOOL_REFACTOR := 999
const TOOL_ANIM_LIBRARY := 1
func _add_refactor_option(on_pressed: Callable):
var base_control := get_editor_interface().get_base_control()
if not anim_menu_button:
anim_menu_button = EditorUtil.find_animation_menu_button(base_control)
if not anim_menu_button:
push_error("Could not find Animation menu button. Please report this issue.")
return
# Remove item up to "Manage Animations..."
var menu_popup := anim_menu_button.get_popup()
var items := []
var count := menu_popup.item_count - 1
while count >= 0 and menu_popup.get_item_id(count) != TOOL_ANIM_LIBRARY:
if menu_popup.is_item_separator(count):
items.append({})
else:
items.append({
"shortcut": menu_popup.get_item_shortcut(count),
"id": menu_popup.get_item_id(count),
"icon": menu_popup.get_item_icon(count)
})
menu_popup.remove_item(count)
count -= 1
# Add refactor item
menu_popup.add_icon_item(
base_control.get_theme_icon(&"Reload", &"EditorIcons"),
"Refactor",
TOOL_REFACTOR,
)
# Re-add items
for i in range(items.size() - 1, -1, -1):
var item: Dictionary = items[i]
if not item.is_empty():
menu_popup.add_shortcut(item.shortcut, item.id)
menu_popup.set_item_icon(menu_popup.get_item_index(item.id), item.icon)
else:
menu_popup.add_separator()
menu_popup.notification(NOTIFICATION_TRANSLATION_CHANGED)
menu_popup.id_pressed.connect(_on_menu_button_pressed)
func _remove_refactor_option():
if not anim_menu_button:
return
var base_control := get_editor_interface().get_base_control()
var menu_popup := anim_menu_button.get_popup()
menu_popup.remove_item(menu_popup.get_item_index(TOOL_REFACTOR))
menu_popup.id_pressed.disconnect(_on_menu_button_pressed)
func _on_menu_button_pressed(id: int):
if id == TOOL_REFACTOR:
refactor_dialogue.popup_centered()

View file

@ -0,0 +1,17 @@
extends CodeEdit
func _ready() -> void:
code_completion_enabled = true
add_code_completion_option(CodeEdit.KIND_MEMBER, "Test", "test")
add_code_completion_option(CodeEdit.KIND_MEMBER, "Boo", "boo")
code_completion_prefixes = ["t", "b"]
code_completion_requested.connect(func():
add_code_completion_option(CodeEdit.KIND_MEMBER, "Test", "test")
add_code_completion_option(CodeEdit.KIND_MEMBER, "Boo", "boo")
update_code_completion_options(true)
)
text_changed.connect(func(): request_code_completion(true))

View file

@ -0,0 +1,50 @@
## Autocomplete Class
extends OptionButton
## LineEdit.text_change_rejected
signal text_change_rejected(rejected_substring: String)
## LineEdit.text_changed
signal text_changed(new_text: String)
## LineEdit.text_submitted
signal text_submitted(new_text: String)
## LineEdit component
var edit: LineEdit = LineEdit.new()
@export var get_autocomplete_options: Callable = func(text: String): return []
func _ready() -> void:
focus_mode = Control.FOCUS_NONE
edit.custom_minimum_size = size
get_popup().unfocusable = true
add_child(edit)
edit.reset_size()
edit.text_change_rejected.connect(func(arg): text_change_rejected.emit(arg))
edit.text_changed.connect(func(arg): text_changed.emit(arg))
edit.text_submitted.connect(func(arg): text_submitted.emit(arg))
edit.text_changed.connect(_update_options)
edit.focus_entered.connect(_update_options)
edit.focus_exited.connect(clear)
get_autocomplete_options = func(text: String):
return [
"test",
"ashina",
"hello"
].filter(func(el: String): return el.contains(text))
func _update_options(text: String = edit.text):
clear()
var options = get_autocomplete_options.call(text)
for option in options:
if typeof(option) == TYPE_STRING:
add_item(option)
show_popup()

View file

@ -0,0 +1,37 @@
extends EditorInspectorPlugin
signal button_clicked
var button: Button
var button_text: String
func _init(text: String) -> void:
button_text = text
func _can_handle(object: Object) -> bool:
return object is AnimationPlayer
func _parse_end(object: Object) -> void:
button = Button.new()
button.text = button_text
button.pressed.connect(func(): button_clicked.emit())
var margins := MarginContainer.new()
margins.add_theme_constant_override("margin_top", 8)
margins.add_theme_constant_override("margin_left", 16)
margins.add_theme_constant_override("margin_bottom", 8)
margins.add_theme_constant_override("margin_right", 16)
margins.add_child(button)
var container = VBoxContainer.new()
container.add_theme_constant_override("separation", 0)
container.add_child(HSeparator.new())
container.add_child(margins)
var container_margins := MarginContainer.new()
container_margins.add_theme_constant_override("margin_top", 8)
container_margins.add_theme_constant_override("margin_left", 4)
container_margins.add_theme_constant_override("margin_bottom", 8)
container_margins.add_theme_constant_override("margin_right", 4)
container_margins.add_child(container)
add_custom_control(container_margins)

View file

@ -0,0 +1,176 @@
@tool
extends Tree
signal rendered
const EditInfo := preload("edit_info.gd")
@export var edittable_items := false
func _ready() -> void:
reset_size()
func render(editor_plugin: EditorPlugin, anim_player: AnimationPlayer) -> void:
clear()
# Get paths
var animations = anim_player.get_animation_list()
var root_node := anim_player.get_node(anim_player.root_node)
var track_paths := {} # Dictionary[NodePath, Dictionary[NodePath, EditInfo]]
# Get EditInfo data
for anim_name in animations:
var animation := anim_player.get_animation(anim_name)
for i in animation.get_track_count():
var path := animation.track_get_path(i)
var type := animation.track_get_type(i)
var node_path := NodePath(path.get_concatenated_names())
var property_path := path.get_concatenated_subnames()
var node := root_node.get_node_or_null(node_path)
var edit_infos: Array[EditInfo] = []
if not node_path in track_paths:
track_paths[node_path] = {}
match type:
Animation.TYPE_METHOD:
for j in animation.track_get_key_count(i):
var method_path = NodePath(
(
path.get_concatenated_names()
+ ":"
+ animation.method_track_get_name(i, j)
)
)
var edit_info = EditInfo.new(
EditInfo.Type.METHOD_TRACK, method_path, node_path, node, [anim_name]
)
edit_infos.append(edit_info)
_:
if not property_path.is_empty():
var edit_info = EditInfo.new(
EditInfo.Type.VALUE_TRACK, path, node_path, node, [anim_name]
)
edit_infos.append(edit_info)
# Combine
for info in edit_infos:
if not StringName(info.path) in track_paths[node_path]:
track_paths[node_path][StringName(info.path)] = info
else:
for name in info.animation_names:
if name in track_paths[node_path][StringName(info.path)].animation_names: continue
track_paths[node_path][StringName(info.path)].animation_names.append(name)
# Sort
var paths := track_paths.keys()
paths.sort()
var tree_root: TreeItem = create_item()
hide_root = true
# Get icons
var gui := editor_plugin.get_editor_interface().get_base_control()
# Render
for path in paths:
var node := root_node.get_node_or_null(path)
var icon := gui.get_theme_icon(node.get_class() if node != null else "", "EditorIcons")
var path_item = create_item(tree_root)
path_item.set_editable(0, edittable_items)
if edittable_items:
path_item.set_text(0, path)
if path.get_concatenated_names() == ".." and node:
path_item.set_suffix(0, "(" + node.name + ")")
else:
path_item.set_text(0, node.name if node else path)
path_item.set_icon(0, icon)
path_item.set_metadata(0, EditInfo.new(EditInfo.Type.NODE, path, path, node, []))
path_item.add_button(0, gui.get_theme_icon("Edit", "EditorIcons"))
path_item.add_button(0, gui.get_theme_icon("Remove", "EditorIcons"))
var property_paths: Array = track_paths[path].keys()
property_paths.sort()
for property_path in property_paths:
var info: EditInfo = track_paths[path][property_path]
var edit_type = EditInfo.Type.VALUE_TRACK
var icon_type = "KeyValue"
var invalid = false
var property := info.path.get_concatenated_subnames()
if node == null:
invalid = true
icon_type = ""
elif node.has_method(StringName(property)):
icon_type = "KeyCall"
elif str(info.path) in node or node.get_indexed(NodePath(property)) != null:
pass
else:
invalid = true
icon_type = ""
var property_item = create_item(path_item)
property_item.set_editable(0, edittable_items)
property_item.set_text(0, property)
property_item.set_icon(0, gui.get_theme_icon(icon_type, "EditorIcons"))
property_item.set_metadata(0, info)
property_item.add_button(0, gui.get_theme_icon("Edit", "EditorIcons"))
property_item.add_button(0, gui.get_theme_icon("Remove", "EditorIcons"))
if invalid:
property_item.set_custom_color(0, Color.RED)
property_item.set_tooltip_text(0, "Possibly invalid value: %s" % info.path)
rendered.emit()
func set_filter(filter: String):
var item_stack := []
var visited := []
item_stack.append(get_root())
# Post-order traversal
while not item_stack.is_empty():
var current: TreeItem = item_stack[item_stack.size() - 1]
var children = current.get_children() if current else []
var children_all_visited := true
var child_visible := false
for child in children:
children_all_visited = children_all_visited and child in visited
child_visible = child_visible or child.visible
if children_all_visited:
item_stack.pop_back()
if current:
if current == get_root() or filter.is_empty() or child_visible:
current.visible = true
else:
current.visible = current.get_text(0).to_lower().contains(filter.to_lower())
visited.append(current)
else:
item_stack += children
## Class to cache heirarchy of nodes
## Unused
class TreeNode:
var node: Node
var path: String
var children: Dictionary
var parent: TreeNode
func debug(level = 0):
print(" - ".repeat(level) + node.name)
for name in children:
children[name].debug(level + 1)

View file

@ -0,0 +1,26 @@
## Data class for storing information on tracks
extends Object
enum Type { VALUE_TRACK, METHOD_TRACK, NODE }
## Type of info being edited
var type: Type
## Full path to property. Same as node_path if type is NODE
var path: NodePath
## Full path to node
var node_path: NodePath
## Cached node
var node: Node
## Animations the track is used in
var animation_names: Array[String] = []
func _init(type: Type, path: NodePath, node_path: NodePath, node: Node, animation_names: Array[String]) -> void:
self.type = type
self.path = path
self.node = node
self.node_path = node_path
self.animation_names = animation_names

View file

@ -0,0 +1,30 @@
@tool
extends Tree
var _editor_plugin: EditorPlugin
var _gui: Control
func init(editor_plugin: EditorPlugin):
_editor_plugin = editor_plugin
_gui = editor_plugin.get_editor_interface().get_base_control()
func render(anim_player: AnimationPlayer):
clear()
_create_items(null, anim_player, anim_player.owner)
func _create_items(parent: TreeItem, anim_player: AnimationPlayer, node: Node):
var icon := _gui.get_theme_icon(node.get_class(), "EditorIcons")
var item := create_item(parent)
item.set_text(0, node.name)
item.set_icon(0, icon)
item.set_metadata(0, anim_player.get_path_to(node))
if anim_player.get_path_to(node) == anim_player.root_node:
item.select(0)
scroll_to_item(item)
for child in node.get_children():
_create_items(item, anim_player, child)

View file

@ -0,0 +1,235 @@
@tool
extends AcceptDialog
const CustomEditorPlugin := preload("res://addons/anim_player_refactor/plugin.gd")
const EditorUtil := preload("res://addons/anim_player_refactor/lib/editor_util.gd")
const AnimPlayerRefactor = preload("res://addons/anim_player_refactor/lib/anim_player_refactor.gd")
const AnimPlayerTree := preload("components/anim_player_tree.gd")
const EditInfo := preload("components/edit_info.gd")
const NodeSelect := preload("components/node_select.gd")
var _editor_plugin: CustomEditorPlugin
var _editor_interface: EditorInterface
var _anim_player_refactor: AnimPlayerRefactor
var _anim_player: AnimationPlayer
@onready var anim_player_tree: AnimPlayerTree = $%AnimPlayerTree
@onready var change_root: Button = $%ChangeRoot
@onready var edit_dialogue: ConfirmationDialog = $%EditDialogue
@onready var edit_dialogue_input: LineEdit = $%EditInput
@onready var edit_dialogue_button: Button = $%EditDialogueButton # Just for pretty icon display
@onready var edit_full_path_toggle: CheckButton = $%EditFullPathToggle
@onready var edit_anim_list: Label = $%EditAnimationList
@onready var node_select_dialogue: ConfirmationDialog = $%NodeSelectDialogue
@onready var node_select: NodeSelect = $%NodeSelect
@onready var confirmation_dialogue: ConfirmationDialog = $%ConfirmationDialog
var is_full_path: bool:
set(val): edit_full_path_toggle.button_pressed = val
get: return edit_full_path_toggle.button_pressed
func init(editor_plugin: CustomEditorPlugin) -> void:
_editor_plugin = editor_plugin
_editor_interface = editor_plugin.get_editor_interface()
_anim_player_refactor = AnimPlayerRefactor.new(_editor_plugin)
node_select.init(_editor_plugin)
func _ready() -> void:
wrap_controls = true
about_to_popup.connect(render)
func render():
_anim_player = _editor_plugin.get_anim_player()
if not _anim_player or not _anim_player is AnimationPlayer:
push_error("AnimationPlayer is null or invalid")
return
# Render track tree
anim_player_tree.render(_editor_plugin, _anim_player)
# Render root node button
var root_node: Node = _anim_player.get_node(_anim_player.root_node)
var node_path := str(_anim_player.owner.get_path_to(root_node))
if node_path == ".":
node_path = _anim_player.owner.name
else:
node_path = _anim_player.owner.name + "/" + node_path
change_root.text = "%s (Change)" % node_path
change_root.icon = _editor_interface.get_base_control().get_theme_icon(
root_node.get_class(), "EditorIcons"
)
# Rename
enum Action { Rename, Delete }
var _current_info: EditInfo
func _on_tree_activated():
_current_info = anim_player_tree.get_selected().get_metadata(0)
_on_action(Action.Rename)
func _on_tree_button_clicked(item: TreeItem, column: int, id: int, mouse_button_index: int):
_current_info = item.get_metadata(column)
if id == 0:
_on_action(Action.Rename)
elif id == 1:
_on_action(Action.Delete)
func _on_action(action: Action):
if action == Action.Rename:
_render_edit_dialogue()
edit_dialogue.popup_centered()
edit_dialogue_input.grab_focus()
edit_dialogue_input.caret_column = edit_dialogue_input.text.length()
elif action == Action.Delete:
var track_path = _current_info.path
var anim_player = _editor_plugin.get_anim_player()
var node = anim_player\
.get_node(anim_player.root_node)\
.get_node_or_null(_current_info.path)
if node:
track_path = node.name
var property := _current_info.path.get_concatenated_subnames()
if not property.is_empty():
track_path += ":" + property
var msg = 'Delete all tracks with the path "%s"?' % track_path
if _current_info.type == EditInfo.Type.NODE:
msg = 'Delete tracks belonging to the node "%s"?' % track_path
_show_confirmation(msg, _remove)
func _render_edit_dialogue():
var info := _current_info
if info.type == EditInfo.Type.METHOD_TRACK:
is_full_path = false
edit_full_path_toggle.disabled = true
edit_full_path_toggle.visible = false
else:
edit_full_path_toggle.disabled = false
edit_full_path_toggle.visible = true
if is_full_path:
edit_dialogue_input.text = info.path
else:
if info.type == EditInfo.Type.NODE:
edit_dialogue.title = "Rename node"
edit_dialogue_input.text = info.path.get_name(info.path.get_name_count() - 1)
elif info.type == EditInfo.Type.VALUE_TRACK:
edit_dialogue.title = "Rename Value"
edit_dialogue_input.text = info.path.get_concatenated_subnames()
elif info.type == EditInfo.Type.METHOD_TRACK:
edit_dialogue.title = "Rename method"
edit_dialogue_input.text = info.path.get_concatenated_subnames()
edit_dialogue_button.text = info.node_path
if str(info.node_path) in [".", ".."] and info.node:
# Show name for relatives paths
edit_dialogue_button.text = info.node.name
if info.node:
# Show icon
edit_dialogue_button.icon = _editor_interface.get_base_control().get_theme_icon(
info.node.get_class(), "EditorIcons"
)
edit_anim_list.text = ""
for name in _current_info.animation_names:
edit_anim_list.text += "" + name + "\n"
## Toggle full path and re-render edit dialogue
func _on_full_path_toggled(pressed: bool):
_render_edit_dialogue()
## Callback on rename
func _on_rename_confirmed(_arg0 = null):
var new := edit_dialogue_input.text
edit_dialogue.hide()
if not _anim_player or not _anim_player is AnimationPlayer:
push_error("AnimationPlayer is null or invalid")
return
if new.is_empty():
return
var info: EditInfo = _current_info
if info.type == EditInfo.Type.NODE:
var old := info.path
var new_path = new
if not is_full_path:
new_path = ""
for i in range(info.path.get_name_count() - 1):
new_path += info.path.get_name(i) + "/"
new_path += new
_anim_player_refactor.rename_node_path(_anim_player, old, NodePath(new))
elif info.type == EditInfo.Type.VALUE_TRACK:
var old_path := info.path
var new_path := NodePath(new)
if not is_full_path:
new_path = info.node_path.get_concatenated_names() + ":" + new
_anim_player_refactor.rename_track_path(_anim_player, old_path, new_path)
elif info.type == EditInfo.Type.METHOD_TRACK:
var old_method := info.path
var new_method := NodePath(
info.path.get_concatenated_names() + ":" + new
)
_anim_player_refactor.rename_method(_anim_player, old_method, new_method)
await get_tree().create_timer(0.1).timeout
render()
func _remove():
var info: EditInfo = _current_info
match info.type:
EditInfo.Type.NODE:
_anim_player_refactor.remove_node_path(_anim_player, info.node_path)
EditInfo.Type.VALUE_TRACK:
_anim_player_refactor.remove_track_path(_anim_player, info.path)
EditInfo.Type.METHOD_TRACK:
_anim_player_refactor.remove_method(_anim_player, info.path)
await get_tree().create_timer(0.1).timeout
render()
# Change root
func _on_change_root_pressed():
node_select_dialogue.popup_centered()
node_select.render(_editor_plugin.get_anim_player())
func _on_node_select_confirmed():
var path: NodePath = node_select.get_selected().get_metadata(0)
_anim_player_refactor.change_root(_editor_plugin.get_anim_player(), path)
await get_tree().create_timer(0.1).timeout
render()
# Confirmation
func _show_confirmation(text: String, on_confirmed: Callable):
for c in confirmation_dialogue.confirmed.get_connections():
confirmation_dialogue.confirmed.disconnect(c.callable)
confirmation_dialogue.confirmed.connect(on_confirmed, CONNECT_ONE_SHOT)
confirmation_dialogue.popup_centered()
confirmation_dialogue.dialog_text = text

View file

@ -0,0 +1,157 @@
[gd_scene load_steps=4 format=3 uid="uid://cyfxysds8uhnx"]
[ext_resource type="Script" path="res://addons/anim_player_refactor/scenes/refactor_dialogue/refactor_dialogue.gd" id="1_nkqdl"]
[ext_resource type="Script" path="res://addons/anim_player_refactor/scenes/refactor_dialogue/components/anim_player_tree.gd" id="2_7pqfs"]
[ext_resource type="Script" path="res://addons/anim_player_refactor/scenes/refactor_dialogue/components/node_select.gd" id="3_87x4i"]
[node name="RefactorDialogue" type="AcceptDialog"]
title = "Refactor Animations"
size = Vector2i(400, 599)
ok_button_text = "Close"
script = ExtResource("1_nkqdl")
[node name="VBoxContainer" type="VBoxContainer" parent="."]
offset_left = 8.0
offset_top = 8.0
offset_right = 392.0
offset_bottom = 550.0
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 8
[node name="TreeContainer" type="VBoxContainer" parent="VBoxContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/TreeContainer"]
layout_mode = 2
text = "Properties:"
[node name="FilterInput" type="LineEdit" parent="VBoxContainer/TreeContainer"]
layout_mode = 2
placeholder_text = "Filter..."
caret_blink = true
caret_blink_interval = 0.5
[node name="AnimPlayerTree" type="Tree" parent="VBoxContainer/TreeContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(300, 400)
layout_mode = 2
size_flags_vertical = 3
hide_root = true
scroll_horizontal_enabled = false
script = ExtResource("2_7pqfs")
[node name="RootNodeContainer" type="VBoxContainer" parent="VBoxContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/RootNodeContainer"]
layout_mode = 2
text = "Root Node"
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/RootNodeContainer"]
layout_mode = 2
[node name="ChangeRoot" type="Button" parent="VBoxContainer/RootNodeContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "Change Root"
[node name="EditDialogue" type="ConfirmationDialog" parent="."]
unique_name_in_owner = true
title = "Renaming"
position = Vector2i(0, 36)
size = Vector2i(230, 239)
[node name="VBoxContainer" type="VBoxContainer" parent="EditDialogue"]
offset_left = 8.0
offset_top = 8.0
offset_right = 222.0
offset_bottom = 190.0
[node name="HBoxContainer" type="HBoxContainer" parent="EditDialogue/VBoxContainer"]
layout_mode = 2
[node name="EditDialogueButton" type="Button" parent="EditDialogue/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
focus_mode = 0
[node name="EditInput" type="LineEdit" parent="EditDialogue/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 0
[node name="HBoxContainer2" type="HBoxContainer" parent="EditDialogue/VBoxContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="EditDialogue/VBoxContainer/HBoxContainer2"]
layout_mode = 2
text = "Used in:"
[node name="EditFullPathToggle" type="CheckButton" parent="EditDialogue/VBoxContainer/HBoxContainer2"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 10
text = "Edit full path"
[node name="MarginContainer" type="MarginContainer" parent="EditDialogue/VBoxContainer"]
custom_minimum_size = Vector2(0, 100)
layout_mode = 2
[node name="ColorRect" type="ColorRect" parent="EditDialogue/VBoxContainer/MarginContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
color = Color(0, 0, 0, 0.211765)
[node name="ScrollContainer" type="ScrollContainer" parent="EditDialogue/VBoxContainer/MarginContainer"]
layout_mode = 2
size_flags_vertical = 3
horizontal_scroll_mode = 0
[node name="MarginContainer" type="MarginContainer" parent="EditDialogue/VBoxContainer/MarginContainer/ScrollContainer"]
layout_mode = 2
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="EditAnimationList" type="Label" parent="EditDialogue/VBoxContainer/MarginContainer/ScrollContainer/MarginContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "Test
Test 2"
[node name="NodeSelectDialogue" type="ConfirmationDialog" parent="."]
unique_name_in_owner = true
title = "Select a node..."
size = Vector2i(616, 557)
ok_button_text = "Change"
[node name="NodeSelect" type="Tree" parent="NodeSelectDialogue"]
unique_name_in_owner = true
custom_minimum_size = Vector2(600, 500)
offset_left = 8.0
offset_top = 8.0
offset_right = 608.0
offset_bottom = 508.0
scroll_horizontal_enabled = false
script = ExtResource("3_87x4i")
[node name="ConfirmationDialog" type="ConfirmationDialog" parent="."]
unique_name_in_owner = true
size = Vector2i(300, 200)
ok_button_text = "Delete"
dialog_autowrap = true
[connection signal="about_to_popup" from="." to="VBoxContainer/TreeContainer/FilterInput" method="clear"]
[connection signal="text_changed" from="VBoxContainer/TreeContainer/FilterInput" to="VBoxContainer/TreeContainer/AnimPlayerTree" method="set_filter"]
[connection signal="button_clicked" from="VBoxContainer/TreeContainer/AnimPlayerTree" to="." method="_on_tree_button_clicked"]
[connection signal="item_activated" from="VBoxContainer/TreeContainer/AnimPlayerTree" to="." method="_on_tree_activated"]
[connection signal="rendered" from="VBoxContainer/TreeContainer/AnimPlayerTree" to="VBoxContainer/TreeContainer/FilterInput" method="clear"]
[connection signal="pressed" from="VBoxContainer/RootNodeContainer/HBoxContainer/ChangeRoot" to="." method="_on_change_root_pressed"]
[connection signal="confirmed" from="EditDialogue" to="." method="_on_rename_confirmed"]
[connection signal="text_submitted" from="EditDialogue/VBoxContainer/EditInput" to="." method="_on_rename_confirmed"]
[connection signal="toggled" from="EditDialogue/VBoxContainer/HBoxContainer2/EditFullPathToggle" to="." method="_on_full_path_toggled"]
[connection signal="confirmed" from="NodeSelectDialogue" to="." method="_on_node_select_confirmed"]

1163
addons/gd-plug/plug.gd Normal file

File diff suppressed because it is too large Load diff

484
addons/log/log.gd Normal file
View file

@ -0,0 +1,484 @@
@tool
extends Object
class_name Log
## helpers ####################################
static func assoc(opts: Dictionary, key: String, val):
var _opts = opts.duplicate(true)
_opts[key] = val
return _opts
## config ####################################
static var config = {
max_array_size=20,
dictionary_skip_keys=["layer_0/tile_data"],
}
static func get_max_array_size():
return Log.config.get("max_array_size", 20)
static func get_dictionary_skip_keys():
return Log.config.get("dictionary_skip_keys", [])
static func set_color_scheme(scheme):
Log.config["color_scheme"] = scheme
static func get_config_color_scheme():
return Log.config.get("color_scheme", {})
## colors ###########################################################################
# terminal safe colors:
# - black
# - red
# - green
# - yellow
# - blue
# - magenta
# - pink
# - purple
# - cyan
# - white
# - orange
# - gray
static var COLORS_TERMINAL_SAFE = {
"SRC": "cyan",
"ADDONS": "red",
"TEST": "green",
",": "red",
"(": "red",
")": "red",
"[": "red",
"]": "red",
"{": "red",
"}": "red",
"&": "orange",
"^": "orange",
"dict_key": "magenta",
"vector_value": "green",
"class_name": "magenta",
TYPE_NIL: "pink",
TYPE_BOOL: "pink",
TYPE_INT: "green",
TYPE_FLOAT: "green",
TYPE_STRING: "pink",
TYPE_VECTOR2: "green",
TYPE_VECTOR2I: "green",
TYPE_RECT2: "green",
TYPE_RECT2I: "green",
TYPE_VECTOR3: "green",
TYPE_VECTOR3I: "green",
TYPE_TRANSFORM2D: "pink",
TYPE_VECTOR4: "green",
TYPE_VECTOR4I: "green",
TYPE_PLANE: "pink",
TYPE_QUATERNION: "pink",
TYPE_AABB: "pink",
TYPE_BASIS: "pink",
TYPE_TRANSFORM3D: "pink",
TYPE_PROJECTION: "pink",
TYPE_COLOR: "pink",
TYPE_STRING_NAME: "pink",
TYPE_NODE_PATH: "pink",
TYPE_RID: "pink",
TYPE_OBJECT: "pink",
TYPE_CALLABLE: "pink",
TYPE_SIGNAL: "pink",
TYPE_DICTIONARY: "pink",
TYPE_ARRAY: "pink",
TYPE_PACKED_BYTE_ARRAY: "pink",
TYPE_PACKED_INT32_ARRAY: "pink",
TYPE_PACKED_INT64_ARRAY: "pink",
TYPE_PACKED_FLOAT32_ARRAY: "pink",
TYPE_PACKED_FLOAT64_ARRAY: "pink",
TYPE_PACKED_STRING_ARRAY: "pink",
TYPE_PACKED_VECTOR2_ARRAY: "pink",
TYPE_PACKED_VECTOR3_ARRAY: "pink",
TYPE_PACKED_COLOR_ARRAY: "pink",
TYPE_MAX: "pink",
}
static var COLORS_PRETTY_V1 = {
"SRC": "aquamarine",
"ADDONS": "peru",
"TEST": "green_yellow",
",": "crimson",
"(": "crimson",
")": "crimson",
"[": "crimson",
"]": "crimson",
"{": "crimson",
"}": "crimson",
"&": "coral",
"^": "coral",
"dict_key": "cadet_blue",
"vector_value": "cornflower_blue",
"class_name": "cadet_blue",
TYPE_NIL: "coral",
TYPE_BOOL: "pink",
TYPE_INT: "cornflower_blue",
TYPE_FLOAT: "cornflower_blue",
TYPE_STRING: "dark_gray",
TYPE_VECTOR2: "cornflower_blue",
TYPE_VECTOR2I: "cornflower_blue",
TYPE_RECT2: "cornflower_blue",
TYPE_RECT2I: "cornflower_blue",
TYPE_VECTOR3: "cornflower_blue",
TYPE_VECTOR3I: "cornflower_blue",
TYPE_TRANSFORM2D: "pink",
TYPE_VECTOR4: "cornflower_blue",
TYPE_VECTOR4I: "cornflower_blue",
TYPE_PLANE: "pink",
TYPE_QUATERNION: "pink",
TYPE_AABB: "pink",
TYPE_BASIS: "pink",
TYPE_TRANSFORM3D: "pink",
TYPE_PROJECTION: "pink",
TYPE_COLOR: "pink",
TYPE_STRING_NAME: "pink",
TYPE_NODE_PATH: "pink",
TYPE_RID: "pink",
TYPE_OBJECT: "pink",
TYPE_CALLABLE: "pink",
TYPE_SIGNAL: "pink",
TYPE_DICTIONARY: "pink",
TYPE_ARRAY: "pink",
TYPE_PACKED_BYTE_ARRAY: "pink",
TYPE_PACKED_INT32_ARRAY: "pink",
TYPE_PACKED_INT64_ARRAY: "pink",
TYPE_PACKED_FLOAT32_ARRAY: "pink",
TYPE_PACKED_FLOAT64_ARRAY: "pink",
TYPE_PACKED_STRING_ARRAY: "pink",
TYPE_PACKED_VECTOR2_ARRAY: "pink",
TYPE_PACKED_VECTOR3_ARRAY: "pink",
TYPE_PACKED_COLOR_ARRAY: "pink",
TYPE_MAX: "pink",
}
## set color scheme ####################################
static func set_colors_termsafe():
set_color_scheme(Log.COLORS_TERMINAL_SAFE)
static func set_colors_pretty():
set_color_scheme(Log.COLORS_PRETTY_V1)
static func color_scheme(opts={}):
var scheme = opts.get("color_scheme", {})
# fill in any missing vals with the set scheme, then the term-safe fallbacks
scheme.merge(Log.get_config_color_scheme())
scheme.merge(Log.COLORS_TERMINAL_SAFE)
return scheme
static func color_wrap(s, opts={}):
var use_color = opts.get("use_color", true)
# don't rebuild the color scheme every time
var colors = opts.get("built_color_scheme", color_scheme(opts))
if use_color:
var color = opts.get("color")
if not color:
var s_type = opts.get("typeof", typeof(s))
if s_type is String:
# type overwrites
color = colors.get(s_type)
elif s_type is int and s_type == TYPE_STRING:
# specific strings/punctuation
var s_trimmed = s.strip_edges()
if s_trimmed in colors:
color = colors.get(s_trimmed)
else:
# fallback string color
color = colors.get(s_type)
else:
# all other types
color = colors.get(s_type)
if color == null:
print("Log.gd could not determine color for object: %s type: (%s)" % [str(s), typeof(s)])
return "[color=%s]%s[/color]" % [color, s]
else:
return s
## overwrites ###########################################################################
static var log_overwrites = {
"Vector2": func(msg, opts):
if opts.get("use_color", true):
return '%s%s%s%s%s' % [
Log.color_wrap("(", opts),
Log.color_wrap(msg.x, Log.assoc(opts, "typeof", "vector_value")),
Log.color_wrap(",", opts),
Log.color_wrap(msg.y, Log.assoc(opts, "typeof", "vector_value")),
Log.color_wrap(")", opts),
]
else:
return '(%s,%s)' % [msg.x, msg.y],
}
static func register_overwrite(key, handler):
# TODO warning on key exists?
# support multiple handlers?
# return success/fail?
# validate the key/handler somehow?
log_overwrites[key] = handler
## to_pretty ###########################################################################
# returns the passed object as a decorated string
static func to_pretty(msg, opts={}):
var newlines = opts.get("newlines", false)
var use_color = opts.get("use_color", true)
var indent_level = opts.get("indent_level", 0)
if not "indent_level" in opts:
opts["indent_level"] = indent_level
var color_scheme = opts.get("built_color_scheme", color_scheme(opts))
if not "built_color_scheme" in opts:
opts["built_color_scheme"] = color_scheme
if not is_instance_valid(msg) and typeof(msg) == TYPE_OBJECT:
return str("invalid instance: ", msg)
if msg == null:
return Log.color_wrap(msg, opts)
if msg is Object and msg.get_class() in log_overwrites:
return log_overwrites.get(msg.get_class()).call(msg, opts)
elif typeof(msg) in log_overwrites:
return log_overwrites.get(typeof(msg)).call(msg, opts)
# objects
if msg is Object and msg.has_method("to_pretty"):
return Log.to_pretty(msg.to_pretty(), opts)
if msg is Object and msg.has_method("data"):
return Log.to_pretty(msg.data(), opts)
if msg is Object and msg.has_method("to_printable"):
return Log.to_pretty(msg.to_printable(), opts)
# arrays
if msg is Array or msg is PackedStringArray:
if len(msg) > Log.get_max_array_size():
pr("[DEBUG]: truncating large array. total:", len(msg))
msg = msg.slice(0, Log.get_max_array_size() - 1)
if newlines:
msg.append("...")
var tmp = Log.color_wrap("[ ", opts)
var last = len(msg) - 1
for i in range(len(msg)):
if newlines and last > 1:
tmp += "\n\t"
tmp += Log.to_pretty(msg[i],
# duplicate here to prevent indenting-per-msg
# e.g. when printing an array of dictionaries
opts.duplicate(true))
if i != last:
tmp += Log.color_wrap(", ", opts)
tmp += Log.color_wrap(" ]", opts)
return tmp
# dictionary
elif msg is Dictionary:
var tmp = Log.color_wrap("{ ", opts)
var ct = len(msg)
var last
if len(msg) > 0:
last = msg.keys()[-1]
for k in msg.keys():
var val
if k in Log.get_dictionary_skip_keys():
val = "..."
else:
opts.indent_level += 1
val = Log.to_pretty(msg[k], opts)
if newlines and ct > 1:
tmp += "\n\t" \
+ range(indent_level)\
.map(func(_i): return "\t")\
.reduce(func(a, b): return str(a, b), "")
if use_color:
var key = Log.color_wrap('"%s"' % k, Log.assoc(opts, "typeof", "dict_key"))
tmp += "%s: %s" % [key, val]
else:
tmp += '"%s": %s' % [k, val]
if last and str(k) != str(last):
tmp += Log.color_wrap(", ", opts)
tmp += Log.color_wrap(" }", opts)
return tmp
# strings
elif msg is String:
if msg == "":
return '""'
if "[color=" in msg and "[/color]" in msg:
# assumes the string is already colorized
# NOT PERFECT! could use a regex for something more robust
return msg
return Log.color_wrap(msg, opts)
elif msg is StringName:
return str(Log.color_wrap("&", opts), '"%s"' % msg)
elif msg is NodePath:
return str(Log.color_wrap("^", opts), '"%s"' % msg)
# vectors
elif msg is Vector2 or msg is Vector2i:
return log_overwrites.get("Vector2").call(msg, opts)
elif msg is Vector3 or msg is Vector3i:
if use_color:
return '%s%s%s%s%s%s%s' % [
Log.color_wrap("(", opts),
Log.color_wrap(msg.x, Log.assoc(opts, "typeof", "vector_value")),
Log.color_wrap(",", opts),
Log.color_wrap(msg.y, Log.assoc(opts, "typeof", "vector_value")),
Log.color_wrap(",", opts),
Log.color_wrap(msg.z, Log.assoc(opts, "typeof", "vector_value")),
Log.color_wrap(")", opts),
]
else:
return '(%s,%s,%s)' % [msg.x, msg.y, msg.z]
elif msg is Vector4 or msg is Vector4i:
if use_color:
return '%s%s%s%s%s%s%s%s%s' % [
Log.color_wrap("(", opts),
Log.color_wrap(msg.x, Log.assoc(opts, "typeof", "vector_value")),
Log.color_wrap(",", opts),
Log.color_wrap(msg.y, Log.assoc(opts, "typeof", "vector_value")),
Log.color_wrap(",", opts),
Log.color_wrap(msg.z, Log.assoc(opts, "typeof", "vector_value")),
Log.color_wrap(",", opts),
Log.color_wrap(msg.w, Log.assoc(opts, "typeof", "vector_value")),
Log.color_wrap(")", opts),
]
else:
return '(%s,%s,%s,%s)' % [msg.x, msg.y, msg.z, msg.w]
# packed scene
elif msg is PackedScene:
if msg.resource_path != "":
return str(Log.color_wrap("PackedScene:", opts), '%s' % msg.resource_path.get_file())
elif msg.get_script() != null and msg.get_script().resource_path != "":
return Log.color_wrap(msg.get_script().resource_path.get_file(), Log.assoc(opts, "typeof", "class_name"))
else:
return Log.color_wrap(msg, opts)
# resource
elif msg is Resource:
if msg.get_script() != null and msg.get_script().resource_path != "":
return Log.color_wrap(msg.get_script().resource_path.get_file(), Log.assoc(opts, "typeof", "class_name"))
elif msg.resource_path != "":
return str(Log.color_wrap("Resource:", opts), '%s' % msg.resource_path.get_file())
else:
return Log.color_wrap(msg, opts)
# refcounted
elif msg is RefCounted:
if msg.get_script() != null and msg.get_script().resource_path != "":
return Log.color_wrap(msg.get_script().resource_path.get_file(), Log.assoc(opts, "typeof", "class_name"))
else:
return Log.color_wrap(msg.get_class(), Log.assoc(opts, "typeof", "class_name"))
# fallback to primitive-type lookup
else:
return Log.color_wrap(msg, opts)
## to_printable ###########################################################################
static func log_prefix(stack):
if len(stack) > 1:
var call_site = stack[1]
var basename = call_site["source"].get_file().get_basename()
var line_num = str(call_site.get("line", 0))
if call_site["source"].match("*/test/*"):
return "{" + basename + ":" + line_num + "}: "
elif call_site["source"].match("*/addons/*"):
return "<" + basename + ":" + line_num + ">: "
else:
return "[" + basename + ":" + line_num + "]: "
static func to_printable(msgs, opts={}):
var stack = opts.get("stack", [])
var pretty = opts.get("pretty", true)
var newlines = opts.get("newlines", false)
var m = ""
if len(stack) > 0:
var prefix = Log.log_prefix(stack)
var prefix_type
if prefix != null and prefix[0] == "[":
prefix_type = "SRC"
elif prefix != null and prefix[0] == "{":
prefix_type = "TEST"
elif prefix != null and prefix[0] == "<":
prefix_type = "ADDONS"
if pretty:
m += Log.color_wrap(prefix, Log.assoc(opts, "typeof", prefix_type))
else:
m += prefix
for msg in msgs:
# add a space between msgs
if pretty:
m += "%s " % Log.to_pretty(msg, opts)
else:
m += "%s " % str(msg)
return m.trim_suffix(" ")
## public print fns ###########################################################################
static func is_not_default(v):
return not v is String or (v is String and v != "ZZZDEF")
static func pr(msg, msg2="ZZZDEF", msg3="ZZZDEF", msg4="ZZZDEF", msg5="ZZZDEF", msg6="ZZZDEF", msg7="ZZZDEF"):
var msgs = [msg, msg2, msg3, msg4, msg5, msg6, msg7]
msgs = msgs.filter(Log.is_not_default)
var m = Log.to_printable(msgs, {stack=get_stack()})
print_rich(m)
static func info(msg, msg2="ZZZDEF", msg3="ZZZDEF", msg4="ZZZDEF", msg5="ZZZDEF", msg6="ZZZDEF", msg7="ZZZDEF"):
var msgs = [msg, msg2, msg3, msg4, msg5, msg6, msg7]
msgs = msgs.filter(Log.is_not_default)
var m = Log.to_printable(msgs, {stack=get_stack()})
print_rich(m)
static func log(msg, msg2="ZZZDEF", msg3="ZZZDEF", msg4="ZZZDEF", msg5="ZZZDEF", msg6="ZZZDEF", msg7="ZZZDEF"):
var msgs = [msg, msg2, msg3, msg4, msg5, msg6, msg7]
msgs = msgs.filter(Log.is_not_default)
var m = Log.to_printable(msgs, {stack=get_stack()})
print_rich(m)
static func prn(msg, msg2="ZZZDEF", msg3="ZZZDEF", msg4="ZZZDEF", msg5="ZZZDEF", msg6="ZZZDEF", msg7="ZZZDEF"):
var msgs = [msg, msg2, msg3, msg4, msg5, msg6, msg7]
msgs = msgs.filter(Log.is_not_default)
var m = Log.to_printable(msgs, {stack=get_stack(), newlines=true})
print_rich(m)
static func warn(msg, msg2="ZZZDEF", msg3="ZZZDEF", msg4="ZZZDEF", msg5="ZZZDEF", msg6="ZZZDEF", msg7="ZZZDEF"):
var msgs = [msg, msg2, msg3, msg4, msg5, msg6, msg7]
msgs = msgs.filter(Log.is_not_default)
var rich_msgs = msgs.duplicate()
rich_msgs.push_front("[color=yellow][WARN][/color]")
print_rich(Log.to_printable(rich_msgs, {stack=get_stack(), newlines=true}))
var m = Log.to_printable(msgs, {stack=get_stack(), newlines=true, pretty=false})
push_warning(m)
static func err(msg, msg2="ZZZDEF", msg3="ZZZDEF", msg4="ZZZDEF", msg5="ZZZDEF", msg6="ZZZDEF", msg7="ZZZDEF"):
var msgs = [msg, msg2, msg3, msg4, msg5, msg6, msg7]
msgs = msgs.filter(Log.is_not_default)
var rich_msgs = msgs.duplicate()
rich_msgs.push_front("[color=red][ERR][/color]")
print_rich(Log.to_printable(rich_msgs, {stack=get_stack(), newlines=true}))
var m = Log.to_printable(msgs, {stack=get_stack(), newlines=true, pretty=false})
push_error(m)
static func error(msg, msg2="ZZZDEF", msg3="ZZZDEF", msg4="ZZZDEF", msg5="ZZZDEF", msg6="ZZZDEF", msg7="ZZZDEF"):
var msgs = [msg, msg2, msg3, msg4, msg5, msg6, msg7]
msgs = msgs.filter(Log.is_not_default)
var rich_msgs = msgs.duplicate()
rich_msgs.push_front("[color=red][ERR][/color]")
print_rich(Log.to_printable(rich_msgs, {stack=get_stack(), newlines=true}))
var m = Log.to_printable(msgs, {stack=get_stack(), newlines=true, pretty=false})
push_error(m)

14
addons/log/plugin.cfg Normal file
View file

@ -0,0 +1,14 @@
[plugin]
name="Log.gd"
description="A pretty-printing debug logger.
Log.pr(\"some str\", some_object)
- Colorizes printed data based on datatype
- Handles nested data structures (Arrays and Dictionaries)
- Prefixes logs with the callsite's source file
- Opt-in to pretty printing via duck-typing (implement a `to_printable()` method on the object)"
author="Russell Matney"
version="v0.0.5"
script="plugin.gd"

3
addons/log/plugin.gd Normal file
View file

@ -0,0 +1,3 @@
@tool
extends EditorPlugin

View file

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://6w1nq8lhq3tq"]
[ext_resource type="Script" path="res://components/scripts/drop_shadow_component.gd" id="1_060pv"]
[node name="DropShadowComponent" type="Node2D"]
script = ExtResource("1_060pv")
[node name="DropShadowSprite" type="Sprite2D" parent="."]

View file

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://dn6aa6f2f4g4i"]
[ext_resource type="Script" path="res://components/scripts/rules_component.gd" id="1_53vkw"]
[node name="RulesComponent" type="Node"]
script = ExtResource("1_53vkw")

View file

@ -0,0 +1,24 @@
extends Node2D
@export var parent_sprite : Sprite2D = null
@export var drop_shadow_distance : int = 10
var drop_shadow_sprite : Sprite2D = null
func _ready() -> void:
if parent_sprite is Sprite2D:
drop_shadow()
pass
func drop_shadow() -> void:
drop_shadow_sprite = parent_sprite.duplicate()
drop_shadow_sprite.scale = Vector2(1.1, 1.1)
drop_shadow_sprite.set_modulate(Color(0, 0, 0, 0.1))
drop_shadow_sprite.set_position(Vector2(drop_shadow_distance, drop_shadow_distance))
#drop_shadow_sprite.global_position = parent_sprite.global_position + Vector2(drop_shadow_distance, drop_shadow_distance)
drop_shadow_sprite.show_behind_parent = true
parent_sprite.add_child.call_deferred(drop_shadow_sprite)

View file

@ -0,0 +1,18 @@
extends Resource
class_name GameRulesResource
@export_category("Level Description")
@export var level_number : int = 1
@export var level_name : String = ""
@export var level_description : String = ""
@export_category("Level Rules")
@export var bees_available : int = 10
@export var nectar_required : int = 50
@export var level_par : int = 2
@export_category("Drones Enabled")
@export var collector_enabled : bool = true
@export var dancer_enabled : bool = true
@export var director_enabled : bool = false
@export var distractor_enabled : bool = false

View file

@ -0,0 +1,4 @@
extends Node
class_name RulesComponent
@export var game_rules : GameRulesResource = null

237
entities/Bee.tscn Normal file
View file

@ -0,0 +1,237 @@
[gd_scene load_steps=21 format=3 uid="uid://deek6uv574xas"]
[ext_resource type="Script" path="res://entities/scripts/bee.gd" id="1_pnu7x"]
[ext_resource type="Script" path="res://entities/scripts/finite_state_machine.gd" id="1_t3s5d"]
[ext_resource type="Script" path="res://entities/bee/states/bee_idle.gd" id="3_vasc5"]
[ext_resource type="Script" path="res://entities/bee/states/bee_death.gd" id="5_1q5nb"]
[ext_resource type="Script" path="res://entities/bee/states/bee_gather.gd" id="5_4vs4l"]
[ext_resource type="Script" path="res://entities/scripts/bee_hit_box.gd" id="5_agq38"]
[ext_resource type="Script" path="res://entities/bee/states/bee_travelling.gd" id="5_qtx0r"]
[ext_resource type="Script" path="res://entities/bee/states/bee_sleeping.gd" id="7_6qlbu"]
[ext_resource type="Script" path="res://entities/bee/states/bee_returning.gd" id="8_dptvu"]
[ext_resource type="Texture2D" uid="uid://ch3qalaaky8ng" path="res://resources/textures/bee_body.png" id="10_yi42o"]
[ext_resource type="Texture2D" uid="uid://bsskcrayofs8n" path="res://resources/textures/bee_wings.png" id="11_utbwk"]
[ext_resource type="Texture2D" uid="uid://b2jr0mt5xymog" path="res://resources/particles/smoke_01.png" id="12_52rft"]
[sub_resource type="Animation" id="Animation_1dh34"]
resource_name = "Death"
length = 2.0
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("BeeBody:rotation")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.5, 2),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [0.0, 1.5708, 1.5708]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("BeeBody:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.6, 2),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Vector2(0, 0), Vector2(0, 50), Vector2(0, 50)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("ImpactCloud:self_modulate:a")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 0.4, 1.3),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [0.0, 0.0, 0.5]
}
tracks/3/type = "method"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath(".")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(2),
"transitions": PackedFloat32Array(1),
"values": [{
"args": [],
"method": &"queue_free"
}]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath(".:modulate:a")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0, 1.6, 2),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [1.0, 1.0, 0.0]
}
tracks/5/type = "value"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("ImpactCloud:visible")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(0, 2),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [true, false]
}
[sub_resource type="Animation" id="Animation_iys4n"]
resource_name = "Flying"
length = 5.0
loop_mode = 1
step = 0.25
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("BeeBody:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 1, 2, 3, 4, 5),
"transitions": PackedFloat32Array(-2, -2, -2, -2, -2, -2),
"update": 0,
"values": [Vector2(0, 0), Vector2(0, 10), Vector2(0, 5), Vector2(0, -5), Vector2(0, 10), Vector2(0, 0)]
}
[sub_resource type="Animation" id="Animation_t75ra"]
resource_name = "Idle"
[sub_resource type="Animation" id="Animation_0encb"]
length = 0.001
[sub_resource type="AnimationLibrary" id="AnimationLibrary_m27po"]
_data = {
"Death": SubResource("Animation_1dh34"),
"Flying": SubResource("Animation_iys4n"),
"Idle": SubResource("Animation_t75ra"),
"RESET": SubResource("Animation_0encb")
}
[sub_resource type="Animation" id="Animation_muxdj"]
resource_name = "Fly"
length = 0.5
loop_mode = 1
step = 0.05
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("BeeBody/BeeWings:scale")
tracks/0/interp = 1
tracks/0/loop_wrap = false
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45),
"transitions": PackedFloat32Array(-2, -2, -2, -2, -2, -2, -2, -2, -2, -2),
"update": 0,
"values": [Vector2(1, 1), Vector2(1, 0.1), Vector2(1, 1), Vector2(1, 0.1), Vector2(1, 1), Vector2(1, 0.1), Vector2(1, 1), Vector2(1, 0.1), Vector2(1, 1), Vector2(1, 0.1)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_yvewf"]
_data = {
"Fly": SubResource("Animation_muxdj")
}
[sub_resource type="CircleShape2D" id="CircleShape2D_86nxf"]
radius = 13.0384
[node name="Bee" type="CharacterBody2D" groups=["bee"]]
self_modulate = Color(1, 1, 1, 0.169489)
z_index = 99
collision_mask = 0
script = ExtResource("1_pnu7x")
[node name="BeePositionAnimation" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_m27po")
}
[node name="WingAnimation" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_yvewf")
}
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
light_mask = 0
shape = SubResource("CircleShape2D_86nxf")
[node name="HitBox" type="Area2D" parent="."]
collision_layer = 6
collision_mask = 7
script = ExtResource("5_agq38")
[node name="CollisionShape2D" type="CollisionShape2D" parent="HitBox"]
light_mask = 0
shape = SubResource("CircleShape2D_86nxf")
[node name="StateMachine" type="Node2D" parent="." node_paths=PackedStringArray("initial_state")]
script = ExtResource("1_t3s5d")
initial_state = NodePath("Idle")
[node name="Idle" type="Node" parent="StateMachine"]
script = ExtResource("3_vasc5")
[node name="Death" type="Node" parent="StateMachine"]
script = ExtResource("5_1q5nb")
[node name="Travelling" type="Node" parent="StateMachine"]
script = ExtResource("5_qtx0r")
[node name="Gathering" type="Node" parent="StateMachine"]
script = ExtResource("5_4vs4l")
[node name="Sleeping" type="Node" parent="StateMachine"]
script = ExtResource("7_6qlbu")
[node name="Returning" type="Node" parent="StateMachine"]
script = ExtResource("8_dptvu")
[node name="BeeBody" type="Sprite2D" parent="."]
position = Vector2(0, 50)
rotation = 1.5708
scale = Vector2(0.1, 0.1)
texture = ExtResource("10_yi42o")
[node name="BeeWings" type="Sprite2D" parent="BeeBody"]
scale = Vector2(1, 0.999992)
texture = ExtResource("11_utbwk")
[node name="CPUParticles2D" type="CPUParticles2D" parent="BeeBody"]
position = Vector2(0, 3.94118)
scale = Vector2(1.52885, 1.5978)
lifetime_randomness = 0.33
gravity = Vector2(0, 0)
linear_accel_min = 5.0
linear_accel_max = 10.0
[node name="Shadow" type="Sprite2D" parent="."]
modulate = Color(0, 0, 0, 0.0784314)
position = Vector2(0, 50)
scale = Vector2(0.07, 0.04)
texture = ExtResource("10_yi42o")
[node name="ImpactCloud" type="CPUParticles2D" parent="."]
self_modulate = Color(1, 1, 1, 0.333333)
position = Vector2(0, 50)
texture = ExtResource("12_52rft")
gravity = Vector2(0, 0)
scale_amount_min = 0.01
scale_amount_max = 0.1
[connection signal="area_entered" from="HitBox" to="HitBox" method="_on_area_entered"]
[connection signal="area_exited" from="HitBox" to="HitBox" method="_on_area_exited"]

64
entities/Beehive.tscn Normal file
View file

@ -0,0 +1,64 @@
[gd_scene load_steps=8 format=3 uid="uid://dyu4mucawjlu6"]
[ext_resource type="Script" path="res://entities/scripts/beehive.gd" id="1_ej1r1"]
[ext_resource type="Texture2D" uid="uid://dijxeckxe7trv" path="res://resources/textures/beehive.png" id="2_2xhre"]
[ext_resource type="PackedScene" uid="uid://6w1nq8lhq3tq" path="res://components/DropShadowComponent.tscn" id="3_uglsl"]
[ext_resource type="Texture2D" uid="uid://dhf4dessaw5p5" path="res://resources/particles/twirl_01.png" id="4_4biie"]
[sub_resource type="CircleShape2D" id="CircleShape2D_h6wmc"]
radius = 250.0
[sub_resource type="Animation" id="Animation_41718"]
resource_name = "Highlight"
length = 5.0
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("AreaHighlight:rotation")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 5),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [6.28319, 0.0]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_qs4pr"]
_data = {
"Highlight": SubResource("Animation_41718")
}
[node name="Beehive" type="Node2D"]
script = ExtResource("1_ej1r1")
[node name="BeehiveSprite" type="Sprite2D" parent="."]
position = Vector2(-3, 1)
scale = Vector2(0.5, 0.5)
texture = ExtResource("2_2xhre")
[node name="DropShadowComponent" parent="." node_paths=PackedStringArray("parent_sprite") instance=ExtResource("3_uglsl")]
parent_sprite = NodePath("../BeehiveSprite")
drop_shadow_distance = 25
[node name="Area2D" type="Area2D" parent="."]
visible = false
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
shape = SubResource("CircleShape2D_h6wmc")
[node name="AreaHighlight" type="Sprite2D" parent="."]
visible = false
self_modulate = Color(1, 1, 0.117647, 0.352941)
rotation = 6.28319
texture = ExtResource("4_4biie")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_qs4pr")
}
autoplay = "Highlight"
[connection signal="area_entered" from="Area2D" to="." method="_on_area_2d_area_entered"]
[connection signal="area_exited" from="Area2D" to="." method="_on_area_2d_area_exited"]

View file

@ -0,0 +1,80 @@
[gd_scene load_steps=5 format=3 uid="uid://dqdi1tpoid80c"]
[ext_resource type="Script" path="res://entities/scripts/collector_drone.gd" id="1_ws83e"]
[ext_resource type="Texture2D" uid="uid://btyc0yk5nbn2t" path="res://resources/textures/collector_drone.png" id="2_wq72s"]
[sub_resource type="Animation" id="Animation_m21sl"]
resource_name = "Idle"
length = 2.0
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("CollectorDrone:offset")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 1, 2),
"transitions": PackedFloat32Array(1, -2, 1),
"update": 0,
"values": [Vector2(0, 0), Vector2(10, 8), Vector2(0, 0)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("CollectorDrone:rotation")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 1, 2),
"transitions": PackedFloat32Array(1, -2, 1),
"update": 0,
"values": [0.0, 0.0523599, 0.0]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Shadow:offset")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 1, 2),
"transitions": PackedFloat32Array(1, -2, 1),
"update": 0,
"values": [Vector2(3.91169, 3.12935), Vector2(10, 8), Vector2(3.91169, 3.12935)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_keqev"]
_data = {
"Idle": SubResource("Animation_m21sl")
}
[node name="CollectorDrone" type="Node2D"]
script = ExtResource("1_ws83e")
[node name="Polygon2D" type="Polygon2D" parent="."]
visible = false
position = Vector2(1, -1)
color = Color(0.620241, 0.619217, 0.900702, 1)
polygon = PackedVector2Array(-28, -25, 25, -28, 26, 33, -32, 19)
[node name="CollectorDrone" type="Sprite2D" parent="."]
position = Vector2(0, 1)
rotation = 0.00352767
scale = Vector2(0.25, 0.25)
texture = ExtResource("2_wq72s")
offset = Vector2(0.673735, 0.538988)
[node name="Shadow" type="Sprite2D" parent="."]
modulate = Color(0, 0, 0, 0.0784314)
position = Vector2(0, 100)
rotation = 0.0204816
scale = Vector2(0.25, 0.1)
texture = ExtResource("2_wq72s")
offset = Vector2(4.32188, 3.4575)
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_keqev")
}
autoplay = "Idle"

179
entities/DancerDrone.tscn Normal file
View file

@ -0,0 +1,179 @@
[gd_scene load_steps=10 format=3 uid="uid://cx7cunaspu08a"]
[ext_resource type="Script" path="res://entities/scripts/dancer_drone.gd" id="1_44a5b"]
[ext_resource type="Texture2D" uid="uid://ck51br2sjtfbk" path="res://resources/textures/dancing_drone_body.png" id="2_d306w"]
[ext_resource type="Texture2D" uid="uid://bf3e8avdh3iwn" path="res://resources/textures/dancing_drone_hat.png" id="3_deyv3"]
[ext_resource type="Texture2D" uid="uid://btwh1m8nvxxn3" path="res://resources/textures/dancing_drone_leg_1.png" id="4_uppgc"]
[ext_resource type="Texture2D" uid="uid://0e8ksjsqrsg5" path="res://resources/textures/dancing_drone_leg_2.png" id="5_kvsjc"]
[sub_resource type="CircleShape2D" id="CircleShape2D_xfqbx"]
radius = 25.0
[sub_resource type="Animation" id="Animation_utxxn"]
resource_name = "Dancing"
length = 3.0
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("DancingDroneBody:rotation")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 1.5, 3),
"transitions": PackedFloat32Array(1, -2, 1),
"update": 0,
"values": [0.0, 0.0523599, 0.0]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("DancingDroneBody:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 1.5, 3),
"transitions": PackedFloat32Array(1, -2, 1),
"update": 0,
"values": [Vector2(1, -3), Vector2(10, -10), Vector2(1, -3)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("DancingDroneBody/DancingDroneHat:rotation")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 1.7, 3),
"transitions": PackedFloat32Array(1, -2, 1),
"update": 0,
"values": [0.0, 0.349066, 0.0]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("DancingDroneBody/DancingDroneLeg1:rotation")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0, 1.6, 3),
"transitions": PackedFloat32Array(1, -2, 1),
"update": 0,
"values": [0.0, -0.174533, 0.0]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("DancingDroneBody/DancingDroneLeg2:rotation")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0, 1.3, 3),
"transitions": PackedFloat32Array(1, -2, 1),
"update": 0,
"values": [0.0, -0.349066, 0.0]
}
tracks/5/type = "value"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("DancingDroneBody2:position")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(0, 1.5, 2.9),
"transitions": PackedFloat32Array(1, -0.5, 1),
"update": 0,
"values": [Vector2(1, 100), Vector2(10, 102), Vector2(1, 100)]
}
[sub_resource type="Animation" id="Animation_iwafd"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("DancingDroneBody2:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(1, 100)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_pfpsg"]
_data = {
"Dancing": SubResource("Animation_utxxn"),
"RESET": SubResource("Animation_iwafd")
}
[node name="DancerDrone" type="Node2D" groups=["dancer"]]
script = ExtResource("1_44a5b")
[node name="Polygon2D" type="Polygon2D" parent="."]
visible = false
position = Vector2(1, -1)
color = Color(0.354435, 0.719091, 0.745333, 1)
polygon = PackedVector2Array(-28, -25, 25, -28, 26, 33, -32, 19)
[node name="HitBox" type="Area2D" parent="." groups=["dancer"]]
[node name="HitBoxShape" type="CollisionShape2D" parent="HitBox"]
shape = SubResource("CircleShape2D_xfqbx")
[node name="DancingDroneBody" type="Sprite2D" parent="."]
position = Vector2(9.98454, -9.98798)
rotation = 0.05227
scale = Vector2(0.2, 0.2)
texture = ExtResource("2_d306w")
offset = Vector2(3.09204, 0)
[node name="DancingDroneHat" type="Sprite2D" parent="DancingDroneBody"]
position = Vector2(-102, -50)
rotation = 0.30747
texture = ExtResource("3_deyv3")
offset = Vector2(41, -91)
[node name="DancingDroneLeg1" type="Sprite2D" parent="DancingDroneBody"]
position = Vector2(-72, 94)
rotation = -0.163344
texture = ExtResource("4_uppgc")
offset = Vector2(19, 94)
[node name="DancingDroneLeg2" type="Sprite2D" parent="DancingDroneBody"]
position = Vector2(54, 86)
rotation = -0.33965
texture = ExtResource("5_kvsjc")
offset = Vector2(-16, 107)
[node name="DancingDroneBody2" type="Sprite2D" parent="."]
modulate = Color(0, 0, 0, 0.0784314)
position = Vector2(1, 100)
rotation = 0.0289966
scale = Vector2(0.2, 0.05)
texture = ExtResource("2_d306w")
offset = Vector2(3.09204, 0)
[node name="DancingDroneHat" type="Sprite2D" parent="DancingDroneBody2"]
position = Vector2(-102, -50)
rotation = 0.229387
texture = ExtResource("3_deyv3")
offset = Vector2(41, -91)
[node name="DancingDroneLeg1" type="Sprite2D" parent="DancingDroneBody2"]
position = Vector2(-72, 94)
rotation = -0.0983052
texture = ExtResource("4_uppgc")
offset = Vector2(19, 94)
[node name="DancingDroneLeg2" type="Sprite2D" parent="DancingDroneBody2"]
position = Vector2(54, 86)
rotation = -0.146
texture = ExtResource("5_kvsjc")
offset = Vector2(-16, 107)
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_pfpsg")
}
autoplay = "Dancing"

126
entities/DirectorDrone.tscn Normal file
View file

@ -0,0 +1,126 @@
[gd_scene load_steps=7 format=3 uid="uid://nxq2fd04ehcu"]
[ext_resource type="Script" path="res://entities/scripts/director_drone.gd" id="1_3v6jp"]
[ext_resource type="Texture2D" uid="uid://dnhs5ymd6ybyd" path="res://resources/textures/director_drone.png" id="2_8nbjk"]
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_wr5vn"]
radius = 43.0
height = 94.0
[sub_resource type="Animation" id="Animation_qstd5"]
resource_name = "Idle"
length = 2.0
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("DirectorDrone:offset")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 1, 2),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Vector2(0, 0), Vector2(10, 0), Vector2(0, 0)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Shadow:offset")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0.047402, 1, 2),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Vector2(0, 0), Vector2(10, 0), Vector2(0, 0)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("DirectorDrone:rotation")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 1, 2),
"transitions": PackedFloat32Array(1, -2, 1),
"update": 0,
"values": [0.0, 0.0523599, 0.0]
}
[sub_resource type="Animation" id="Animation_gkp0o"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("DirectorDrone:offset")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(0, 0)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Shadow:offset")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(0, 0)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_xu26h"]
_data = {
"Idle": SubResource("Animation_qstd5"),
"RESET": SubResource("Animation_gkp0o")
}
[node name="DirectorDrone" type="Node2D"]
script = ExtResource("1_3v6jp")
[node name="ClickDetection" type="Area2D" parent="."]
[node name="CollisionShape2D" type="CollisionShape2D" parent="ClickDetection"]
position = Vector2(-2, 10)
shape = SubResource("CapsuleShape2D_wr5vn")
[node name="DirectorDrone" type="Sprite2D" parent="."]
scale = Vector2(0.3, 0.3)
texture = ExtResource("2_8nbjk")
[node name="Shadow" type="Sprite2D" parent="."]
self_modulate = Color(0, 0, 0, 0.0784314)
position = Vector2(0, 100)
scale = Vector2(0.3, 0.1)
texture = ExtResource("2_8nbjk")
[node name="Polygon2D" type="Polygon2D" parent="."]
visible = false
position = Vector2(1, -1)
color = Color(0.703926, 0.656042, 0.441124, 1)
polygon = PackedVector2Array(-28, -25, 25, -28, 26, 33, -32, 19)
[node name="Label" type="Label" parent="."]
visible = false
offset_left = 16.0
offset_top = 25.0
offset_right = 56.0
offset_bottom = 48.0
theme_override_colors/font_color = Color(1, 1, 1, 1)
text = "9 "
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_xu26h")
}
autoplay = "Idle"
[connection signal="input_event" from="ClickDetection" to="." method="_on_click_detection_input_event"]
[connection signal="mouse_entered" from="ClickDetection" to="." method="_on_click_detection_mouse_entered"]
[connection signal="mouse_exited" from="ClickDetection" to="." method="_on_click_detection_mouse_exited"]

View file

@ -0,0 +1,95 @@
[gd_scene load_steps=6 format=3 uid="uid://ss2dg1i7j4ck"]
[ext_resource type="Script" path="res://entities/scripts/distractor_drone.gd" id="1_vnjar"]
[ext_resource type="Texture2D" uid="uid://cfufcbeeeg5oy" path="res://resources/textures/distractor_drone.png" id="2_dr1h4"]
[sub_resource type="Animation" id="Animation_wno6f"]
resource_name = "Idle"
length = 5.0
loop_mode = 1
step = 0.5
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("DistractorDrone:position:x")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 2.5, 5),
"transitions": PackedFloat32Array(-2, -2, -2),
"update": 0,
"values": [30.0, -30.0, 30.0]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("DistractorDrone:position:y")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 1, 2.5, 4, 5),
"transitions": PackedFloat32Array(-2, -2, 1, -2, -2),
"update": 0,
"values": [0.0, 30.0, 0.0, 40.0, 0.0]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("DistractorDrone:rotation")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 1, 2.5, 4, 5),
"transitions": PackedFloat32Array(-2, -2, -2, -2, -2),
"update": 0,
"values": [0.0, 0.0698132, -0.10472, 0.10472, 0.0]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("Shadow:position:x")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0, 2.5, 5),
"transitions": PackedFloat32Array(-2, -2, -2),
"update": 0,
"values": [30.0, -30.0, 30.0]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_lcuxq"]
_data = {
"Idle": SubResource("Animation_wno6f")
}
[sub_resource type="CircleShape2D" id="CircleShape2D_bxdlt"]
radius = 31.0161
[node name="DistractorDrone" type="CharacterBody2D" groups=["distractor"]]
script = ExtResource("1_vnjar")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_lcuxq")
}
autoplay = "Idle"
[node name="DroneShape" type="CollisionShape2D" parent="."]
shape = SubResource("CircleShape2D_bxdlt")
[node name="HitBox" type="Area2D" parent="."]
[node name="Shape" type="CollisionShape2D" parent="HitBox"]
shape = SubResource("CircleShape2D_bxdlt")
[node name="DistractorDrone" type="Sprite2D" parent="."]
position = Vector2(28.6279, 5.71726)
rotation = 0.0149678
scale = Vector2(0.2, 0.2)
texture = ExtResource("2_dr1h4")
[node name="Shadow" type="Sprite2D" parent="."]
modulate = Color(0, 0, 0, 0.0784314)
position = Vector2(28.6279, 100)
scale = Vector2(0.151346, 0.0434807)
texture = ExtResource("2_dr1h4")

172
entities/Dog.tscn Normal file
View file

@ -0,0 +1,172 @@
[gd_scene load_steps=11 format=3 uid="uid://cfhoi2rqxa3up"]
[ext_resource type="Script" path="res://scenes/scripts/dog.gd" id="1_26pvc"]
[ext_resource type="Texture2D" uid="uid://cqs2lfakkpqib" path="res://resources/textures/dog_body.png" id="2_mewoo"]
[ext_resource type="Texture2D" uid="uid://b22isfr66b8y2" path="res://resources/textures/dog_head.png" id="3_d7db6"]
[ext_resource type="Texture2D" uid="uid://bwxbit5i2x2ti" path="res://resources/textures/dog_tail.png" id="4_odrmk"]
[ext_resource type="Texture2D" uid="uid://dhf4dessaw5p5" path="res://resources/particles/twirl_01.png" id="5_dwvih"]
[sub_resource type="Animation" id="Animation_y6mxj"]
resource_name = "Idle"
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("DogSprite/DogTail:rotation")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.5, 1),
"transitions": PackedFloat32Array(-2, -2, -2),
"update": 0,
"values": [-0.10472, 0.10472, -0.10472]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("DogSprite/DogHead:rotation")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.4, 1),
"transitions": PackedFloat32Array(-2, -2, -2),
"update": 0,
"values": [0.0349066, -0.0349066, 0.0349066]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("DogSprite/DogBody:scale")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 0.6, 1),
"transitions": PackedFloat32Array(-2, -2, -2),
"update": 0,
"values": [Vector2(1, 1), Vector2(1.04, 1), Vector2(1, 1)]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("DogShadow/DogBody:scale")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0, 0.6, 1),
"transitions": PackedFloat32Array(-2, -2, -2),
"update": 0,
"values": [Vector2(1, 1), Vector2(1.04, 1), Vector2(1, 1)]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("DogShadow/DogTail:rotation")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0, 0.5, 1),
"transitions": PackedFloat32Array(-2, -2, -2),
"update": 0,
"values": [-0.10472, 0.10472, -0.10472]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_2ki86"]
_data = {
"Idle": SubResource("Animation_y6mxj")
}
[sub_resource type="Animation" id="Animation_ajt0l"]
resource_name = "Highlight"
length = 5.0
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("AreaHighlight:rotation")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 5),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [6.28319, 0.0]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_t7soo"]
_data = {
"Highlight": SubResource("Animation_ajt0l")
}
[sub_resource type="CircleShape2D" id="CircleShape2D_eyufl"]
radius = 191.83
[node name="Dog" type="Node2D" groups=["dog"]]
position = Vector2(-5, -1)
script = ExtResource("1_26pvc")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_2ki86")
}
autoplay = "Idle"
[node name="DogHighlightAnimation" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_t7soo")
}
autoplay = "Highlight"
[node name="DeathBox" type="Area2D" parent="."]
input_pickable = false
[node name="CollisionShape2D" type="CollisionShape2D" parent="DeathBox"]
shape = SubResource("CircleShape2D_eyufl")
[node name="DogShadow" type="Node2D" parent="."]
modulate = Color(0, 0, 0, 0.0392157)
position = Vector2(10, 10)
rotation = 1.5708
scale = Vector2(0.4, 0.4)
[node name="DogBody" type="Sprite2D" parent="DogShadow"]
scale = Vector2(1.03986, 1)
texture = ExtResource("2_mewoo")
[node name="DogHead" type="Sprite2D" parent="DogShadow"]
position = Vector2(12.5, -165)
rotation = 0.0349066
texture = ExtResource("3_d7db6")
offset = Vector2(-2.5, -75)
[node name="DogTail" type="Sprite2D" parent="DogShadow"]
position = Vector2(2.50001, 205)
rotation = 0.0818845
texture = ExtResource("4_odrmk")
offset = Vector2(2.5, 67.5)
[node name="DogSprite" type="Node2D" parent="."]
rotation = 1.5708
scale = Vector2(0.4, 0.4)
[node name="DogBody" type="Sprite2D" parent="DogSprite"]
scale = Vector2(1.03986, 1)
texture = ExtResource("2_mewoo")
[node name="DogHead" type="Sprite2D" parent="DogSprite"]
position = Vector2(12.5, -165)
rotation = -0.0166864
texture = ExtResource("3_d7db6")
offset = Vector2(-2.5, -75)
[node name="DogTail" type="Sprite2D" parent="DogSprite"]
position = Vector2(5, 182.5)
rotation = 0.0818845
texture = ExtResource("4_odrmk")
offset = Vector2(2.5, 67.5)
[node name="AreaHighlight" type="Sprite2D" parent="."]
visible = false
modulate = Color(1, 0.0980392, 0.160784, 0.345098)
rotation = 0.633674
scale = Vector2(0.8, 0.8)
texture = ExtResource("5_dwvih")

138
entities/Flowers.tscn Normal file
View file

@ -0,0 +1,138 @@
[gd_scene load_steps=9 format=3 uid="uid://bme541qdw7nai"]
[ext_resource type="Script" path="res://entities/scripts/flowers.gd" id="1_72iub"]
[ext_resource type="PackedScene" uid="uid://rnykx61eqxyk" path="res://scenes/decor/flower_1.tscn" id="1_biusc"]
[ext_resource type="PackedScene" uid="uid://b7quc1hxenh5p" path="res://scenes/decor/flower_2.tscn" id="2_k5hnf"]
[ext_resource type="Texture2D" uid="uid://dhf4dessaw5p5" path="res://resources/particles/twirl_01.png" id="3_xruiv"]
[ext_resource type="PackedScene" uid="uid://bnwvtlsvxjmel" path="res://entities/Snail.tscn" id="5_5uu7l"]
[sub_resource type="CircleShape2D" id="CircleShape2D_1tovu"]
radius = 142.316
[sub_resource type="Animation" id="Animation_41718"]
resource_name = "Highlight"
length = 5.0
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("AreaHighlight:rotation")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 5),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [6.28319, 0.0]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_qs4pr"]
_data = {
"Highlight": SubResource("Animation_41718")
}
[node name="Flowers" type="Node2D"]
script = ExtResource("1_72iub")
[node name="FlowerSprites" type="Node2D" parent="."]
[node name="Flower1" parent="FlowerSprites" instance=ExtResource("1_biusc")]
position = Vector2(-10, 41)
scale = Vector2(0.5, 0.5)
[node name="Flower4" parent="FlowerSprites" instance=ExtResource("1_biusc")]
position = Vector2(-50, -75)
scale = Vector2(0.5, 0.5)
[node name="Flower5" parent="FlowerSprites" instance=ExtResource("1_biusc")]
position = Vector2(-53, -4)
scale = Vector2(0.5, 0.5)
[node name="Flower6" parent="FlowerSprites" instance=ExtResource("1_biusc")]
position = Vector2(45, -69)
scale = Vector2(0.5, 0.5)
[node name="Flower14" parent="FlowerSprites" instance=ExtResource("1_biusc")]
position = Vector2(-99, -46)
scale = Vector2(0.5, 0.5)
[node name="Flower15" parent="FlowerSprites" instance=ExtResource("1_biusc")]
position = Vector2(100, -42)
scale = Vector2(0.5, 0.5)
[node name="Flower16" parent="FlowerSprites" instance=ExtResource("1_biusc")]
position = Vector2(117, 13)
scale = Vector2(0.5, 0.5)
[node name="Flower17" parent="FlowerSprites" instance=ExtResource("1_biusc")]
position = Vector2(71, 88)
scale = Vector2(0.5, 0.5)
[node name="Flower7" parent="FlowerSprites" instance=ExtResource("1_biusc")]
position = Vector2(64, 17)
scale = Vector2(0.5, 0.5)
[node name="Flower8" parent="FlowerSprites" instance=ExtResource("1_biusc")]
position = Vector2(-84, 60)
scale = Vector2(0.5, 0.5)
[node name="Flower9" parent="FlowerSprites" instance=ExtResource("1_biusc")]
position = Vector2(30, 68)
scale = Vector2(0.5, 0.5)
[node name="Flower10" parent="FlowerSprites" instance=ExtResource("1_biusc")]
position = Vector2(0, -61)
scale = Vector2(0.5, 0.5)
[node name="Flower11" parent="FlowerSprites" instance=ExtResource("1_biusc")]
position = Vector2(1, -123)
scale = Vector2(0.5, 0.5)
[node name="Flower12" parent="FlowerSprites" instance=ExtResource("1_biusc")]
position = Vector2(-68, 117)
scale = Vector2(0.5, 0.5)
[node name="Flower13" parent="FlowerSprites" instance=ExtResource("1_biusc")]
position = Vector2(13, 108)
scale = Vector2(0.5, 0.5)
[node name="Flower2" parent="FlowerSprites" instance=ExtResource("2_k5hnf")]
position = Vector2(-31, 83)
scale = Vector2(0.5, 0.5)
[node name="Flower3" parent="FlowerSprites" instance=ExtResource("2_k5hnf")]
position = Vector2(4, -16)
scale = Vector2(0.5, 0.5)
[node name="FlowerCollectionArea" type="Area2D" parent="." groups=["flowers"]]
position = Vector2(1, 2)
collision_layer = 7
collision_mask = 7
[node name="CollisionShape2D" type="CollisionShape2D" parent="FlowerCollectionArea"]
shape = SubResource("CircleShape2D_1tovu")
[node name="AreaHighlight" type="Sprite2D" parent="."]
visible = false
modulate = Color(1, 1, 0.160784, 0.345098)
rotation = 5.02655
scale = Vector2(0.6, 0.6)
texture = ExtResource("3_xruiv")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_qs4pr")
}
autoplay = "Highlight"
[node name="Snail" parent="." instance=ExtResource("5_5uu7l")]
[node name="HealthBar" type="ProgressBar" parent="."]
offset_left = -50.0
offset_top = 90.0
offset_right = 50.0
offset_bottom = 110.0
mouse_filter = 2
max_value = 10.0
step = 1.0
show_percentage = false

335
entities/Snail.tscn Normal file
View file

@ -0,0 +1,335 @@
[gd_scene load_steps=14 format=3 uid="uid://bnwvtlsvxjmel"]
[ext_resource type="Script" path="res://entities/scripts/snail.gd" id="1_lkvd1"]
[ext_resource type="Script" path="res://entities/scripts/finite_state_machine.gd" id="1_tejvt"]
[ext_resource type="Texture2D" uid="uid://dh8fo7865wgs" path="res://resources/textures/snail.png" id="2_yor00"]
[ext_resource type="Script" path="res://entities/snail/states/snail_sleeping.gd" id="3_wnrnl"]
[ext_resource type="Script" path="res://entities/snail/states/snail_eating.gd" id="4_1abwi"]
[ext_resource type="Texture2D" uid="uid://coqnsy2doe00a" path="res://resources/textures/z.png" id="5_owmpd"]
[ext_resource type="Texture2D" uid="uid://d30yqtob6phcj" path="res://resources/textures/snail_body.png" id="7_8spp3"]
[ext_resource type="Texture2D" uid="uid://5vt8eaihmut3" path="res://resources/textures/snail_shell.png" id="8_0v3d4"]
[sub_resource type="Animation" id="Animation_kpiuy"]
resource_name = "GoingToSleep"
length = 1.5
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite/SnailBody:scale")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.3, 1.5),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Vector2(1, 1), Vector2(0, 0), Vector2(0, 0)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite/SnailShell:rotation")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0.1, 1, 1.1, 1.2, 1.3, 1.4, 1.5),
"transitions": PackedFloat32Array(1, -2, 1, 1, 1, 1, 1),
"update": 0,
"values": [0.0, -6.28319, -6.10865, -6.28319, -6.10865, -6.28319, -6.28319]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite/SnailShell:position")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0.1, 0.6, 1, 1.5),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 0,
"values": [Vector2(0, 0), Vector2(0, -300), Vector2(0, 0), Vector2(0, 0)]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("Sprite/SnailBody:position")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0, 0.4, 0.6, 1.5),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 0,
"values": [Vector2(60, 30), Vector2(60, -300), Vector2(60, 30), Vector2(60, 30)]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("Sprite/ShadowEating:scale")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0, 0.3, 1.5),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Vector2(1.09451, 0.620219), Vector2(0, 0), Vector2(0, 0)]
}
tracks/5/type = "value"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("Sprite/ShadowShell:scale")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(0, 0.3, 1, 1.5),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 0,
"values": [Vector2(1.002, 0.3), Vector2(0.8, 0.3), Vector2(1.002, 0.3), Vector2(1.002, 0.3)]
}
tracks/6/type = "value"
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/path = NodePath("Sprite/ShadowShell:visible")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/keys = {
"times": PackedFloat32Array(0, 1.5),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [true, true]
}
[sub_resource type="Animation" id="Animation_w6m82"]
resource_name = "Move"
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite/SnailBody:scale")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.5, 1),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Vector2(1, 1), Vector2(1.08, 1), Vector2(1, 1)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite/SnailShell:rotation")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.5, 1),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [0.0, -0.0523599, 0.0]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite/SnailBody:visible")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 1),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [true, true]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("Sprite/ShadowEating:scale")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0, 0.5, 1),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Vector2(1, 1), Vector2(1.08, 1), Vector2(1, 1)]
}
[sub_resource type="Animation" id="Animation_oua3i"]
resource_name = "Sleep"
length = 4.0
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite/SnailBody:visible")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 4),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [false, false]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite/SnailShell:scale")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4),
"transitions": PackedFloat32Array(-2, -2, -2, -2, -2, -2, -2, -2, -2),
"update": 0,
"values": [Vector2(1, 1), Vector2(1.01, 1.01), Vector2(1, 1), Vector2(1.01, 1.01), Vector2(1, 1), Vector2(1.01, 1.01), Vector2(1, 1), Vector2(1.01, 1.01), Vector2(1, 1)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Z:visible")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 4),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [true, false]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("Z:modulate")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0, 0.2, 0.3, 1.2, 1.3, 4),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
"update": 0,
"values": [Color(1, 1, 1, 0), Color(1, 1, 1, 0), Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 0), Color(1, 1, 1, 0)]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("Z2:visible")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0, 4),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [true, false]
}
tracks/5/type = "value"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("Z2:modulate")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(0, 0.4, 0.5, 1.4, 1.5, 4),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
"update": 0,
"values": [Color(1, 1, 1, 0), Color(1, 1, 1, 0), Color(1, 1, 1, 1), Color(1, 1, 1, 0.885714), Color(1, 1, 1, 0), Color(1, 1, 1, 0)]
}
tracks/6/type = "value"
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/path = NodePath("Z3:visible")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/keys = {
"times": PackedFloat32Array(0, 4),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [true, false]
}
tracks/7/type = "value"
tracks/7/imported = false
tracks/7/enabled = true
tracks/7/path = NodePath("Z3:modulate")
tracks/7/interp = 1
tracks/7/loop_wrap = true
tracks/7/keys = {
"times": PackedFloat32Array(0, 0.6, 0.7, 1.7, 1.8, 4),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
"update": 0,
"values": [Color(1, 1, 1, 0), Color(1, 1, 1, 0), Color(1, 1, 1, 0.992157), Color(1, 1, 1, 1), Color(1, 1, 1, 0), Color(1, 1, 1, 0)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_6ntaf"]
_data = {
"GoingToSleep": SubResource("Animation_kpiuy"),
"Move": SubResource("Animation_w6m82"),
"Sleep": SubResource("Animation_oua3i")
}
[sub_resource type="CircleShape2D" id="CircleShape2D_2whjo"]
radius = 42.0476
[node name="Snail" type="CharacterBody2D"]
collision_layer = 8
collision_mask = 8
input_pickable = true
script = ExtResource("1_lkvd1")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_6ntaf")
}
autoplay = "Sleep"
[node name="Z" type="Sprite2D" parent="."]
position = Vector2(-17, -22)
scale = Vector2(0.1, 0.1)
texture = ExtResource("5_owmpd")
[node name="Z2" type="Sprite2D" parent="."]
modulate = Color(1, 1, 1, 0.936508)
position = Vector2(-12, -38)
rotation = 0.464258
scale = Vector2(0.11, 0.11)
texture = ExtResource("5_owmpd")
[node name="Z3" type="Sprite2D" parent="."]
modulate = Color(1, 1, 1, 0.99451)
position = Vector2(-30, -47)
rotation = -0.205949
scale = Vector2(0.13, 0.13)
texture = ExtResource("5_owmpd")
[node name="Sprite" type="Sprite2D" parent="."]
position = Vector2(-6, 0)
scale = Vector2(0.1, 0.1)
[node name="SnailBody" type="Sprite2D" parent="Sprite"]
visible = false
position = Vector2(60, 30)
scale = Vector2(1e-05, 1e-05)
texture = ExtResource("7_8spp3")
[node name="ShadowShell" type="Sprite2D" parent="Sprite"]
self_modulate = Color(0, 0, 0, 0.0784314)
position = Vector2(10, 130)
rotation = -0.00998773
scale = Vector2(1.002, 0.3)
texture = ExtResource("8_0v3d4")
[node name="SnailShell" type="Sprite2D" parent="Sprite"]
rotation = -6.28319
scale = Vector2(1, 1)
texture = ExtResource("8_0v3d4")
[node name="ShadowEating" type="Sprite2D" parent="Sprite"]
self_modulate = Color(0, 0, 0, 0.0784314)
show_behind_parent = true
position = Vector2(60, 20)
scale = Vector2(1e-05, 1e-05)
texture = ExtResource("2_yor00")
[node name="StateMachine" type="Node" parent="." node_paths=PackedStringArray("initial_state")]
script = ExtResource("1_tejvt")
initial_state = NodePath("Sleeping")
[node name="Sleeping" type="Node" parent="StateMachine"]
script = ExtResource("3_wnrnl")
[node name="Eating" type="Node" parent="StateMachine"]
script = ExtResource("4_1abwi")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
visible = false
shape = SubResource("CircleShape2D_2whjo")

View file

@ -0,0 +1,96 @@
[gd_scene load_steps=7 format=3 uid="uid://clomllso36j02"]
[ext_resource type="Script" path="res://entities/scripts/vegetable_patch.gd" id="1_0gto5"]
[ext_resource type="Texture2D" uid="uid://s673b25l7g3k" path="res://resources/textures/veg.png" id="1_xnay0"]
[ext_resource type="Texture2D" uid="uid://dn35q8nkyy8q2" path="res://resources/particles/light_03.png" id="2_og86v"]
[sub_resource type="Curve" id="Curve_j5a63"]
_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(1, 1), 1.4, 0.0, 0, 0]
point_count = 2
[sub_resource type="Gradient" id="Gradient_am1ne"]
offsets = PackedFloat32Array(0.789238, 1)
colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 0)
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_qfjud"]
radius = 85.57
height = 669.91
[node name="VegetablePatch" type="Node2D"]
script = ExtResource("1_0gto5")
[node name="Veg" type="Sprite2D" parent="."]
texture = ExtResource("1_xnay0")
offset = Vector2(1, 18)
[node name="Outline" type="Sprite2D" parent="Veg"]
visible = false
modulate = Color(0.882353, 0, 0, 1)
show_behind_parent = true
scale = Vector2(1.05, 1.025)
texture = ExtResource("1_xnay0")
offset = Vector2(1, 18)
[node name="PesticideClouds" type="Node2D" parent="."]
[node name="PesticideCloud_1" type="CPUParticles2D" parent="PesticideClouds"]
position = Vector2(2, -63)
amount = 6
lifetime = 3.0
texture = ExtResource("2_og86v")
emission_shape = 1
emission_sphere_radius = 20.0
gravity = Vector2(0, 0)
scale_amount_min = 0.1
scale_amount_max = 0.4
scale_amount_curve = SubResource("Curve_j5a63")
color = Color(0.94902, 0.184314, 0.27451, 0.27451)
color_ramp = SubResource("Gradient_am1ne")
[node name="PesticideCloud_2" type="CPUParticles2D" parent="PesticideClouds"]
position = Vector2(-1, -236)
amount = 6
lifetime = 3.0
texture = ExtResource("2_og86v")
emission_shape = 1
emission_sphere_radius = 20.0
gravity = Vector2(0, 0)
scale_amount_min = 0.1
scale_amount_max = 0.4
scale_amount_curve = SubResource("Curve_j5a63")
color = Color(0.94902, 0.184314, 0.27451, 0.27451)
color_ramp = SubResource("Gradient_am1ne")
[node name="PesticideCloud_3" type="CPUParticles2D" parent="PesticideClouds"]
position = Vector2(2, 110)
amount = 6
lifetime = 3.0
texture = ExtResource("2_og86v")
emission_shape = 1
emission_sphere_radius = 20.0
gravity = Vector2(0, 0)
scale_amount_min = 0.1
scale_amount_max = 0.4
scale_amount_curve = SubResource("Curve_j5a63")
color = Color(0.94902, 0.184314, 0.27451, 0.27451)
color_ramp = SubResource("Gradient_am1ne")
[node name="PesticideCloud_4" type="CPUParticles2D" parent="PesticideClouds"]
position = Vector2(6, 269)
amount = 6
lifetime = 3.0
texture = ExtResource("2_og86v")
emission_shape = 1
emission_sphere_radius = 20.0
gravity = Vector2(0, 0)
scale_amount_min = 0.1
scale_amount_max = 0.4
scale_amount_curve = SubResource("Curve_j5a63")
color = Color(0.94902, 0.184314, 0.27451, 0.27451)
color_ramp = SubResource("Gradient_am1ne")
[node name="DeathBox" type="Area2D" parent="."]
[node name="CollisionShape2D" type="CollisionShape2D" parent="DeathBox"]
position = Vector2(2, 14)
shape = SubResource("CapsuleShape2D_qfjud")

View file

@ -0,0 +1,16 @@
extends State
class_name BeeDeath
@onready var bee : Bee = get_parent().get_parent() as Bee
func enter(_msg : Dictionary = {}) -> void:
GameState.bee_died()
bee.bee_position_animation.play("Death")
bee.bee_wing_animation.stop()
func update(_delta : float) -> void:
pass
func physics_update(_delta : float) -> void:
pass

View file

@ -0,0 +1,36 @@
extends State
class_name BeeGathering
@export var animator : AnimationPlayer
@onready var bee : Bee= get_parent().get_parent() as Bee # I think this is bad but I dont care it works
var time_at_patch : float = 0.0
var target : Vector2 = Vector2.ZERO
func enter(_msg : Dictionary = {}) -> void:
bee.just_gathering = true
Log.pr("Gathering now...")
randomize()
target = bee.get_global_position() + Vector2(randi_range(-100, 100), randi_range(-100, 100))
func update(_delta : float) -> void:
if bee.in_range_of_flowers:
#animator.play("Gathering")
time_at_patch += _delta
if time_at_patch > 5.0:
Log.pr("Gathered nectar!")
bee.nectar += GameState.flower_nectar_level # Add nectar to the bee based on current flower nectar level
state_transition.emit(self, "Idle")
else:
state_transition.emit(self, "Idle")
func physics_update(delta : float) -> void:
if target:
if bee.position.distance_to(target) > 2:
bee.velocity = (target - bee.position).normalized() * bee.speed / 2 * delta
bee.move_and_collide(bee.velocity)
bee.bee_body.look_at(target)

View file

@ -0,0 +1,50 @@
extends State
class_name BeeIdle
@onready var bee : Bee = get_parent().get_parent() as Bee # I think this is bad but I dont care it works
var idle_time : float = 0.0
var target : Vector2 = Vector2.ZERO
var acquire_new_target : bool = false
func enter(_msg : Dictionary = {}) -> void:
if acquire_new_target:
target = bee.get_global_position() + Vector2(randi_range(-60, 60), randi_range(-60, 60))
func exit() -> void:
acquire_new_target = true
func update(delta : float) -> void:
if target == Vector2.ZERO:
randomize()
target = bee.get_global_position() + Vector2(randi_range(-60, 60), randi_range(-60, 60))
idle_time += delta
if idle_time > 2.0:
find_something_to_do()
idle_time = 0.0
pass
func physics_update(delta : float) -> void:
if target:
if bee.position.distance_to(target) > 3:
bee.velocity = (target - bee.position).normalized() * bee.speed / 2 * delta
bee.move_and_collide(bee.velocity)
bee.bee_body.look_at(target)
func find_something_to_do() -> void:
if bee.nectar > 0:
Log.pr("I have pollen, time to move..")
## Bee has pollen - head home
state_transition.emit(self, "Travelling")
else:
## Bee has no pollen - they should move to a flower
state_transition.emit(self, "Travelling")
pass

View file

@ -0,0 +1,26 @@
extends State
class_name BeeReturning
@onready var bee : Bee = get_parent().get_parent() as Bee # I think this is bad but I dont care it works
@onready var target : Beehive = get_tree().get_first_node_in_group("beehive")
func enter(_msg : Dictionary = {}) -> void:
Log.pr("Returning to the hive")
bee.bee_position_animation.play("Flying")
func update(_delta : float) -> void:
pass
func physics_update(delta : float) -> void:
if target:
if bee.position.distance_to(target.position) > 3:
bee.velocity = (target.get_global_position() - bee.position).normalized() * bee.speed * delta
bee.move_and_collide(bee.velocity)
bee.bee_body.look_at(target.position)
else:
# Deposit the nectar and return it idle state
bee.deposit_nectar()
state_transition.emit(self, "Idle")

View file

@ -0,0 +1,15 @@
extends State
class_name BeeSleeping
@onready var bee : Bee = get_parent().get_parent() as Bee # I think this is bad but I dont care it works
var time_at_patch : float = 0.0
func enter(_msg : Dictionary = {}) -> void:
pass
func update(_delta : float) -> void:
pass
func physics_update(_delta : float) -> void:
pass

View file

@ -0,0 +1,52 @@
extends State
class_name BeeTravelling
@export var target : Drone = null
@onready var bee : Bee = get_parent().get_parent() as Bee # I think this is bad but I dont care it works
var return_to_hive : bool = false
var moving_to : Vector2 = Vector2(0,0)
func enter(_msg : Dictionary = {}) -> void:
return_to_hive = false
## Get the next target location from the bee
if bee.just_gathering:
target = bee.get_current_director() # We want to go back the way we came
if !target:
Log.pr("No director around, returning to hive")
## If there is no other director, just go straight back home
state_transition.emit(self, "Returning")
bee.just_gathering = false
else:
target = bee.get_next_target()
# If we have no target, we are returning to the hive
if !target:
return_to_hive = true
else:
moving_to = target.get_global_position()
bee.bee_position_animation.play("Flying")
func update(_delta : float) -> void:
if return_to_hive:
state_transition.emit(self, "Returning")
return
func physics_update(delta : float) -> void:
if target:
if bee.position.distance_to(target.position) > 3:
bee.velocity = (moving_to - bee.position).normalized() * bee.speed * delta
bee.move_and_collide(bee.velocity)
bee.bee_body.look_at(target.position)
else:
# Bee has arrived at location, if its the hive or a collector drone do the things
if(target.name == "CollectorDrone"):
state_transition.emit(self, "Gathering")
else:
state_transition.emit(self, "Idle")

75
entities/scripts/bee.gd Normal file
View file

@ -0,0 +1,75 @@
extends Node2D
class_name Bee
@onready var fsm : FiniteStateMachine = $StateMachine as FiniteStateMachine
@onready var drone_manager : DroneManager = get_tree().get_first_node_in_group("dronemanager") as DroneManager
@onready var bee_position_animation : AnimationPlayer = $BeePositionAnimation as AnimationPlayer
@onready var bee_wing_animation : AnimationPlayer = $WingAnimation as AnimationPlayer
@onready var bee_body : Sprite2D = $BeeBody as Sprite2D
@onready var impact_cloud : CPUParticles2D = $ImpactCloud
@export var nectar : int = 0
@export var speed : int = 30
var latest_target_director : int = 0
# This is updated when the bee enters or exits a flower patch
var in_range_of_flowers : bool = false
var just_gathering : bool = false # Used to check if the bee has just been gathering to return to their previous director
func _ready() -> void:
modulate = Color(1,1,1,1)
impact_cloud.visible = false
speed = randi_range(35,55) # Randomise the bee speed a bit
bee_wing_animation.play("Fly")
func get_current_director() -> DirectorDrone:
return drone_manager.get_director(latest_target_director)
## Get the next target to move to
## If we have no nectar, we need to go up the director list
## If we have nectar, we need to go down the director list
## If we are at the lower director, we need to go the hive
## If we are at the highest director, we need to go to a flower
func get_next_target() -> Drone:
if nectar == 0:
Log.pr("No nectar!")
## If there is a next directory drone, lets go to it
var next_drone : DirectorDrone = drone_manager.get_next_director(latest_target_director)
if next_drone:
latest_target_director = next_drone.visit_order
return next_drone
## If there is no next drone, check for a collector drone
var collector_drone : CollectorDrone = drone_manager.get_collector()
if collector_drone:
return collector_drone
else:
## Let's go home, we need the previous director drones location
var previous_drone : DirectorDrone = drone_manager.get_previous_director(latest_target_director)
if previous_drone:
Log.pr("Previous drone", previous_drone)
latest_target_director = previous_drone.visit_order
return previous_drone
else:
Log.pr("No previous drone")
return null
return null
func deposit_nectar() -> void:
if nectar > 0:
GameState.add_nectar(nectar)
nectar = 0
latest_target_director = 0
just_gathering = false
func die() -> void:
# Move to the death state
fsm.force_change_state("Death")

View file

@ -0,0 +1,13 @@
extends Area2D
@onready var bee : Bee = get_parent() as Bee
func _on_area_entered(area : Area2D) -> void:
## Check if the area entered is a flower patch
if area.is_in_group("flowers"):
bee.in_range_of_flowers = true
func _on_area_exited(area : Area2D) -> void:
## Check if the area exited is a flower patch
if area.is_in_group("flowers"):
bee.in_range_of_flowers = false

View file

@ -0,0 +1,20 @@
extends Node2D
class_name Beehive
var dancer_in_range : bool = false
@onready var outline : Sprite2D = $AreaHighlight
func show_outline() -> void:
outline.visible = true
func hide_outline() -> void:
outline.visible = false
func _on_area_2d_area_entered(area : Area2D) -> void:
if area.is_in_group("dancer"):
dancer_in_range = true
func _on_area_2d_area_exited(area : Area2D) -> void:
if area.is_in_group("dancer"):
dancer_in_range = false

View file

@ -0,0 +1 @@
class_name CollectorDrone extends Drone

View file

@ -0,0 +1 @@
class_name DancerDrone extends Drone

View file

@ -0,0 +1,35 @@
class_name DirectorDrone extends Drone
@onready var label : Label = get_node("Label")
@export var visit_order : int = 0 :
get:
return visit_order
set(value):
visit_order = value
update_label_value()
func update_label_value() -> void:
$Label.text = str(visit_order)
func _on_click_detection_mouse_entered() -> void:
if GameState.placing_drone == false:
Log.pr("Mouse entered the director drone!")
label.visible = true
CursorMgr.edit()
func _on_click_detection_mouse_exited() -> void:
if GameState.placing_drone == false:
Log.pr("Mouse exited the director drone!")
label.visible = false
CursorMgr.reset_cursor()
func _on_click_detection_input_event(_viewport:Node, event:InputEvent, _shape_idx:int) -> void:
if GameState.placing_drone == false:
if (event is InputEventMouseButton && event.button_index == MOUSE_BUTTON_RIGHT && event.pressed):
CursorMgr.reset_cursor()
queue_free()
get_parent().get_parent().update_director_drone_list()

View file

@ -0,0 +1 @@
class_name DistractorDrone extends Drone

View file

@ -0,0 +1 @@
class_name Drone extends Node2D

View file

@ -0,0 +1,76 @@
@icon("res://resources/icons/fsm.png")
extends Node
class_name FiniteStateMachine
var states : Dictionary = {}
var current_state : State
@export var initial_state : State
#NOTE This is a generic finite_state_machine, it handles all states, changes to this code will affect
# everything that uses a state machine!
func _ready() -> void:
for child : Node in get_children():
if child is State:
states[child.name.to_lower()] = child
child.state_transition.connect(change_state)
if initial_state:
initial_state.enter()
current_state = initial_state
# Call the current states update function
func _process(delta : float) -> void:
if current_state:
current_state.update(delta)
func _physics_process(delta : float) -> void:
if current_state:
current_state.physics_update(delta)
func get_current_state_name() -> String:
if current_state:
return current_state.name.to_lower()
else:
return ""
# Use force_change_state cautiously, it immediately switches to a state regardless of any transitions.
# This is used to force us into a 'death state' when killed
func force_change_state(new_state : String) -> void:
var newState : State = states.get(new_state.to_lower())
if !newState:
print(new_state + " does not exist in the dictionary of states")
return
if current_state == newState:
print("State is same, aborting")
return
# NOTE Calling exit like so: (current_state.Exit()) may cause warnings when flushing queries, like when the enemy is being removed after death.
# call_deferred is safe and prevents this from occuring. We get the Exit function from the state as a callable and then call it in a thread-safe manner
if current_state:
var exit_callable : Callable = Callable(current_state, "exit")
exit_callable.call_deferred()
newState.enter()
current_state = newState
func change_state(source_state : State, new_state_name : String) -> void:
if source_state != current_state:
#print("Invalid change_state trying from: " + source_state.name + " but currently in: " + current_state.name)
#This typically only happens when trying to switch from death state following a force_change
return
var new_state : State = states.get(new_state_name.to_lower())
if !new_state:
print("New state is empty")
return
if current_state:
current_state.exit()
new_state.enter()
current_state = new_state

View file

@ -0,0 +1,70 @@
extends Node2D
class_name Flowers
@onready var outline : Sprite2D = $AreaHighlight
@export var health : int = 100
var spawn_snails : bool = false
@onready var spawn_area : CollisionShape2D = $FlowerCollectionArea/CollisionShape2D
@onready var snail : Snail = $Snail
var last_health_check : float = 0
var health_check_timer : float = 0.5
@onready var health_bar : ProgressBar = $HealthBar
func _ready() -> void:
hide_outline()
setup_healthbar()
## Check if this level is spawning snails or not
if GameState.spawn_snails:
Log.pr("Going to be spawning snails!")
spawn_snails = true
Log.pr(get_random_circumference_points())
snail.global_position = get_random_circumference_points()
func _process(delta: float) -> void:
update_healthbar(delta)
func show_outline() -> void:
outline.visible = true
func hide_outline() -> void:
outline.visible = false
func get_random_circumference_points() -> Vector2:
var circle_radius : float = spawn_area.shape.radius
var random_angle : float = randf_range(0, TAU)
var x : float = circle_radius * cos(random_angle)
var y : float = circle_radius * sin(random_angle)
var circle_center : Vector2 = spawn_area.global_position
var random_point : Vector2 = circle_center + Vector2(x, y)
return random_point
## Initial setup of the health bar - updating the values
# and hiding it from view.
func setup_healthbar() -> void:
health_bar.max_value = GameState.max_flower_nectar_level
health_bar.value = GameState.flower_nectar_level
health_bar.visible = false
## Update the health bar based on the current GameState values
# and display it if required. Conversely, hide it if the flower is at max powah.
func update_healthbar(delta : float) -> void:
last_health_check += delta
if last_health_check >= health_check_timer:
last_health_check = 0
if GameState.flower_nectar_level < GameState.max_flower_nectar_level:
health_bar.value = GameState.flower_nectar_level
health_bar.visible = true
else:
health_bar.value = GameState.max_flower_nectar_level
health_bar.visible = false

59
entities/scripts/snail.gd Normal file
View file

@ -0,0 +1,59 @@
extends CharacterBody2D
class_name Snail
@onready var fsm : FiniteStateMachine = $StateMachine as FiniteStateMachine
@onready var flowers : Flowers = get_parent()
@onready var sprite : Sprite2D = $Sprite
@onready var animation : AnimationPlayer = $AnimationPlayer
var enabled : bool = false
var eating : bool = false
var speed : float = 20.0
var mouse_over : bool = false
func _ready() -> void:
connect("mouse_entered", Callable(self, "on_mouse_entered"))
connect("mouse_exited", Callable(self, "on_mouse_exited"))
animation.connect("animation_finished", Callable(self, "on_animation_finished"))
# Detect mouse left click and trigger function
func _input(event : InputEvent) -> void:
if mouse_over:
if event is InputEventMouseButton:
if (event is InputEventMouseButton && event.button_index == MOUSE_BUTTON_LEFT && event.pressed):
maybe_sleep()
func eat() -> void:
# Play the munch animation and noise
# Reduce the GameState flower_nectar_level
GameState.flower_nectar_level -= 1
func hide_zeds() -> void:
$Z.hide()
$Z2.hide()
$Z3.hide()
$Sprite/ShadowShell.hide()
func maybe_sleep() -> void:
# If the snail is still eating, then we want a 30% chance of switching it it to the sleeping state
if eating:
if randf() < 0.3:
if fsm.get_current_state_name() == "eating":
fsm.change_state(fsm.current_state, "sleeping")
func get_random_target() -> Vector2:
return flowers.get_random_circumference_points()
func on_mouse_entered() -> void:
CursorMgr.hand()
mouse_over = true
func on_mouse_exited() -> void:
# Reset the cursor to the default
mouse_over = false
CursorMgr.reset_cursor()
func on_animation_finished(anim_name : StringName) -> void:
if anim_name == "GoingToSleep":
animation.play("Sleep")

15
entities/scripts/state.gd Normal file
View file

@ -0,0 +1,15 @@
@icon("res://resources/icons/fsm.png")
extends Node
class_name State
signal state_transition
func enter(_msg : Dictionary = {}) -> void:
pass
func exit() -> void :
pass
func update(_delta : float) -> void:
pass

View file

@ -0,0 +1,12 @@
extends Node2D
class_name VegetablePatch
@onready var death_box : Area2D = $DeathBox
func _ready() -> void:
death_box.connect("body_entered", Callable(self, "_on_body_entered"))
func _on_body_entered(area : Bee) -> void:
if area.is_in_group("bee"):
area.die()

View file

@ -0,0 +1,51 @@
extends State
class_name SnailEating
@onready var snail : Snail = get_parent().get_parent() as Snail # I think this is bad but I dont care it works
var eat_interval : float = 3.0
var eat_timer : float = 0.0
var move_to : Vector2 = Vector2.ZERO
var original_snail_scale : float = 0.1
func enter(_msg : Dictionary = {}) -> void:
Log.pr("I am a snail and I will eat!")
snail.eating = true
if snail.animation:
snail.animation.play("Move")
snail.hide_zeds()
func exit() -> void:
snail.eating = false
snail.sprite.flip_h = false
func update(delta : float) -> void:
eat_timer += delta
if eat_timer >= eat_interval:
snail.eat()
eat_timer = 0.0
func physics_update(_delta : float) -> void:
if move_to == Vector2.ZERO:
move_to = snail.get_random_target()
if snail.global_position.distance_to(move_to) > 3:
snail.velocity = snail.global_position.direction_to(move_to) * snail.speed
if move_to.x > snail.global_position.x:
snail.sprite.scale.x = original_snail_scale
else:
snail.sprite.scale.x = -original_snail_scale
snail.move_and_slide()
else:
move_to = Vector2.ZERO

View file

@ -0,0 +1,34 @@
extends State
class_name SnailSleeping
@onready var snail : Snail = get_parent().get_parent() as Snail # I think this is bad but I dont care it works
var wakes_up_in : float = 0
var sleep_timer : float = 0
func enter(_msg : Dictionary = {}) -> void:
Log.pr("I am a snail asleep...")
snail.rotation = 0
if snail.animation:
snail.animation.play("GoingToSleep")
CursorMgr.reset_cursor()
# Decide how many seconds until the snail wakes up again
wakes_up_in = randf_range(15.0, 25.0)
sleep_timer = 0
func exit() -> void:
pass
func update(delta : float) -> void:
if GameState.level_started:
sleep_timer += delta
# Snail will only wake up if the level has started
if sleep_timer > wakes_up_in:
state_transition.emit(self, "Eating")
func physics_update(_delta : float) -> void:
pass

140
export_presets.cfg Normal file
View file

@ -0,0 +1,140 @@
[preset.0]
name="Web"
platform="Web"
runnable=true
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="build/web/index.html"
encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
[preset.0.options]
custom_template/debug=""
custom_template/release=""
variant/extensions_support=false
vram_texture_compression/for_desktop=true
vram_texture_compression/for_mobile=false
html/export_icon=true
html/custom_html_shell=""
html/head_include=""
html/canvas_resize_policy=2
html/focus_canvas_on_start=true
html/experimental_virtual_keyboard=false
progressive_web_app/enabled=false
progressive_web_app/offline_page=""
progressive_web_app/display=1
progressive_web_app/orientation=0
progressive_web_app/icon_144x144=""
progressive_web_app/icon_180x180=""
progressive_web_app/icon_512x512=""
progressive_web_app/background_color=Color(0, 0, 0, 1)
[preset.1]
name="Windows Desktop"
platform="Windows Desktop"
runnable=true
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="build/windows/Pollen Not Included.exe"
encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
[preset.1.options]
custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=0
binary_format/embed_pck=false
texture_format/bptc=true
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false
binary_format/architecture="x86_64"
codesign/enable=false
codesign/timestamp=true
codesign/timestamp_server_url=""
codesign/digest_algorithm=1
codesign/description=""
codesign/custom_options=PackedStringArray()
application/modify_resources=true
application/icon="res://resources/icons/gameicon.png"
application/console_wrapper_icon=""
application/icon_interpolation=4
application/file_version=""
application/product_version=""
application/company_name="Happy Little Robots"
application/product_name="Pollen Not Included"
application/file_description=""
application/copyright=""
application/trademarks=""
application/export_angle=0
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
ssh_remote_deploy/port="22"
ssh_remote_deploy/extra_args_ssh=""
ssh_remote_deploy/extra_args_scp=""
ssh_remote_deploy/run_script="Expand-Archive -LiteralPath '{temp_dir}\\{archive_name}' -DestinationPath '{temp_dir}'
$action = New-ScheduledTaskAction -Execute '{temp_dir}\\{exe_name}' -Argument '{cmd_args}'
$trigger = New-ScheduledTaskTrigger -Once -At 00:00
$settings = New-ScheduledTaskSettingsSet
$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings
Register-ScheduledTask godot_remote_debug -InputObject $task -Force:$true
Start-ScheduledTask -TaskName godot_remote_debug
while (Get-ScheduledTask -TaskName godot_remote_debug | ? State -eq running) { Start-Sleep -Milliseconds 100 }
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue"
ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue
Remove-Item -Recurse -Force '{temp_dir}'"
[preset.2]
name="Linux/X11"
platform="Linux/X11"
runnable=true
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="build/linux/PollenNotIncluded.x86_64"
encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
[preset.2.options]
custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=1
binary_format/embed_pck=false
texture_format/bptc=true
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false
binary_format/architecture="x86_64"
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
ssh_remote_deploy/port="22"
ssh_remote_deploy/extra_args_ssh=""
ssh_remote_deploy/extra_args_scp=""
ssh_remote_deploy/run_script="#!/usr/bin/env bash
export DISPLAY=:0
unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"
\"{temp_dir}/{exe_name}\" {cmd_args}"
ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash
kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\")
rm -rf \"{temp_dir}\""

158
levels/level_1.tscn Normal file
View file

@ -0,0 +1,158 @@
[gd_scene load_steps=16 format=3 uid="uid://dalh10tit6qg"]
[ext_resource type="PackedScene" uid="uid://dn6aa6f2f4g4i" path="res://components/RulesComponent.tscn" id="1_g1iu7"]
[ext_resource type="Script" path="res://levels/scripts/level_1.gd" id="1_jrhhc"]
[ext_resource type="Resource" uid="uid://byyectcdb7e14" path="res://levels/rules/level_1_rules.tres" id="2_osic7"]
[ext_resource type="PackedScene" uid="uid://d1uawawum16b0" path="res://scenes/elements/background.tscn" id="3_8a85u"]
[ext_resource type="PackedScene" uid="uid://dwuc6byusf1r3" path="res://scenes/decor/bush.tscn" id="4_f1siw"]
[ext_resource type="PackedScene" uid="uid://dj51rgpihnhi" path="res://scenes/decor/naked_tree.tscn" id="5_mset6"]
[ext_resource type="PackedScene" uid="uid://d3mas42mbgec1" path="res://scenes/decor/tree.tscn" id="6_7gdup"]
[ext_resource type="PackedScene" uid="uid://eiyribk1ijcu" path="res://scenes/decor/mushroom.tscn" id="7_hxhav"]
[ext_resource type="PackedScene" uid="uid://bme541qdw7nai" path="res://entities/Flowers.tscn" id="8_yg6w2"]
[ext_resource type="PackedScene" uid="uid://dyu4mucawjlu6" path="res://entities/Beehive.tscn" id="9_7gmgu"]
[ext_resource type="PackedScene" uid="uid://ddf2mkkw1trkj" path="res://scenes/elements/bee_spawner.tscn" id="10_yjc17"]
[ext_resource type="PackedScene" uid="uid://b7eeptlk47ymd" path="res://ui/UiComponent.tscn" id="11_ndtvv"]
[ext_resource type="PackedScene" uid="uid://ct3c16xm33r2a" path="res://scenes/elements/drone_manager.tscn" id="12_37aah"]
[ext_resource type="PackedScene" uid="uid://cwutwy11pityw" path="res://ui/LevelCompleteComponent.tscn" id="13_we755"]
[ext_resource type="PackedScene" uid="uid://b5whit1dshr3" path="res://ui/GameOverComponent.tscn" id="15_jn0bj"]
[node name="Level1" type="Node2D"]
script = ExtResource("1_jrhhc")
[node name="RulesComponent" parent="." instance=ExtResource("1_g1iu7")]
unique_name_in_owner = true
game_rules = ExtResource("2_osic7")
[node name="Grass" parent="." instance=ExtResource("3_8a85u")]
[node name="LevelDecor" type="Node" parent="."]
[node name="BushGroup" type="Node2D" parent="LevelDecor"]
[node name="Bush" parent="LevelDecor/BushGroup" instance=ExtResource("4_f1siw")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup" instance=ExtResource("4_f1siw")]
position = Vector2(1272, 123)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup" instance=ExtResource("4_f1siw")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="BushGroup3" type="Node2D" parent="LevelDecor"]
position = Vector2(-928, 592)
scale = Vector2(0.75, 0.75)
[node name="Bush" parent="LevelDecor/BushGroup3" instance=ExtResource("4_f1siw")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup3" instance=ExtResource("4_f1siw")]
position = Vector2(1272, 123)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup3" instance=ExtResource("4_f1siw")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="BushGroup2" type="Node2D" parent="LevelDecor"]
position = Vector2(456, 1669)
rotation = 5.29882
[node name="Bush" parent="LevelDecor/BushGroup2" instance=ExtResource("4_f1siw")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup2" instance=ExtResource("4_f1siw")]
position = Vector2(1272, 123)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup2" instance=ExtResource("4_f1siw")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="NakedTree" parent="LevelDecor" instance=ExtResource("5_mset6")]
position = Vector2(53, 336)
scale = Vector2(0.6, 0.6)
[node name="Tree" parent="LevelDecor" instance=ExtResource("6_7gdup")]
position = Vector2(119, 100)
scale = Vector2(0.6, 0.6)
[node name="Tree2" parent="LevelDecor" instance=ExtResource("6_7gdup")]
position = Vector2(64, 473)
rotation = -0.42237
scale = Vector2(0.4, 0.4)
[node name="Mushrooms" type="Node2D" parent="LevelDecor"]
[node name="Mushroom" parent="LevelDecor/Mushrooms" instance=ExtResource("7_hxhav")]
position = Vector2(232, 250)
scale = Vector2(0.5, 0.5)
[node name="Mushroom2" parent="LevelDecor/Mushrooms" instance=ExtResource("7_hxhav")]
position = Vector2(252, 289)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Mushroom3" parent="LevelDecor/Mushrooms" instance=ExtResource("7_hxhav")]
position = Vector2(260, 225)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Mushrooms2" type="Node2D" parent="LevelDecor"]
position = Vector2(1553, 732)
rotation = 2.81347
[node name="Mushroom" parent="LevelDecor/Mushrooms2" instance=ExtResource("7_hxhav")]
position = Vector2(232, 250)
scale = Vector2(0.5, 0.5)
[node name="Mushroom2" parent="LevelDecor/Mushrooms2" instance=ExtResource("7_hxhav")]
position = Vector2(252, 289)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Mushroom3" parent="LevelDecor/Mushrooms2" instance=ExtResource("7_hxhav")]
position = Vector2(260, 225)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Flowers" parent="." instance=ExtResource("8_yg6w2")]
unique_name_in_owner = true
position = Vector2(1054, 350)
[node name="Beehive" parent="." groups=["beehive"] instance=ExtResource("9_7gmgu")]
unique_name_in_owner = true
position = Vector2(629, 360)
[node name="BeeSpawner" parent="." instance=ExtResource("10_yjc17")]
unique_name_in_owner = true
[node name="UiComponent" parent="." instance=ExtResource("11_ndtvv")]
unique_name_in_owner = true
z_index = 999
offset_right = 1280.0
offset_bottom = 720.0
mouse_filter = 1
[node name="DroneManager" parent="." instance=ExtResource("12_37aah")]
unique_name_in_owner = true
[node name="LevelCompleteComponent" parent="." instance=ExtResource("13_we755")]
visible = false
z_index = 1000
offset_right = 1280.0
offset_bottom = 720.0
mouse_filter = 1
[node name="GameOverComponent" parent="." instance=ExtResource("15_jn0bj")]
visible = false
z_index = 900
offset_right = 1280.0
offset_bottom = 720.0

162
levels/level_2.tscn Normal file
View file

@ -0,0 +1,162 @@
[gd_scene load_steps=17 format=3 uid="uid://dcgmtmjsrtafq"]
[ext_resource type="Script" path="res://levels/scripts/level_2.gd" id="1_dtbi3"]
[ext_resource type="PackedScene" uid="uid://dn6aa6f2f4g4i" path="res://components/RulesComponent.tscn" id="2_gln7y"]
[ext_resource type="Resource" uid="uid://cqtsmjsyqne41" path="res://levels/rules/level_2_rules.tres" id="3_58a2h"]
[ext_resource type="PackedScene" uid="uid://d1uawawum16b0" path="res://scenes/elements/background.tscn" id="4_tliaa"]
[ext_resource type="PackedScene" uid="uid://dwuc6byusf1r3" path="res://scenes/decor/bush.tscn" id="5_rr770"]
[ext_resource type="PackedScene" uid="uid://dj51rgpihnhi" path="res://scenes/decor/naked_tree.tscn" id="6_rjinx"]
[ext_resource type="PackedScene" uid="uid://d3mas42mbgec1" path="res://scenes/decor/tree.tscn" id="7_cvl7f"]
[ext_resource type="PackedScene" uid="uid://eiyribk1ijcu" path="res://scenes/decor/mushroom.tscn" id="8_8v50e"]
[ext_resource type="PackedScene" uid="uid://bme541qdw7nai" path="res://entities/Flowers.tscn" id="9_4jnhv"]
[ext_resource type="PackedScene" uid="uid://clomllso36j02" path="res://entities/VegetablePatch.tscn" id="10_1x4lm"]
[ext_resource type="PackedScene" uid="uid://dyu4mucawjlu6" path="res://entities/Beehive.tscn" id="10_6ye1u"]
[ext_resource type="PackedScene" uid="uid://ddf2mkkw1trkj" path="res://scenes/elements/bee_spawner.tscn" id="11_gkdx0"]
[ext_resource type="PackedScene" uid="uid://b7eeptlk47ymd" path="res://ui/UiComponent.tscn" id="12_mmtyl"]
[ext_resource type="PackedScene" uid="uid://ct3c16xm33r2a" path="res://scenes/elements/drone_manager.tscn" id="13_pibpn"]
[ext_resource type="PackedScene" uid="uid://cwutwy11pityw" path="res://ui/LevelCompleteComponent.tscn" id="14_uyhgj"]
[ext_resource type="PackedScene" uid="uid://b5whit1dshr3" path="res://ui/GameOverComponent.tscn" id="16_450js"]
[node name="Level2" type="Node2D"]
script = ExtResource("1_dtbi3")
[node name="RulesComponent" parent="." instance=ExtResource("2_gln7y")]
unique_name_in_owner = true
game_rules = ExtResource("3_58a2h")
[node name="Grass" parent="." instance=ExtResource("4_tliaa")]
[node name="LevelDecor" type="Node" parent="."]
[node name="BushGroup" type="Node2D" parent="LevelDecor"]
[node name="Bush" parent="LevelDecor/BushGroup" instance=ExtResource("5_rr770")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup" instance=ExtResource("5_rr770")]
position = Vector2(1272, 123)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup" instance=ExtResource("5_rr770")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="BushGroup3" type="Node2D" parent="LevelDecor"]
position = Vector2(-928, 592)
scale = Vector2(0.75, 0.75)
[node name="Bush" parent="LevelDecor/BushGroup3" instance=ExtResource("5_rr770")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup3" instance=ExtResource("5_rr770")]
position = Vector2(1272, 123)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup3" instance=ExtResource("5_rr770")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="BushGroup2" type="Node2D" parent="LevelDecor"]
position = Vector2(1291, 1886)
rotation = 4.5012
[node name="Bush" parent="LevelDecor/BushGroup2" instance=ExtResource("5_rr770")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup2" instance=ExtResource("5_rr770")]
position = Vector2(1272, 123)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup2" instance=ExtResource("5_rr770")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="NakedTree" parent="LevelDecor" instance=ExtResource("6_rjinx")]
position = Vector2(-41, 437)
scale = Vector2(0.6, 0.6)
[node name="Tree" parent="LevelDecor" instance=ExtResource("7_cvl7f")]
position = Vector2(217, 52)
scale = Vector2(0.6, 0.6)
[node name="Tree2" parent="LevelDecor" instance=ExtResource("7_cvl7f")]
position = Vector2(948, 20.0001)
rotation = -0.42237
scale = Vector2(0.4, 0.4)
[node name="Mushrooms" type="Node2D" parent="LevelDecor"]
[node name="Mushroom" parent="LevelDecor/Mushrooms" instance=ExtResource("8_8v50e")]
position = Vector2(232, 250)
scale = Vector2(0.5, 0.5)
[node name="Mushroom2" parent="LevelDecor/Mushrooms" instance=ExtResource("8_8v50e")]
position = Vector2(252, 289)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Mushroom3" parent="LevelDecor/Mushrooms" instance=ExtResource("8_8v50e")]
position = Vector2(260, 225)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Mushrooms2" type="Node2D" parent="LevelDecor"]
position = Vector2(1551, 802)
rotation = 2.81347
[node name="Mushroom" parent="LevelDecor/Mushrooms2" instance=ExtResource("8_8v50e")]
position = Vector2(232, 250)
scale = Vector2(0.5, 0.5)
[node name="Mushroom2" parent="LevelDecor/Mushrooms2" instance=ExtResource("8_8v50e")]
position = Vector2(252, 289)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Mushroom3" parent="LevelDecor/Mushrooms2" instance=ExtResource("8_8v50e")]
position = Vector2(260, 225)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Flowers" parent="." instance=ExtResource("9_4jnhv")]
unique_name_in_owner = true
position = Vector2(1102, 298)
[node name="VegetablePatch" parent="." instance=ExtResource("10_1x4lm")]
position = Vector2(806, 325)
scale = Vector2(0.5, 0.5)
[node name="Beehive" parent="." groups=["beehive"] instance=ExtResource("10_6ye1u")]
unique_name_in_owner = true
position = Vector2(432, 404)
[node name="BeeSpawner" parent="." instance=ExtResource("11_gkdx0")]
unique_name_in_owner = true
[node name="UiComponent" parent="." instance=ExtResource("12_mmtyl")]
unique_name_in_owner = true
z_index = 900
offset_right = 1280.0
offset_bottom = 720.0
mouse_filter = 1
[node name="DroneManager" parent="." instance=ExtResource("13_pibpn")]
unique_name_in_owner = true
[node name="LevelCompleteComponent" parent="." instance=ExtResource("14_uyhgj")]
visible = false
z_index = 999
offset_right = 1280.0
offset_bottom = 720.0
[node name="GameOverComponent" parent="." instance=ExtResource("16_450js")]
visible = false
z_index = 900
offset_right = 1280.0
offset_bottom = 720.0

193
levels/level_3.tscn Normal file
View file

@ -0,0 +1,193 @@
[gd_scene load_steps=17 format=3 uid="uid://bw12t0pk5eecr"]
[ext_resource type="Script" path="res://levels/scripts/level_3.gd" id="1_6fiq4"]
[ext_resource type="PackedScene" uid="uid://dn6aa6f2f4g4i" path="res://components/RulesComponent.tscn" id="2_qf6aq"]
[ext_resource type="Resource" uid="uid://b5s6jqa3ardn0" path="res://levels/rules/level_3_rules.tres" id="3_j7g73"]
[ext_resource type="PackedScene" uid="uid://d1uawawum16b0" path="res://scenes/elements/background.tscn" id="4_dm3kt"]
[ext_resource type="PackedScene" uid="uid://dwuc6byusf1r3" path="res://scenes/decor/bush.tscn" id="5_73yq7"]
[ext_resource type="PackedScene" uid="uid://dj51rgpihnhi" path="res://scenes/decor/naked_tree.tscn" id="6_kh7s2"]
[ext_resource type="PackedScene" uid="uid://d3mas42mbgec1" path="res://scenes/decor/tree.tscn" id="7_oatrq"]
[ext_resource type="PackedScene" uid="uid://eiyribk1ijcu" path="res://scenes/decor/mushroom.tscn" id="8_biah2"]
[ext_resource type="PackedScene" uid="uid://bme541qdw7nai" path="res://entities/Flowers.tscn" id="9_3gmrl"]
[ext_resource type="PackedScene" uid="uid://clomllso36j02" path="res://entities/VegetablePatch.tscn" id="10_knlnk"]
[ext_resource type="PackedScene" uid="uid://dyu4mucawjlu6" path="res://entities/Beehive.tscn" id="11_xvue4"]
[ext_resource type="PackedScene" uid="uid://ddf2mkkw1trkj" path="res://scenes/elements/bee_spawner.tscn" id="12_vwesr"]
[ext_resource type="PackedScene" uid="uid://b7eeptlk47ymd" path="res://ui/UiComponent.tscn" id="13_cw1ps"]
[ext_resource type="PackedScene" uid="uid://ct3c16xm33r2a" path="res://scenes/elements/drone_manager.tscn" id="14_mtjsg"]
[ext_resource type="PackedScene" uid="uid://cwutwy11pityw" path="res://ui/LevelCompleteComponent.tscn" id="15_1jo0f"]
[ext_resource type="PackedScene" uid="uid://b5whit1dshr3" path="res://ui/GameOverComponent.tscn" id="16_61bnh"]
[node name="Level3" type="Node2D"]
script = ExtResource("1_6fiq4")
[node name="RulesComponent" parent="." instance=ExtResource("2_qf6aq")]
unique_name_in_owner = true
game_rules = ExtResource("3_j7g73")
[node name="Grass" parent="." instance=ExtResource("4_dm3kt")]
[node name="LevelDecor" type="Node" parent="."]
[node name="BushGroup" type="Node2D" parent="LevelDecor"]
position = Vector2(-243, -56)
[node name="Bush" parent="LevelDecor/BushGroup" instance=ExtResource("5_73yq7")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup" instance=ExtResource("5_73yq7")]
position = Vector2(1272, 123)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup" instance=ExtResource("5_73yq7")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="BushGroup4" type="Node2D" parent="LevelDecor"]
position = Vector2(8, -4)
[node name="Bush" parent="LevelDecor/BushGroup4" instance=ExtResource("5_73yq7")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup4" instance=ExtResource("5_73yq7")]
position = Vector2(1272, 123)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup4" instance=ExtResource("5_73yq7")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="BushGroup3" type="Node2D" parent="LevelDecor"]
position = Vector2(-928, 592)
scale = Vector2(0.75, 0.75)
[node name="Bush" parent="LevelDecor/BushGroup3" instance=ExtResource("5_73yq7")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup3" instance=ExtResource("5_73yq7")]
position = Vector2(1272, 123)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup3" instance=ExtResource("5_73yq7")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="BushGroup2" type="Node2D" parent="LevelDecor"]
position = Vector2(1291, 1886)
rotation = 4.5012
[node name="Bush" parent="LevelDecor/BushGroup2" instance=ExtResource("5_73yq7")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup2" instance=ExtResource("5_73yq7")]
position = Vector2(1272, 123)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup2" instance=ExtResource("5_73yq7")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="NakedTree" parent="LevelDecor" instance=ExtResource("6_kh7s2")]
position = Vector2(-41, 437)
scale = Vector2(0.6, 0.6)
[node name="Tree" parent="LevelDecor" instance=ExtResource("7_oatrq")]
position = Vector2(217, 52)
scale = Vector2(0.6, 0.6)
[node name="Tree2" parent="LevelDecor" instance=ExtResource("7_oatrq")]
position = Vector2(1175, -35)
rotation = -0.42237
scale = Vector2(0.6, 0.6)
[node name="Mushrooms" type="Node2D" parent="LevelDecor"]
position = Vector2(-254, 571)
rotation = -0.60912
[node name="Mushroom" parent="LevelDecor/Mushrooms" instance=ExtResource("8_biah2")]
position = Vector2(232, 250)
scale = Vector2(0.5, 0.5)
[node name="Mushroom4" parent="LevelDecor/Mushrooms" instance=ExtResource("8_biah2")]
position = Vector2(1209.52, 209.747)
scale = Vector2(0.5, 0.5)
[node name="Mushroom2" parent="LevelDecor/Mushrooms" instance=ExtResource("8_biah2")]
position = Vector2(252, 289)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Mushroom3" parent="LevelDecor/Mushrooms" instance=ExtResource("8_biah2")]
position = Vector2(260, 225)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Mushrooms2" type="Node2D" parent="LevelDecor"]
position = Vector2(1551, 802)
rotation = 2.81347
[node name="Mushroom" parent="LevelDecor/Mushrooms2" instance=ExtResource("8_biah2")]
position = Vector2(232, 250)
scale = Vector2(0.5, 0.5)
[node name="Mushroom2" parent="LevelDecor/Mushrooms2" instance=ExtResource("8_biah2")]
position = Vector2(252, 289)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Mushroom3" parent="LevelDecor/Mushrooms2" instance=ExtResource("8_biah2")]
position = Vector2(260, 225)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Flowers" parent="." instance=ExtResource("9_3gmrl")]
unique_name_in_owner = true
position = Vector2(1102, 298)
[node name="VegetablePatch" parent="." instance=ExtResource("10_knlnk")]
position = Vector2(610, 6)
scale = Vector2(0.5, 0.5)
[node name="VegetablePatch2" parent="." instance=ExtResource("10_knlnk")]
position = Vector2(608, 567)
scale = Vector2(0.5, 0.5)
[node name="VegetablePatch3" parent="." instance=ExtResource("10_knlnk")]
position = Vector2(862, 266)
scale = Vector2(0.5, 0.5)
[node name="Beehive" parent="." groups=["beehive"] instance=ExtResource("11_xvue4")]
unique_name_in_owner = true
position = Vector2(272, 427)
[node name="BeeSpawner" parent="." instance=ExtResource("12_vwesr")]
unique_name_in_owner = true
[node name="UiComponent" parent="." instance=ExtResource("13_cw1ps")]
unique_name_in_owner = true
z_index = 1000
offset_right = 1280.0
offset_bottom = 720.0
mouse_filter = 1
[node name="DroneManager" parent="." instance=ExtResource("14_mtjsg")]
unique_name_in_owner = true
[node name="LevelCompleteComponent" parent="." instance=ExtResource("15_1jo0f")]
visible = false
z_index = 999
offset_right = 1280.0
offset_bottom = 720.0
[node name="GameOverComponent" parent="." instance=ExtResource("16_61bnh")]
visible = false
z_index = 900
offset_right = 1280.0
offset_bottom = 720.0

185
levels/level_4.tscn Normal file
View file

@ -0,0 +1,185 @@
[gd_scene load_steps=17 format=3 uid="uid://byndd263rnk4q"]
[ext_resource type="Script" path="res://levels/scripts/level_3.gd" id="1_uldek"]
[ext_resource type="PackedScene" uid="uid://dn6aa6f2f4g4i" path="res://components/RulesComponent.tscn" id="2_41ccr"]
[ext_resource type="Resource" uid="uid://2xo8nkuq5g35" path="res://levels/rules/level_4_rules.tres" id="3_y0164"]
[ext_resource type="PackedScene" uid="uid://d1uawawum16b0" path="res://scenes/elements/background.tscn" id="4_2ulo2"]
[ext_resource type="PackedScene" uid="uid://dwuc6byusf1r3" path="res://scenes/decor/bush.tscn" id="5_r4fbb"]
[ext_resource type="PackedScene" uid="uid://dj51rgpihnhi" path="res://scenes/decor/naked_tree.tscn" id="6_4f8v1"]
[ext_resource type="PackedScene" uid="uid://d3mas42mbgec1" path="res://scenes/decor/tree.tscn" id="7_tlpqx"]
[ext_resource type="PackedScene" uid="uid://eiyribk1ijcu" path="res://scenes/decor/mushroom.tscn" id="8_fw2qi"]
[ext_resource type="PackedScene" uid="uid://bme541qdw7nai" path="res://entities/Flowers.tscn" id="9_4looi"]
[ext_resource type="PackedScene" uid="uid://dyu4mucawjlu6" path="res://entities/Beehive.tscn" id="11_m7gfp"]
[ext_resource type="PackedScene" uid="uid://ddf2mkkw1trkj" path="res://scenes/elements/bee_spawner.tscn" id="12_scxhi"]
[ext_resource type="PackedScene" uid="uid://b7eeptlk47ymd" path="res://ui/UiComponent.tscn" id="13_a7gm0"]
[ext_resource type="PackedScene" uid="uid://ct3c16xm33r2a" path="res://scenes/elements/drone_manager.tscn" id="14_6mygu"]
[ext_resource type="PackedScene" uid="uid://cwutwy11pityw" path="res://ui/LevelCompleteComponent.tscn" id="15_vt473"]
[ext_resource type="PackedScene" uid="uid://cfhoi2rqxa3up" path="res://entities/Dog.tscn" id="16_ams0s"]
[ext_resource type="PackedScene" uid="uid://b5whit1dshr3" path="res://ui/GameOverComponent.tscn" id="16_quoie"]
[node name="Level4" type="Node2D"]
script = ExtResource("1_uldek")
[node name="RulesComponent" parent="." instance=ExtResource("2_41ccr")]
unique_name_in_owner = true
game_rules = ExtResource("3_y0164")
[node name="Grass" parent="." instance=ExtResource("4_2ulo2")]
[node name="LevelDecor" type="Node" parent="."]
[node name="BushGroup" type="Node2D" parent="LevelDecor"]
position = Vector2(-243, -56)
[node name="Bush" parent="LevelDecor/BushGroup" instance=ExtResource("5_r4fbb")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup" instance=ExtResource("5_r4fbb")]
position = Vector2(1272, 123)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup" instance=ExtResource("5_r4fbb")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="BushGroup4" type="Node2D" parent="LevelDecor"]
position = Vector2(8, -4)
[node name="Bush" parent="LevelDecor/BushGroup4" instance=ExtResource("5_r4fbb")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup4" instance=ExtResource("5_r4fbb")]
position = Vector2(1272, 123)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup4" instance=ExtResource("5_r4fbb")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="BushGroup3" type="Node2D" parent="LevelDecor"]
position = Vector2(-928, 592)
scale = Vector2(0.75, 0.75)
[node name="Bush" parent="LevelDecor/BushGroup3" instance=ExtResource("5_r4fbb")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup3" instance=ExtResource("5_r4fbb")]
position = Vector2(1272, 123)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup3" instance=ExtResource("5_r4fbb")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="BushGroup2" type="Node2D" parent="LevelDecor"]
position = Vector2(1291, 1886)
rotation = 4.5012
[node name="Bush" parent="LevelDecor/BushGroup2" instance=ExtResource("5_r4fbb")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup2" instance=ExtResource("5_r4fbb")]
position = Vector2(1272, 123)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup2" instance=ExtResource("5_r4fbb")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="NakedTree" parent="LevelDecor" instance=ExtResource("6_4f8v1")]
position = Vector2(-41, 437)
scale = Vector2(0.6, 0.6)
[node name="Tree" parent="LevelDecor" instance=ExtResource("7_tlpqx")]
position = Vector2(217, 52)
scale = Vector2(0.6, 0.6)
[node name="Tree2" parent="LevelDecor" instance=ExtResource("7_tlpqx")]
position = Vector2(1175, -35)
rotation = -0.42237
scale = Vector2(0.6, 0.6)
[node name="Mushrooms" type="Node2D" parent="LevelDecor"]
position = Vector2(-254, 571)
rotation = -0.60912
[node name="Mushroom" parent="LevelDecor/Mushrooms" instance=ExtResource("8_fw2qi")]
position = Vector2(232, 250)
scale = Vector2(0.5, 0.5)
[node name="Mushroom4" parent="LevelDecor/Mushrooms" instance=ExtResource("8_fw2qi")]
position = Vector2(1209.52, 209.747)
scale = Vector2(0.5, 0.5)
[node name="Mushroom2" parent="LevelDecor/Mushrooms" instance=ExtResource("8_fw2qi")]
position = Vector2(252, 289)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Mushroom3" parent="LevelDecor/Mushrooms" instance=ExtResource("8_fw2qi")]
position = Vector2(260, 225)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Mushrooms2" type="Node2D" parent="LevelDecor"]
position = Vector2(1551, 802)
rotation = 2.81347
[node name="Mushroom" parent="LevelDecor/Mushrooms2" instance=ExtResource("8_fw2qi")]
position = Vector2(232, 250)
scale = Vector2(0.5, 0.5)
[node name="Mushroom2" parent="LevelDecor/Mushrooms2" instance=ExtResource("8_fw2qi")]
position = Vector2(252, 289)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Mushroom3" parent="LevelDecor/Mushrooms2" instance=ExtResource("8_fw2qi")]
position = Vector2(260, 225)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Flowers" parent="." instance=ExtResource("9_4looi")]
unique_name_in_owner = true
position = Vector2(1102, 298)
[node name="Beehive" parent="." groups=["beehive"] instance=ExtResource("11_m7gfp")]
unique_name_in_owner = true
position = Vector2(272, 427)
[node name="BeeSpawner" parent="." instance=ExtResource("12_scxhi")]
unique_name_in_owner = true
[node name="UiComponent" parent="." instance=ExtResource("13_a7gm0")]
unique_name_in_owner = true
z_index = 1000
offset_right = 1280.0
offset_bottom = 720.0
mouse_filter = 1
[node name="DroneManager" parent="." instance=ExtResource("14_6mygu")]
unique_name_in_owner = true
[node name="LevelCompleteComponent" parent="." instance=ExtResource("15_vt473")]
visible = false
z_index = 999
offset_right = 1280.0
offset_bottom = 720.0
[node name="GameOverComponent" parent="." instance=ExtResource("16_quoie")]
visible = false
z_index = 900
offset_right = 1280.0
offset_bottom = 720.0
[node name="Dog" parent="." instance=ExtResource("16_ams0s")]
position = Vector2(731, 309)
rotation = 0.844739

220
levels/level_5.tscn Normal file
View file

@ -0,0 +1,220 @@
[gd_scene load_steps=18 format=3 uid="uid://vvk5h14u0i1k"]
[ext_resource type="Script" path="res://levels/scripts/level_3.gd" id="1_7viev"]
[ext_resource type="PackedScene" uid="uid://dn6aa6f2f4g4i" path="res://components/RulesComponent.tscn" id="2_d6prf"]
[ext_resource type="Resource" uid="uid://drdk5e8lskbwo" path="res://levels/rules/level_5_rules.tres" id="3_xjoeh"]
[ext_resource type="PackedScene" uid="uid://d1uawawum16b0" path="res://scenes/elements/background.tscn" id="4_o2mgo"]
[ext_resource type="PackedScene" uid="uid://dwuc6byusf1r3" path="res://scenes/decor/bush.tscn" id="5_ldaym"]
[ext_resource type="PackedScene" uid="uid://dj51rgpihnhi" path="res://scenes/decor/naked_tree.tscn" id="6_4xst1"]
[ext_resource type="PackedScene" uid="uid://d3mas42mbgec1" path="res://scenes/decor/tree.tscn" id="7_bmsu5"]
[ext_resource type="PackedScene" uid="uid://eiyribk1ijcu" path="res://scenes/decor/mushroom.tscn" id="8_dtrxx"]
[ext_resource type="PackedScene" uid="uid://bme541qdw7nai" path="res://entities/Flowers.tscn" id="9_ne0y1"]
[ext_resource type="PackedScene" uid="uid://dyu4mucawjlu6" path="res://entities/Beehive.tscn" id="10_ogjm5"]
[ext_resource type="PackedScene" uid="uid://ddf2mkkw1trkj" path="res://scenes/elements/bee_spawner.tscn" id="11_kkv2y"]
[ext_resource type="PackedScene" uid="uid://b7eeptlk47ymd" path="res://ui/UiComponent.tscn" id="12_ml7gj"]
[ext_resource type="PackedScene" uid="uid://ct3c16xm33r2a" path="res://scenes/elements/drone_manager.tscn" id="13_yi2jf"]
[ext_resource type="PackedScene" uid="uid://cwutwy11pityw" path="res://ui/LevelCompleteComponent.tscn" id="14_i1bii"]
[ext_resource type="PackedScene" uid="uid://b5whit1dshr3" path="res://ui/GameOverComponent.tscn" id="15_2iprn"]
[ext_resource type="PackedScene" uid="uid://cfhoi2rqxa3up" path="res://entities/Dog.tscn" id="16_jy3y1"]
[ext_resource type="PackedScene" uid="uid://clomllso36j02" path="res://entities/VegetablePatch.tscn" id="17_0sreo"]
[node name="Level5" type="Node2D"]
script = ExtResource("1_7viev")
[node name="RulesComponent" parent="." instance=ExtResource("2_d6prf")]
unique_name_in_owner = true
game_rules = ExtResource("3_xjoeh")
[node name="Grass" parent="." instance=ExtResource("4_o2mgo")]
[node name="Beehive" parent="." groups=["beehive"] instance=ExtResource("10_ogjm5")]
unique_name_in_owner = true
position = Vector2(138, 488)
[node name="Dog" parent="." instance=ExtResource("16_jy3y1")]
position = Vector2(1021, 227)
rotation = 0.844739
[node name="VegetablePatch" parent="." instance=ExtResource("17_0sreo")]
position = Vector2(382, 146)
scale = Vector2(0.5, 0.5)
[node name="LevelDecor" type="Node2D" parent="."]
[node name="BushGroup" type="Node2D" parent="LevelDecor"]
position = Vector2(-243, -56)
[node name="Bush" parent="LevelDecor/BushGroup" instance=ExtResource("5_ldaym")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup" instance=ExtResource("5_ldaym")]
position = Vector2(1272, 123)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup" instance=ExtResource("5_ldaym")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="BushGroup4" type="Node2D" parent="LevelDecor"]
position = Vector2(83, 221)
[node name="Bush" parent="LevelDecor/BushGroup4" instance=ExtResource("5_ldaym")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup4" instance=ExtResource("5_ldaym")]
position = Vector2(1272, 123)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup4" instance=ExtResource("5_ldaym")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="BushGroup3" type="Node2D" parent="LevelDecor"]
position = Vector2(-928, 592)
scale = Vector2(0.75, 0.75)
[node name="Bush" parent="LevelDecor/BushGroup3" instance=ExtResource("5_ldaym")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup3" instance=ExtResource("5_ldaym")]
position = Vector2(1272, 123)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup3" instance=ExtResource("5_ldaym")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="BushGroup2" type="Node2D" parent="LevelDecor"]
position = Vector2(1291, 1886)
rotation = -1.78199
[node name="Bush" parent="LevelDecor/BushGroup2" instance=ExtResource("5_ldaym")]
visible = false
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup2" instance=ExtResource("5_ldaym")]
position = Vector2(1235.53, -33.756)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup2" instance=ExtResource("5_ldaym")]
visible = false
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="NakedTree" parent="LevelDecor" instance=ExtResource("6_4xst1")]
position = Vector2(57, 251)
scale = Vector2(0.6, 0.6)
[node name="Tree" parent="LevelDecor" instance=ExtResource("7_bmsu5")]
position = Vector2(217, 52)
scale = Vector2(0.6, 0.6)
[node name="Tree3" parent="LevelDecor" instance=ExtResource("7_bmsu5")]
position = Vector2(-27, 309)
rotation = 1.54811
scale = Vector2(0.3, 0.3)
[node name="Tree2" parent="LevelDecor" instance=ExtResource("7_bmsu5")]
position = Vector2(1175, -35)
rotation = -0.42237
scale = Vector2(0.6, 0.6)
[node name="Mushrooms" type="Node2D" parent="LevelDecor"]
position = Vector2(42, 290)
rotation = 0.563741
[node name="Mushroom" parent="LevelDecor/Mushrooms" instance=ExtResource("8_dtrxx")]
position = Vector2(232, 250)
scale = Vector2(0.5, 0.5)
[node name="Mushroom4" parent="LevelDecor/Mushrooms" instance=ExtResource("8_dtrxx")]
position = Vector2(133.124, -146.86)
scale = Vector2(0.5, 0.5)
[node name="Mushroom2" parent="LevelDecor/Mushrooms" instance=ExtResource("8_dtrxx")]
visible = false
position = Vector2(252, 289)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Mushroom3" parent="LevelDecor/Mushrooms" instance=ExtResource("8_dtrxx")]
position = Vector2(260, 225)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Mushrooms2" type="Node2D" parent="LevelDecor"]
position = Vector2(1551, 802)
rotation = 2.81347
[node name="Mushroom" parent="LevelDecor/Mushrooms2" instance=ExtResource("8_dtrxx")]
position = Vector2(232, 250)
scale = Vector2(0.5, 0.5)
[node name="Mushroom2" parent="LevelDecor/Mushrooms2" instance=ExtResource("8_dtrxx")]
position = Vector2(252, 289)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Mushroom3" parent="LevelDecor/Mushrooms2" instance=ExtResource("8_dtrxx")]
position = Vector2(260, 225)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Flowers" parent="." instance=ExtResource("9_ne0y1")]
unique_name_in_owner = true
position = Vector2(1092, 495)
[node name="BeeSpawner" parent="." instance=ExtResource("11_kkv2y")]
unique_name_in_owner = true
[node name="UiComponent" parent="." instance=ExtResource("12_ml7gj")]
unique_name_in_owner = true
z_index = 1000
offset_right = 1280.0
offset_bottom = 720.0
mouse_filter = 1
[node name="DroneManager" parent="." instance=ExtResource("13_yi2jf")]
unique_name_in_owner = true
[node name="LevelCompleteComponent" parent="." instance=ExtResource("14_i1bii")]
visible = false
z_index = 999
offset_right = 1280.0
offset_bottom = 720.0
[node name="GameOverComponent" parent="." instance=ExtResource("15_2iprn")]
visible = false
z_index = 900
offset_right = 1280.0
offset_bottom = 720.0
[node name="VegetablePatch5" parent="." instance=ExtResource("17_0sreo")]
position = Vector2(620, 691)
scale = Vector2(0.5, 0.5)
[node name="VegetablePatch6" parent="." instance=ExtResource("17_0sreo")]
position = Vector2(837, 732)
scale = Vector2(0.5, 0.5)
[node name="VegetablePatch2" parent="." instance=ExtResource("17_0sreo")]
position = Vector2(384, 624)
scale = Vector2(0.5, 0.5)
[node name="VegetablePatch3" parent="." instance=ExtResource("17_0sreo")]
position = Vector2(747, 374)
rotation = 1.5708
scale = Vector2(0.5, 0.5)
[node name="VegetablePatch4" parent="." instance=ExtResource("17_0sreo")]
position = Vector2(743, 151)
rotation = 1.5708
scale = Vector2(0.5, 0.5)

225
levels/level_6.tscn Normal file
View file

@ -0,0 +1,225 @@
[gd_scene load_steps=18 format=3 uid="uid://dtrqvifl07hgo"]
[ext_resource type="Script" path="res://levels/scripts/level_3.gd" id="1_hg53e"]
[ext_resource type="PackedScene" uid="uid://dn6aa6f2f4g4i" path="res://components/RulesComponent.tscn" id="2_ufpjb"]
[ext_resource type="Resource" uid="uid://bts21313fjhri" path="res://levels/rules/level_6_rules.tres" id="3_ckppu"]
[ext_resource type="PackedScene" uid="uid://d1uawawum16b0" path="res://scenes/elements/background.tscn" id="4_7ro3d"]
[ext_resource type="PackedScene" uid="uid://dyu4mucawjlu6" path="res://entities/Beehive.tscn" id="5_613ii"]
[ext_resource type="PackedScene" uid="uid://cfhoi2rqxa3up" path="res://entities/Dog.tscn" id="6_fbrq3"]
[ext_resource type="PackedScene" uid="uid://clomllso36j02" path="res://entities/VegetablePatch.tscn" id="7_85a4g"]
[ext_resource type="PackedScene" uid="uid://dwuc6byusf1r3" path="res://scenes/decor/bush.tscn" id="8_cbi4d"]
[ext_resource type="PackedScene" uid="uid://dj51rgpihnhi" path="res://scenes/decor/naked_tree.tscn" id="9_hxin4"]
[ext_resource type="PackedScene" uid="uid://d3mas42mbgec1" path="res://scenes/decor/tree.tscn" id="10_60f2e"]
[ext_resource type="PackedScene" uid="uid://eiyribk1ijcu" path="res://scenes/decor/mushroom.tscn" id="11_hhoco"]
[ext_resource type="PackedScene" uid="uid://bme541qdw7nai" path="res://entities/Flowers.tscn" id="12_75856"]
[ext_resource type="PackedScene" uid="uid://ddf2mkkw1trkj" path="res://scenes/elements/bee_spawner.tscn" id="13_wjpeu"]
[ext_resource type="PackedScene" uid="uid://b7eeptlk47ymd" path="res://ui/UiComponent.tscn" id="14_05wvt"]
[ext_resource type="PackedScene" uid="uid://ct3c16xm33r2a" path="res://scenes/elements/drone_manager.tscn" id="15_6fk1g"]
[ext_resource type="PackedScene" uid="uid://cwutwy11pityw" path="res://ui/LevelCompleteComponent.tscn" id="16_r0rm6"]
[ext_resource type="PackedScene" uid="uid://b5whit1dshr3" path="res://ui/GameOverComponent.tscn" id="17_x23hi"]
[node name="Level6" type="Node2D"]
script = ExtResource("1_hg53e")
[node name="RulesComponent" parent="." instance=ExtResource("2_ufpjb")]
unique_name_in_owner = true
game_rules = ExtResource("3_ckppu")
[node name="Grass" parent="." instance=ExtResource("4_7ro3d")]
[node name="Beehive" parent="." groups=["beehive"] instance=ExtResource("5_613ii")]
unique_name_in_owner = true
position = Vector2(647, 184)
[node name="VegetablePatch6" parent="." instance=ExtResource("7_85a4g")]
position = Vector2(568, 516)
rotation = 1.5708
scale = Vector2(0.4, 0.4)
[node name="VegetablePatch" parent="." instance=ExtResource("7_85a4g")]
position = Vector2(465, 301)
scale = Vector2(0.4, 0.4)
[node name="VegetablePatch3" parent="." instance=ExtResource("7_85a4g")]
position = Vector2(276, 230)
rotation = 0.785398
scale = Vector2(0.4, 0.4)
[node name="VegetablePatch2" parent="." instance=ExtResource("7_85a4g")]
position = Vector2(833, 309)
scale = Vector2(0.4, 0.4)
[node name="VegetablePatch4" parent="." instance=ExtResource("7_85a4g")]
position = Vector2(1013, 227)
rotation = -0.785398
scale = Vector2(0.4, 0.4)
[node name="VegetablePatch5" parent="." instance=ExtResource("7_85a4g")]
position = Vector2(1236, 441)
rotation = -0.785398
scale = Vector2(0.4, 0.4)
[node name="LevelDecor" type="Node2D" parent="."]
[node name="BushGroup" type="Node2D" parent="LevelDecor"]
position = Vector2(-243, -56)
[node name="Bush" parent="LevelDecor/BushGroup" instance=ExtResource("8_cbi4d")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup" instance=ExtResource("8_cbi4d")]
position = Vector2(495, 53)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup" instance=ExtResource("8_cbi4d")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="BushGroup4" type="Node2D" parent="LevelDecor"]
position = Vector2(83, 221)
[node name="Bush" parent="LevelDecor/BushGroup4" instance=ExtResource("8_cbi4d")]
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup4" instance=ExtResource("8_cbi4d")]
position = Vector2(1272, 123)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup4" instance=ExtResource("8_cbi4d")]
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="BushGroup3" type="Node2D" parent="LevelDecor"]
position = Vector2(-928, 592)
scale = Vector2(0.75, 0.75)
[node name="Bush" parent="LevelDecor/BushGroup3" instance=ExtResource("8_cbi4d")]
position = Vector2(1726.67, -413.333)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup3" instance=ExtResource("8_cbi4d")]
position = Vector2(1309.33, 81.3333)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup3" instance=ExtResource("8_cbi4d")]
position = Vector2(1233.33, -340)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="BushGroup2" type="Node2D" parent="LevelDecor"]
position = Vector2(1291, 1886)
rotation = -1.78199
[node name="Bush" parent="LevelDecor/BushGroup2" instance=ExtResource("8_cbi4d")]
visible = false
position = Vector2(1110, 28)
scale = Vector2(0.25, 0.25)
[node name="Bush3" parent="LevelDecor/BushGroup2" instance=ExtResource("8_cbi4d")]
position = Vector2(1235.53, -33.756)
scale = Vector2(0.25, 0.25)
[node name="Bush2" parent="LevelDecor/BushGroup2" instance=ExtResource("8_cbi4d")]
visible = false
position = Vector2(1214, 47)
rotation = 0.60912
scale = Vector2(0.4, 0.4)
[node name="NakedTree" parent="LevelDecor" instance=ExtResource("9_hxin4")]
position = Vector2(-4, 157)
scale = Vector2(0.6, 0.6)
[node name="Tree" parent="LevelDecor" instance=ExtResource("10_60f2e")]
position = Vector2(59, -4)
scale = Vector2(0.6, 0.6)
[node name="Tree3" parent="LevelDecor" instance=ExtResource("10_60f2e")]
position = Vector2(648, 371)
rotation = 0.986111
scale = Vector2(0.25, 0.25)
[node name="Tree2" parent="LevelDecor" instance=ExtResource("10_60f2e")]
position = Vector2(1175, -35)
rotation = -0.42237
scale = Vector2(0.6, 0.6)
[node name="Mushrooms" type="Node2D" parent="LevelDecor"]
position = Vector2(42, 290)
rotation = 0.563741
[node name="Mushroom" parent="LevelDecor/Mushrooms" instance=ExtResource("11_hhoco")]
position = Vector2(232, 250)
scale = Vector2(0.5, 0.5)
[node name="Mushroom4" parent="LevelDecor/Mushrooms" instance=ExtResource("11_hhoco")]
position = Vector2(54.3027, -282.772)
scale = Vector2(0.5, 0.5)
[node name="Mushroom2" parent="LevelDecor/Mushrooms" instance=ExtResource("11_hhoco")]
position = Vector2(949.017, -785.684)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Mushroom3" parent="LevelDecor/Mushrooms" instance=ExtResource("11_hhoco")]
position = Vector2(260, 225)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Mushrooms2" type="Node2D" parent="LevelDecor"]
position = Vector2(1551, 802)
rotation = 2.81347
[node name="Mushroom" parent="LevelDecor/Mushrooms2" instance=ExtResource("11_hhoco")]
position = Vector2(321.639, 243.653)
scale = Vector2(0.5, 0.5)
[node name="Mushroom2" parent="LevelDecor/Mushrooms2" instance=ExtResource("11_hhoco")]
position = Vector2(252, 289)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Mushroom3" parent="LevelDecor/Mushrooms2" instance=ExtResource("11_hhoco")]
position = Vector2(260, 225)
rotation = 1.13446
scale = Vector2(0.3, 0.3)
[node name="Flowers" parent="." instance=ExtResource("12_75856")]
unique_name_in_owner = true
position = Vector2(197, 524)
[node name="Flowers2" parent="." instance=ExtResource("12_75856")]
unique_name_in_owner = true
position = Vector2(1006, 486)
[node name="Dog" parent="." instance=ExtResource("6_fbrq3")]
position = Vector2(1007, 488)
rotation = 0.844739
[node name="BeeSpawner" parent="." instance=ExtResource("13_wjpeu")]
unique_name_in_owner = true
[node name="UiComponent" parent="." instance=ExtResource("14_05wvt")]
unique_name_in_owner = true
z_index = 1000
offset_right = 1280.0
offset_bottom = 720.0
mouse_filter = 1
[node name="DroneManager" parent="." instance=ExtResource("15_6fk1g")]
unique_name_in_owner = true
[node name="LevelCompleteComponent" parent="." instance=ExtResource("16_r0rm6")]
visible = false
z_index = 999
offset_right = 1280.0
offset_bottom = 720.0
[node name="GameOverComponent" parent="." instance=ExtResource("17_x23hi")]
visible = false
z_index = 900
offset_right = 1280.0
offset_bottom = 720.0

View file

@ -0,0 +1,16 @@
[gd_resource type="Resource" script_class="GameRulesResource" load_steps=2 format=3 uid="uid://dxkuoaiws5cc3"]
[ext_resource type="Script" path="res://components/scripts/game_rules.gd" id="1_g4ck5"]
[resource]
script = ExtResource("1_g4ck5")
level_number = 20
level_name = "High Scores"
level_description = "These are the high scores"
bees_available = 5
nectar_required = 9999999
level_par = 2
collector_enabled = false
dancer_enabled = false
director_enabled = false
distractor_enabled = false

View file

@ -0,0 +1,16 @@
[gd_resource type="Resource" script_class="GameRulesResource" load_steps=2 format=3 uid="uid://byyectcdb7e14"]
[ext_resource type="Script" path="res://components/scripts/game_rules.gd" id="1_265gm"]
[resource]
script = ExtResource("1_265gm")
level_number = 1
level_name = "Level One"
level_description = "Basic game introduction"
bees_available = 40
nectar_required = 400
level_par = 2
collector_enabled = true
dancer_enabled = true
director_enabled = false
distractor_enabled = false

View file

@ -0,0 +1,16 @@
[gd_resource type="Resource" script_class="GameRulesResource" load_steps=2 format=3 uid="uid://cqtsmjsyqne41"]
[ext_resource type="Script" path="res://components/scripts/game_rules.gd" id="1_ga8fp"]
[resource]
script = ExtResource("1_ga8fp")
level_number = 2
level_name = "Level Two"
level_description = "Hazard introduction - pesticide"
bees_available = 40
nectar_required = 800
level_par = 3
collector_enabled = true
dancer_enabled = true
director_enabled = true
distractor_enabled = false

View file

@ -0,0 +1,16 @@
[gd_resource type="Resource" script_class="GameRulesResource" load_steps=2 format=3 uid="uid://b5s6jqa3ardn0"]
[ext_resource type="Script" path="res://components/scripts/game_rules.gd" id="1_kdeq5"]
[resource]
script = ExtResource("1_kdeq5")
level_number = 3
level_name = "Level Three"
level_description = "Hazard introduction - more pesticide!"
bees_available = 60
nectar_required = 1000
level_par = 4
collector_enabled = true
dancer_enabled = true
director_enabled = true
distractor_enabled = false

View file

@ -0,0 +1,16 @@
[gd_resource type="Resource" script_class="GameRulesResource" load_steps=2 format=3 uid="uid://2xo8nkuq5g35"]
[ext_resource type="Script" path="res://components/scripts/game_rules.gd" id="1_c8fak"]
[resource]
script = ExtResource("1_c8fak")
level_number = 4
level_name = "Level Four"
level_description = "Hazard introduction - it's a dog!"
bees_available = 60
nectar_required = 1000
level_par = 3
collector_enabled = true
dancer_enabled = true
director_enabled = false
distractor_enabled = true

View file

@ -0,0 +1,16 @@
[gd_resource type="Resource" script_class="GameRulesResource" load_steps=2 format=3 uid="uid://drdk5e8lskbwo"]
[ext_resource type="Script" path="res://components/scripts/game_rules.gd" id="1_6j81d"]
[resource]
script = ExtResource("1_6j81d")
level_number = 5
level_name = "Level Five"
level_description = "Serious Business"
bees_available = 100
nectar_required = 2000
level_par = 5
collector_enabled = true
dancer_enabled = true
director_enabled = true
distractor_enabled = true

View file

@ -0,0 +1,16 @@
[gd_resource type="Resource" script_class="GameRulesResource" load_steps=2 format=3 uid="uid://bts21313fjhri"]
[ext_resource type="Script" path="res://components/scripts/game_rules.gd" id="1_j7qva"]
[resource]
script = ExtResource("1_j7qva")
level_number = 6
level_name = "Level Six"
level_description = "Serious Business"
bees_available = 120
nectar_required = 3000
level_par = 6
collector_enabled = true
dancer_enabled = true
director_enabled = true
distractor_enabled = true

View file

@ -0,0 +1,16 @@
[gd_resource type="Resource" script_class="GameRulesResource" load_steps=2 format=3 uid="uid://bn4qhonifxne3"]
[ext_resource type="Script" path="res://components/scripts/game_rules.gd" id="1_nviaj"]
[resource]
script = ExtResource("1_nviaj")
level_number = 0
level_name = "Main Menu"
level_description = "This is the main menu"
bees_available = 5
nectar_required = 9999999
level_par = 2
collector_enabled = false
dancer_enabled = false
director_enabled = false
distractor_enabled = false

17
levels/scripts/level.gd Normal file
View file

@ -0,0 +1,17 @@
class_name Level extends Node
@onready var rules : RulesComponent = get_node("RulesComponent") as RulesComponent
@onready var bee_spawner : BeeSpawner = get_node("BeeSpawner") as BeeSpawner
@onready var ui_controls : UIComponent = get_node("UiComponent") as UIComponent
func _ready() -> void:
update_game_state()
func update_game_state() -> void:
GameState.required_nectar = rules.game_rules.nectar_required
GameState.level_par = rules.game_rules.level_par
GameState.level_number = rules.game_rules.level_number
GameState.bees_available = rules.game_rules.bees_available
ui_controls.update_level_text("Level : " + str(rules.game_rules.level_number))
ui_controls.update_par_text("Par : " + str(rules.game_rules.level_par))
bee_spawner.max_bees = rules.game_rules.bees_available

View file

@ -0,0 +1,3 @@
extends Level
class_name LevelOne

View file

@ -0,0 +1,2 @@
extends Level
class_name LevelTwo

View file

@ -0,0 +1,2 @@
extends Level
class_name LevelThree

View file

@ -11,5 +11,52 @@ config_version=5
[application]
config/name="Pollen Not Included"
run/main_scene="res://scenes/scene_manager.tscn"
config/features=PackedStringArray("4.2", "Forward Plus")
config/icon="res://icon.svg"
boot_splash/show_image=false
config/icon="res://resources/icons/gameicon.png"
config/windows_native_icon="res://resources/icons/icon.ico"
[autoload]
Str="*res://utility/utility_strings.gd"
CursorMgr="*res://utility/cursor_manager.gd"
GameState="*res://utility/game_state.gd"
SceneMgr="*res://utility/global_scene_manager.gd"
HighScoreMgr="*res://utility/high_scores.gd"
[debug]
gdscript/warnings/untyped_declaration=1
gdscript/warnings/inferred_declaration=1
[display]
window/size/viewport_width=1280
window/size/viewport_height=720
window/stretch/mode="viewport"
window/vsync/vsync_mode=0
mouse_cursor/custom_image="res://resources/cursors/pointer_a.png"
mouse_cursor/custom_image_hotspot=Vector2(8, 8)
[editor_plugins]
enabled=PackedStringArray("res://addons/log/plugin.cfg")
[gui]
theme/custom="res://resources/theme/game_theme.tres"
[layer_names]
2d_physics/layer_1="bees"
2d_physics/layer_2="hazards"
2d_physics/layer_3="flowers"
[physics]
2d/run_on_separate_thread=true
[rendering]
renderer/rendering_method="gl_compatibility"

BIN
resources/SFX/bee.ogg Normal file

Binary file not shown.

View file

@ -0,0 +1,19 @@
[remap]
importer="oggvorbisstr"
type="AudioStreamOggVorbis"
uid="uid://jdk681m35wt4"
path="res://.godot/imported/bee.ogg-2ae807cffcea1e18ac098b6092cda761.oggvorbisstr"
[deps]
source_file="res://resources/SFX/bee.ogg"
dest_files=["res://.godot/imported/bee.ogg-2ae807cffcea1e18ac098b6092cda761.oggvorbisstr"]
[params]
loop=true
loop_offset=0
bpm=0
beat_count=0
bar_beats=4

Binary file not shown.

View file

@ -0,0 +1,24 @@
[remap]
importer="wav"
type="AudioStreamWAV"
uid="uid://dpgl5huwc4yl8"
path="res://.godot/imported/mixkit-big-bee-hard-flying-sound-42.wav-772da984940bacc52c99d0787cc9adb8.sample"
[deps]
source_file="res://resources/SFX/mixkit-big-bee-hard-flying-sound-42.wav"
dest_files=["res://.godot/imported/mixkit-big-bee-hard-flying-sound-42.wav-772da984940bacc52c99d0787cc9adb8.sample"]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=0

View file

@ -0,0 +1,24 @@
[remap]
importer="wav"
type="AudioStreamWAV"
uid="uid://dvsjpsh5dyixq"
path="res://.godot/imported/mixkit-european-spring-forest-ambience-1219.wav-d4f05387a508f164ac731bd7237091a8.sample"
[deps]
source_file="res://resources/SFX/mixkit-european-spring-forest-ambience-1219.wav"
dest_files=["res://.godot/imported/mixkit-european-spring-forest-ambience-1219.wav-d4f05387a508f164ac731bd7237091a8.sample"]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=2
edit/loop_begin=0
edit/loop_end=-1
compress/mode=0

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bn1mvt0n0idwv"
path="res://.godot/imported/arrow_e.png-7b1be4e767721a9ed88ed338570ad7fc.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://resources/cursors/arrow_e.png"
dest_files=["res://.godot/imported/arrow_e.png-7b1be4e767721a9ed88ed338570ad7fc.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://3oxvxr1gqqxq"
path="res://.godot/imported/arrow_n.png-fef8c72db9afa29d32e4024daa81dcab.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://resources/cursors/arrow_n.png"
dest_files=["res://.godot/imported/arrow_n.png-fef8c72db9afa29d32e4024daa81dcab.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b8fw6tnl30udj"
path="res://.godot/imported/arrow_ne.png-178cbd61845b6728a7cee6d8ce2cee65.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://resources/cursors/arrow_ne.png"
dest_files=["res://.godot/imported/arrow_ne.png-178cbd61845b6728a7cee6d8ce2cee65.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dytk3baj31d1i"
path="res://.godot/imported/arrow_nw.png-fa4c1384472ccb0ed8e7dbd053d1370a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://resources/cursors/arrow_nw.png"
dest_files=["res://.godot/imported/arrow_nw.png-fa4c1384472ccb0ed8e7dbd053d1370a.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cs4d7bu221y0v"
path="res://.godot/imported/arrow_s.png-b3f8530096e88442ff816309033c3041.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://resources/cursors/arrow_s.png"
dest_files=["res://.godot/imported/arrow_s.png-b3f8530096e88442ff816309033c3041.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c6ok1cpd8ostw"
path="res://.godot/imported/arrow_se.png-1039f2195e10040c4685d9c17feef67d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://resources/cursors/arrow_se.png"
dest_files=["res://.godot/imported/arrow_se.png-1039f2195e10040c4685d9c17feef67d.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bx4w2polamajx"
path="res://.godot/imported/arrow_sw.png-a1c39c74ea5ba886f65393b9116bf124.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://resources/cursors/arrow_sw.png"
dest_files=["res://.godot/imported/arrow_sw.png-a1c39c74ea5ba886f65393b9116bf124.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bpi0rv1uxno7y"
path="res://.godot/imported/arrow_w.png-7b56f9e9f96eb58f8919921a38416da8.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://resources/cursors/arrow_w.png"
dest_files=["res://.godot/imported/arrow_w.png-7b56f9e9f96eb58f8919921a38416da8.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://vda0xt2gxpkb"
path="res://.godot/imported/bracket_a_horizontal.png-d224bf4cf52fe5b551a8ad950aa55b97.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://resources/cursors/bracket_a_horizontal.png"
dest_files=["res://.godot/imported/bracket_a_horizontal.png-d224bf4cf52fe5b551a8ad950aa55b97.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://npevc1mcu6lb"
path="res://.godot/imported/bracket_a_vertical.png-506648ad4e87f7e225b6360392276da6.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://resources/cursors/bracket_a_vertical.png"
dest_files=["res://.godot/imported/bracket_a_vertical.png-506648ad4e87f7e225b6360392276da6.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

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