@tool extends EditorPlugin # Editor plugin that provides a UI for creating 3D weapons with all required resources # Adds a dock panel to the editor with input fields and a create button var dock_instance: PanelContainer func _enter_tree() -> void: # Load the dock script and instantiate programmatically var dock_script = load("res://addons/weapon_creator/WeaponCreatorDock.gd") dock_instance = PanelContainer.new() dock_instance.set_script(dock_script) # Pass editor interface to dock dock_instance.call("setup", get_editor_interface()) # Connect the create button signal from the dock if dock_instance.has_signal("create_weapon_requested"): dock_instance.create_weapon_requested.connect(_on_create_weapon_requested) if dock_instance.has_signal("create_bullet_requested"): dock_instance.create_bullet_requested.connect(_on_create_bullet_requested) # Add the dock to the editor (bottom dock area) add_control_to_bottom_panel(dock_instance, "Weapon Creator") func _exit_tree() -> void: # Cleanup when plugin is disabled if dock_instance: remove_control_from_bottom_panel(dock_instance) dock_instance.queue_free() func _on_create_weapon_requested(weapon_data: Dictionary) -> void: # Extract data from the dictionary var weapon_name: String = weapon_data.get("weapon_name", "New Weapon") var weapon_item_key: String = weapon_data.get("weapon_item_key", "NEW_WEAPON") var ammo_key: String = weapon_data.get("ammo_key", "") var weapon_short_name: String = weapon_data.get("weapon_short_name", "NW-1") var weapon_description: String = weapon_data.get("weapon_description", "A new weapon") var sprite_resource: Texture2D = weapon_data.get("sprite_resource", null) var default_bullet_path: String = weapon_data.get("default_bullet_path", "res://Resources/Bullets/3D/icicle_repeater_bullets_3D.tres") var is_3d: bool = weapon_data.get("is_3d", true) # Weapon stats var priority: int = weapon_data.get("priority", 10) var ammo_per_shot: int = weapon_data.get("ammo_per_shot", 1) var rate_of_fire: float = weapon_data.get("rate_of_fire", 0.2) var bullet_capacity: int = weapon_data.get("bullet_capacity", 50) var reload_time: float = weapon_data.get("reload_time", 1.0) var infinite_ammo: bool = weapon_data.get("infinite_ammo", false) var recharge_time: float = weapon_data.get("recharge_time", 0.5) var recharge_amount: int = weapon_data.get("recharge_amount", 5) var bullets_per_shot: int = weapon_data.get("bullets_per_shot", 1) var spread_angle: float = weapon_data.get("spread_angle", 0.0) var random_spread: float = weapon_data.get("random_spread", 0.0) # Append 2D or 3D to the end of the key var dimension_suffix = "_3D" if is_3d else "_2D" var weapon_resource_path: String = "res://Resources/Weapons/" + weapon_item_key + dimension_suffix + ".tres" var item_resource_path: String = "res://Resources/Items/" + weapon_item_key + "_Item" + dimension_suffix + ".tres" var items_database_path: String = "res://Resources/ItemsDatabase.tres" # Feedback to the UI dock_instance.call("add_log", "=== Starting Weapon Creation ===") dock_instance.call("add_log", "Weapon Name: " + weapon_name) dock_instance.call("add_log", "Item Key: " + weapon_item_key) # Step 1: Create WeaponResource if _create_weapon_resource(weapon_resource_path, weapon_name, weapon_item_key, ammo_key, default_bullet_path, priority, ammo_per_shot, rate_of_fire, bullet_capacity, reload_time, infinite_ammo, recharge_time, recharge_amount, bullets_per_shot, spread_angle, random_spread): dock_instance.call("add_log", "✓ Created WeaponResource at: " + weapon_resource_path, Color.GREEN) else: dock_instance.call("add_log", "✗ Failed to create WeaponResource", Color.RED) dock_instance.call("set_creation_complete") return # Step 2: Create LootItem resource if _create_loot_item_resource(item_resource_path, weapon_name, weapon_short_name, weapon_description, weapon_item_key, weapon_resource_path, sprite_resource, is_3d): dock_instance.call("add_log", "✓ Created LootItem at: " + item_resource_path, Color.GREEN) else: dock_instance.call("add_log", "✗ Failed to create LootItem", Color.RED) dock_instance.call("set_creation_complete") return # Step 3: Add to ItemsDatabase if _add_to_items_database(items_database_path, item_resource_path): dock_instance.call("add_log", "✓ Added to ItemsDatabase", Color.GREEN) else: dock_instance.call("add_log", "✗ Failed to add to ItemsDatabase", Color.RED) dock_instance.call("set_creation_complete") return dock_instance.call("add_log", "=== Weapon Creation Complete ===", Color.CYAN) dock_instance.call("add_log", "Next steps:") dock_instance.call("add_log", "1. Add sounds to the weapon resource if needed") dock_instance.call("add_log", "2. Test the weapon in-game") dock_instance.call("set_creation_complete") # Refresh the filesystem get_editor_interface().get_resource_filesystem().scan() func _create_weapon_resource(path: String, weapon_name: String, item_key: String, ammo_key: String, bullet_path: String, priority: int, ammo_per_shot: int, rate_of_fire: float, bullet_capacity: int, reload_time: float, infinite_ammo: bool, recharge_time: float, recharge_amount: int, bullets_per_shot: int, spread_angle: float, random_spread: float) -> bool: # Check if file already exists if ResourceLoader.exists(path): dock_instance.call("add_log", "Warning: WeaponResource already exists at " + path, Color.YELLOW) return false # Load the WeaponResource script var weapon_script = load("res://Scripts/Resources/WeaponResource.cs") if weapon_script == null: dock_instance.call("add_log", "Error: Could not load WeaponResource.cs script", Color.RED) return false # Load the bullet resource var bullet_resource = load(bullet_path) if bullet_resource == null: dock_instance.call("add_log", "Error: Could not load bullet resource from " + bullet_path, Color.RED) return false # Create new WeaponResource var weapon_resource = Resource.new() weapon_resource.set_script(weapon_script) # Set basic properties weapon_resource.set("Name", weapon_name) weapon_resource.set("BulletData", bullet_resource) weapon_resource.set("ItemKey", item_key) weapon_resource.set("AmmoKey", ammo_key) # Set weapon stats weapon_resource.set("Priority", priority) weapon_resource.set("AmmoPerShot", ammo_per_shot) weapon_resource.set("RateOfFire", rate_of_fire) weapon_resource.set("BulletCapacity", bullet_capacity) weapon_resource.set("ReloadTime", reload_time) weapon_resource.set("InfiniteAmmo", infinite_ammo) weapon_resource.set("AutoReload", true) weapon_resource.set("RechargeTime", recharge_time) weapon_resource.set("RechargeAmount", recharge_amount) weapon_resource.set("BulletsPerShot", bullets_per_shot) weapon_resource.set("SpreadAngle", spread_angle) weapon_resource.set("RandomSpread", random_spread) # Save the resource var err = ResourceSaver.save(weapon_resource, path) if err != OK: dock_instance.call("add_log", "Error saving WeaponResource: " + str(err), Color.RED) return false return true func _create_loot_item_resource(path: String, item_name: String, short_name: String, description: String, item_key: String, weapon_resource_path: String, sprite_resource: Texture2D, is_3d: bool) -> bool: # Check if file already exists if ResourceLoader.exists(path): dock_instance.call("add_log", "Warning: LootItem already exists at " + path, Color.YELLOW) return false # Load the LootItem script var loot_item_script = load("res://Scripts/Resources/LootItem.cs") if loot_item_script == null: dock_instance.call("add_log", "Error: Could not load LootItem.cs script", Color.RED) return false # Load the weapon resource we just created var weapon_resource = load(weapon_resource_path) if weapon_resource == null: dock_instance.call("add_log", "Error: Could not load weapon resource from " + weapon_resource_path, Color.RED) return false # Create new LootItem var loot_item = Resource.new() loot_item.set_script(loot_item_script) # Set properties loot_item.set("ItemName", item_name) loot_item.set("ShortName", short_name) loot_item.set("ItemDescription", description) loot_item.set("ItemKey", item_key) # ItemTypes.Weapon enum value var item_types_script = load("res://Scripts/ItemTypes.cs") var weapon_enum_value = 9 # ItemTypes.Weapon = 9 (from enum definition) loot_item.set("Item", weapon_enum_value) # Set weapon data in appropriate property based on mode if is_3d: loot_item.set("WeaponData3D", weapon_resource) else: loot_item.set("WeaponData", weapon_resource) loot_item.set("Amount", 1) loot_item.set("Max", 1) loot_item.set("Selectable", true) loot_item.set("DropScenePath3D", "res://Scenes/Items/GenericItem3D.tscn") # Set sprite if provided (supports all Texture2D types including AtlasTexture) if sprite_resource != null: loot_item.set("InventorySprite", sprite_resource) var sprite_type = sprite_resource.get_class() dock_instance.call("add_log", "✓ Set inventory sprite (" + sprite_type + ")", Color.GREEN) # Save the resource var err = ResourceSaver.save(loot_item, path) if err != OK: dock_instance.call("add_log", "Error saving LootItem: " + str(err), Color.RED) return false return true func _add_to_items_database(database_path: String, item_resource_path: String) -> bool: # Load the ItemsDatabase var items_database = load(database_path) if items_database == null: dock_instance.call("add_log", "Error: Could not load ItemsDatabase from " + database_path, Color.RED) return false # Load the item we just created var new_item = load(item_resource_path) if new_item == null: dock_instance.call("add_log", "Error: Could not load item from " + item_resource_path, Color.RED) return false # Get current items array var loot_items = items_database.get("LootItems") if loot_items == null: dock_instance.call("add_log", "Error: Could not get LootItems array from database", Color.RED) return false # Check if item already exists for item in loot_items: if item.resource_path == item_resource_path: dock_instance.call("add_log", "Warning: Item already exists in database", Color.YELLOW) return false # Append the new item loot_items.append(new_item) items_database.set("LootItems", loot_items) # Save the database var err = ResourceSaver.save(items_database, database_path) if err != OK: dock_instance.call("add_log", "Error saving ItemsDatabase: " + str(err), Color.RED) return false return true func _on_create_bullet_requested(bullet_data: Dictionary) -> void: var bullet_name: String = bullet_data.get("bullet_name", "new_bullet") var is_3d: bool = bullet_data.get("is_3d", true) var bullets_dir = "res://Resources/Bullets/" if is_3d: bullets_dir += "3D/" var bullet_path = bullets_dir + bullet_name + ".tres" dock_instance.call("add_log", "=== Starting Bullet Creation ===") dock_instance.call("add_log", "Bullet Name: " + bullet_name) dock_instance.call("add_log", "Mode: " + ("3D" if is_3d else "2D")) if _create_bullet_resource(bullet_path, bullet_data): dock_instance.call("add_log", "✓ Created BulletResource at: " + bullet_path, Color.GREEN) else: dock_instance.call("add_log", "✗ Failed to create BulletResource", Color.RED) dock_instance.call("set_creation_complete") return dock_instance.call("add_log", "=== Bullet Creation Complete ===", Color.CYAN) dock_instance.call("add_log", "Next steps:") dock_instance.call("add_log", "1. Test the bullet in-game") dock_instance.call("add_log", "2. Adjust properties as needed") dock_instance.call("set_creation_complete") get_editor_interface().get_resource_filesystem().scan() func _create_bullet_resource(path: String, bullet_data: Dictionary) -> bool: if ResourceLoader.exists(path): dock_instance.call("add_log", "Warning: BulletResource already exists at " + path, Color.YELLOW) return false var bullet_script = load("res://Scripts/Resources/BulletResource.cs") if bullet_script == null: dock_instance.call("add_log", "Error: Could not load BulletResource.cs script", Color.RED) return false var bullet_resource = Resource.new() bullet_resource.set_script(bullet_script) # Set properties from bullet_data var bullet_sprite = bullet_data.get("bullet_sprite", null) if bullet_sprite: bullet_resource.set("BulletSprite", bullet_sprite) var bullet_scene = bullet_data.get("bullet_scene", null) if bullet_scene: bullet_resource.set("BulletScene", bullet_scene) bullet_resource.set("BulletSize", bullet_data.get("bullet_size", 1.0)) bullet_resource.set("BulletSpeed", bullet_data.get("bullet_speed", 100.0)) bullet_resource.set("BulletDamage", bullet_data.get("bullet_damage", 1.0)) bullet_resource.set("MaxDamage", bullet_data.get("max_damage", 1.0)) bullet_resource.set("Knockback", bullet_data.get("knockback", 1.0)) bullet_resource.set("LifeTime", bullet_data.get("life_time", 10.0)) bullet_resource.set("GrazeValue", bullet_data.get("graze_value", 0.2)) var destruction_particles = bullet_data.get("destruction_particles_scene", null) if destruction_particles: bullet_resource.set("DestructionParticlesScene", destruction_particles) # Set default Direction bullet_resource.set("Direction", Vector2.RIGHT) var err = ResourceSaver.save(bullet_resource, path) if err != OK: dock_instance.call("add_log", "Error saving BulletResource: " + str(err), Color.RED) return false return true