diff --git a/.claude/project-context.md b/.claude/project-context.md index 8e7b0af..9ce60b3 100644 --- a/.claude/project-context.md +++ b/.claude/project-context.md @@ -9,6 +9,37 @@ Quick reference for Claude Code sessions. - **Founders**: Andrew Madison & Justin Madison - **Organization**: JustInternetAI +## GitHub Configuration +- **Project Board**: Agent Arena Development Board (Project #3) +- **Project Board ID**: `PVT_kwDODG39W84BHw8k` +- **Issue Labels**: + - `enhancement`: New feature or request + - `backend`: LLM backends and inference + - `tools`: Agent tools + - `memory`: Memory systems + - `evals`: Evaluation and benchmarks + - `critical`: Critical priority + - `high-priority`: High priority + +### GitHub CLI Commands +```bash +# List projects +gh project list --owner JustInternetAI + +# View project board +gh project view 3 --owner JustInternetAI + +# Create issue (may auto-add to project if automation enabled) +gh issue create --title "Title" --body "Description" --label "enhancement" + +# Create issue and add to project +gh issue create --title "Title" --body "Description" --label "enhancement" +gh project item-add 3 --owner JustInternetAI --url https://github.com/JustInternetAI/AgentArena/issues/ISSUE_NUMBER + +# Refresh auth with project scopes (if needed) +gh auth refresh -h github.com -s read:project -s project +``` + ## Tech Stack - **Godot 4.5**: C++ GDExtension module for simulation - **Python 3.11**: Agent runtime, LLM backends, tools (3.11 required - many ML packages don't support 3.14 yet) diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..ff2eb0e --- /dev/null +++ b/.gitattributes @@ -0,0 +1,33 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Ensure these files always have LF endings (even on Windows) +*.cpp text eol=lf +*.h text eol=lf +*.hpp text eol=lf +*.c text eol=lf +*.gd text eol=lf +*.tscn text eol=lf +*.tres text eol=lf +*.gdshader text eol=lf +*.md text eol=lf +*.txt text eol=lf +CMakeLists.txt text eol=lf +*.cmake text eol=lf + +# Windows-specific files should use CRLF +*.bat text eol=crlf +*.ps1 text eol=crlf +*.cmd text eol=crlf + +# Binary files +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.dll binary +*.so binary +*.dylib binary +*.exe binary +*.app binary diff --git a/BUILD_GUIDE.md b/BUILD_GUIDE.md new file mode 100644 index 0000000..0d36113 --- /dev/null +++ b/BUILD_GUIDE.md @@ -0,0 +1,84 @@ +# Build Guide for Agent Arena GDExtension + +## Quick Start + +### Rebuild Everything (Recommended) +```powershell +.\rebuild_clean.ps1 +``` +This script will: +1. Clean the build +2. Build Debug configuration +3. Build Release configuration +4. Output DLLs to `bin/windows/` with correct names + +### Build Debug Only +```powershell +cmake --build godot/build --config Debug +``` + +### Build Release Only +```powershell +cmake --build godot/build --config Release +``` + +### Force Clean Rebuild +```powershell +cmake --build godot/build --config Debug --clean-first +``` + +## After Building + +### Clear Godot Cache +If Godot doesn't pick up changes, clear the cache: +```powershell +Remove-Item .godot -Recurse -Force +``` +Then restart Godot editor. + +### Verify Build +Check DLL timestamps: +```powershell +Get-Item bin/windows/*.dll | Select-Object Name, LastWriteTime +``` + +## Build Output Locations + +- **Debug DLL**: `bin/windows/libagent_arena.windows.template_debug.x86_64.dll` +- **Release DLL**: `bin/windows/libagent_arena.windows.template_release.x86_64.dll` + +## CMake Configuration + +The project uses CMake with Visual Studio generator (multi-config). + +### Reconfigure CMake (if CMakeLists.txt changes) +```powershell +cmake -S godot -B godot/build -G "Visual Studio 17 2022" -A x64 +``` + +## Troubleshooting + +### "cmake: command not found" +CMake needs to be in your PATH. Either: +1. Restart your terminal/VS Code after installing CMake +2. Use full path: `& "C:\Program Files\CMake\bin\cmake.exe"` + +### "EventBus node not found in scene" +1. Make sure DLL was rebuilt: `Get-Item bin/windows/*.dll | Select-Object LastWriteTime` +2. Clear Godot cache: `Remove-Item .godot -Recurse -Force` +3. Restart Godot editor + +### Wrong DLL location +If DLL goes to `bin/windows/Debug/`, the CMakeLists.txt wasn't updated correctly. +Make sure lines 96-105 in `godot/CMakeLists.txt` have the `RUNTIME_OUTPUT_DIRECTORY_*` properties. + +## Architecture Notes + +The GDExtension includes these C++ classes: +- `SimulationManager` - Manages simulation tick loop +- `EventBus` - Handles event recording/replay (critical for deterministic simulation) +- `Agent` - Agent representation with perception/action +- `ToolRegistry` - Manages available agent tools +- `IPCClient` - Communication with Python runtime + +All classes are registered in `godot/src/register_types.cpp`. diff --git a/clear_godot_cache.ps1 b/clear_godot_cache.ps1 new file mode 100644 index 0000000..c82aceb --- /dev/null +++ b/clear_godot_cache.ps1 @@ -0,0 +1,16 @@ +# Clear Godot cache to fix class registration issues +Write-Host "Clearing Godot cache..." -ForegroundColor Cyan + +$cachePath = "c:\Projects\Agent Arena\.godot" + +if (Test-Path $cachePath) { + Write-Host "Found .godot cache directory" -ForegroundColor Yellow + + # Remove the entire .godot directory + Remove-Item "$cachePath\*" -Recurse -Force -Exclude ".gdignore" + + Write-Host "Cache cleared!" -ForegroundColor Green + Write-Host "Restart Godot to regenerate the cache." -ForegroundColor Cyan +} else { + Write-Host "No cache directory found at $cachePath" -ForegroundColor Yellow +} diff --git a/copy_dll.ps1 b/copy_dll.ps1 new file mode 100644 index 0000000..3a87eca --- /dev/null +++ b/copy_dll.ps1 @@ -0,0 +1,25 @@ +# Copy the newly built DLL to the correct location for Godot +Write-Host "Copying newly built DLL to correct location..." -ForegroundColor Cyan + +$sourceDll = "c:\Projects\Agent Arena\bin\windows\Debug\libagent_arena.windows.template_release.x86_64.dll" +$targetDll = "c:\Projects\Agent Arena\bin\windows\libagent_arena.windows.template_debug.x86_64.dll" + +# Check if source exists +if (Test-Path $sourceDll) { + Write-Host "Found newly built DLL in Debug folder" -ForegroundColor Green + Write-Host "Source: $sourceDll" -ForegroundColor Gray + + # Show file info + $fileInfo = Get-Item $sourceDll + Write-Host "Build time: $($fileInfo.LastWriteTime)" -ForegroundColor Gray + Write-Host "Size: $([math]::Round($fileInfo.Length / 1MB, 2)) MB" -ForegroundColor Gray + + # Copy to target location + Write-Host "`nCopying to: $targetDll" -ForegroundColor Yellow + Copy-Item $sourceDll $targetDll -Force + + Write-Host "`nDone! DLL has been copied." -ForegroundColor Green + Write-Host "You can now restart Godot and test the scene." -ForegroundColor Cyan +} else { + Write-Host "Error: Source DLL not found at $sourceDll" -ForegroundColor Red +} diff --git a/fix_dll.ps1 b/fix_dll.ps1 new file mode 100644 index 0000000..726ff56 --- /dev/null +++ b/fix_dll.ps1 @@ -0,0 +1,26 @@ +# Script to replace the old DLL with the newly built one +Write-Host "Fixing DLL issue..." -ForegroundColor Cyan + +$binPath = "c:\Projects\Agent Arena\bin\windows" +$oldDll = "$binPath\libagent_arena.windows.template_debug.x86_64.dll" +$newDll = "$binPath\~libagent_arena.windows.template_debug.x86_64.dll" + +# Check if new DLL exists +if (Test-Path $newDll) { + Write-Host "Found newly built DLL (with ~ prefix)" -ForegroundColor Green + + # Remove old DLL if it exists + if (Test-Path $oldDll) { + Write-Host "Removing old DLL..." -ForegroundColor Yellow + Remove-Item $oldDll -Force + } + + # Rename new DLL to correct name + Write-Host "Renaming new DLL to correct name..." -ForegroundColor Yellow + Move-Item $newDll $oldDll -Force + + Write-Host "Done! DLL has been updated." -ForegroundColor Green + Write-Host "You can now restart Godot and test." -ForegroundColor Cyan +} else { + Write-Host "Error: New DLL not found at $newDll" -ForegroundColor Red +} diff --git a/godot/CMakeLists.txt b/godot/CMakeLists.txt index f6dfdbd..cd4e6f9 100644 --- a/godot/CMakeLists.txt +++ b/godot/CMakeLists.txt @@ -23,11 +23,18 @@ elseif(UNIX) set(PLATFORM_ARCH "x86_64") endif() -# Build type -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(BUILD_TYPE "template_debug") +# Build type (handle both single-config and multi-config generators) +if(CMAKE_BUILD_TYPE) + # Single-config generator (Ninja, Unix Makefiles) + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(BUILD_TYPE "template_debug") + else() + set(BUILD_TYPE "template_release") + endif() else() - set(BUILD_TYPE "template_release") + # Multi-config generator (Visual Studio, Xcode) + # Use generator expression for build type + set(BUILD_TYPE "$,template_debug,template_release>") endif() # godot-cpp path (you'll need to clone godot-cpp as a submodule or dependency) @@ -86,9 +93,16 @@ endif() # Output directory set(OUTPUT_NAME "libagent_arena.${PLATFORM_NAME}.${BUILD_TYPE}.${PLATFORM_ARCH}") set_target_properties(${PROJECT_NAME} PROPERTIES - OUTPUT_NAME ${OUTPUT_NAME} + OUTPUT_NAME_DEBUG "libagent_arena.${PLATFORM_NAME}.template_debug.${PLATFORM_ARCH}" + OUTPUT_NAME_RELEASE "libagent_arena.${PLATFORM_NAME}.template_release.${PLATFORM_ARCH}" + OUTPUT_NAME_RELWITHDEBINFO "libagent_arena.${PLATFORM_NAME}.template_release.${PLATFORM_ARCH}" + OUTPUT_NAME_MINSIZEREL "libagent_arena.${PLATFORM_NAME}.template_release.${PLATFORM_ARCH}" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../bin/${PLATFORM_NAME}" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../bin/${PLATFORM_NAME}" + LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../bin/${PLATFORM_NAME}" + LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../bin/${PLATFORM_NAME}" + RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../bin/${PLATFORM_NAME}" + RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../bin/${PLATFORM_NAME}" ) # Install rules diff --git a/godot/include/agent_arena.h b/godot/include/agent_arena.h index 5b6bbf4..7f95bc5 100644 --- a/godot/include/agent_arena.h +++ b/godot/include/agent_arena.h @@ -2,6 +2,7 @@ #define AGENT_ARENA_H #include +#include #include #include #include @@ -33,7 +34,7 @@ class SimulationManager : public godot::Node { uint64_t current_tick; double tick_rate; bool is_running; - godot::Ref event_bus; + EventBus* event_bus; protected: static void _bind_methods(); @@ -42,6 +43,7 @@ class SimulationManager : public godot::Node { SimulationManager(); ~SimulationManager(); + void _ready() override; void _process(double delta) override; void _physics_process(double delta) override; @@ -64,8 +66,8 @@ class SimulationManager : public godot::Node { /** * Event bus for deterministic event ordering and replay */ -class EventBus : public godot::RefCounted { - GDCLASS(EventBus, godot::RefCounted) +class EventBus : public godot::Node { + GDCLASS(EventBus, godot::Node) private: struct Event { @@ -97,8 +99,8 @@ class EventBus : public godot::RefCounted { /** * Base agent class with perception, memory, and action capabilities */ -class Agent : public godot::Node { - GDCLASS(Agent, godot::Node) +class Agent : public godot::Node3D { + GDCLASS(Agent, godot::Node3D) private: godot::String agent_id; @@ -137,8 +139,8 @@ class Agent : public godot::Node { /** * Tool registry for managing available agent actions */ -class ToolRegistry : public godot::RefCounted { - GDCLASS(ToolRegistry, godot::RefCounted) +class ToolRegistry : public godot::Node { + GDCLASS(ToolRegistry, godot::Node) private: godot::Dictionary registered_tools; diff --git a/godot/rebuild.ps1 b/godot/rebuild.ps1 new file mode 100644 index 0000000..73f71d3 --- /dev/null +++ b/godot/rebuild.ps1 @@ -0,0 +1,15 @@ +# Quick rebuild script for Agent Arena GDExtension +Set-Location -Path "c:\Projects\Agent Arena\godot\build" + +Write-Host "Building Agent Arena GDExtension..." -ForegroundColor Cyan + +# Try using cmake +cmake --build . --config Debug + +if ($LASTEXITCODE -eq 0) { + Write-Host "Build successful!" -ForegroundColor Green + Write-Host "DLL location: c:\Projects\Agent Arena\bin\windows\" -ForegroundColor Yellow +} else { + Write-Host "Build failed with exit code $LASTEXITCODE" -ForegroundColor Red + exit $LASTEXITCODE +} diff --git a/godot/src/agent_arena.cpp b/godot/src/agent_arena.cpp index 8f6f761..18b2453 100644 --- a/godot/src/agent_arena.cpp +++ b/godot/src/agent_arena.cpp @@ -9,8 +9,7 @@ using namespace agent_arena; // ============================================================================ SimulationManager::SimulationManager() - : current_tick(0), tick_rate(60.0), is_running(false) { - event_bus.instantiate(); + : current_tick(0), tick_rate(60.0), is_running(false), event_bus(nullptr) { } SimulationManager::~SimulationManager() {} @@ -37,6 +36,18 @@ void SimulationManager::_bind_methods() { ADD_SIGNAL(MethodInfo("simulation_stopped")); } +void SimulationManager::_ready() { + // Get EventBus from the scene tree (sibling node) + Node* parent = get_parent(); + if (parent) { + event_bus = Object::cast_to(parent->get_node_or_null("EventBus")); + if (event_bus) { + UtilityFunctions::print("SimulationManager: EventBus connected"); + } + // Note: EventBus is optional - scenes without it will simply not record events + } +} + void SimulationManager::_process(double delta) { if (!is_running) return; @@ -50,14 +61,18 @@ void SimulationManager::_physics_process(double delta) { void SimulationManager::start_simulation() { is_running = true; - event_bus->start_recording(); + if (event_bus) { + event_bus->start_recording(); + } emit_signal("simulation_started"); UtilityFunctions::print("Simulation started at tick ", current_tick); } void SimulationManager::stop_simulation() { is_running = false; - event_bus->stop_recording(); + if (event_bus) { + event_bus->stop_recording(); + } emit_signal("simulation_stopped"); UtilityFunctions::print("Simulation stopped at tick ", current_tick); } @@ -67,16 +82,20 @@ void SimulationManager::step_simulation() { emit_signal("tick_advanced", current_tick); // Process all pending events for this tick - Array events = event_bus->get_events_for_tick(current_tick); - for (int i = 0; i < events.size(); i++) { - // Process each event + if (event_bus) { + Array events = event_bus->get_events_for_tick(current_tick); + for (int i = 0; i < events.size(); i++) { + // Process each event + } } } void SimulationManager::reset_simulation() { current_tick = 0; is_running = false; - event_bus->clear_events(); + if (event_bus) { + event_bus->clear_events(); + } UtilityFunctions::print("Simulation reset"); } diff --git a/rebuild_clean.ps1 b/rebuild_clean.ps1 new file mode 100644 index 0000000..45a7a5d --- /dev/null +++ b/rebuild_clean.ps1 @@ -0,0 +1,40 @@ +# Force a clean rebuild of the GDExtension +Write-Host "Forcing clean rebuild..." -ForegroundColor Cyan + +Set-Location "c:\Projects\Agent Arena\godot\build" + +# Rebuild Debug +Write-Host "Building Debug configuration..." -ForegroundColor Yellow +cmake --build . --config Debug --clean-first + +if ($LASTEXITCODE -eq 0) { + Write-Host "`nDebug build successful!" -ForegroundColor Green + + $debugDll = "c:\Projects\Agent Arena\bin\windows\libagent_arena.windows.template_debug.x86_64.dll" + if (Test-Path $debugDll) { + $fileInfo = Get-Item $debugDll + Write-Host "Debug DLL timestamp: $($fileInfo.LastWriteTime)" -ForegroundColor Gray + } +} else { + Write-Host "`nDebug build failed!" -ForegroundColor Red + exit 1 +} + +# Rebuild Release +Write-Host "`nBuilding Release configuration..." -ForegroundColor Yellow +cmake --build . --config Release + +if ($LASTEXITCODE -eq 0) { + Write-Host "`nRelease build successful!" -ForegroundColor Green + + $releaseDll = "c:\Projects\Agent Arena\bin\windows\libagent_arena.windows.template_release.x86_64.dll" + if (Test-Path $releaseDll) { + $fileInfo = Get-Item $releaseDll + Write-Host "Release DLL timestamp: $($fileInfo.LastWriteTime)" -ForegroundColor Gray + } + + Write-Host "`nAll builds completed successfully!" -ForegroundColor Green +} else { + Write-Host "`nRelease build failed!" -ForegroundColor Red + exit 1 +} diff --git a/scenes/README_CAPTURE_POINTS.md b/scenes/README_CAPTURE_POINTS.md new file mode 100644 index 0000000..54a76d3 --- /dev/null +++ b/scenes/README_CAPTURE_POINTS.md @@ -0,0 +1,136 @@ +# Capture Point Scene Usage + +## Overview +The capture point is a reusable scene component for creating territorial control objectives in team-based benchmarks. + +## Files +- **Scene**: `scenes/capture_point.tscn` +- **Script**: `scripts/capture_point.gd` + +## Features + +### Visual Feedback +- **Color coding** based on ownership: + - Gray: Neutral + - Blue: Blue team controlled + - Red: Red team controlled +- **Progress bar** appears during capture attempts +- **3D label** shows status and agent count +- **Emission effects** on controlled points + +### Exported Properties +- `point_name` (String): Display name for the capture point +- `capture_radius` (float): Detection radius for agents (default: 3.0) + +## How to Use + +### Adding to a Scene +1. In Godot editor, navigate to `scenes/capture_point.tscn` +2. Drag and drop into your scene +3. Position using the Transform tool +4. Set the `point_name` in the Inspector + +### Example Scene Structure +``` +TeamCaptureScene (Node3D) +├── CapturePoints (Node3D) +│ ├── PointA (CapturePoint) - transform: (-15, 0.5, -15) +│ ├── PointB (CapturePoint) - transform: (15, 0.5, -15) +│ └── PointC (CapturePoint) - transform: (0, 0.5, 0) +``` + +### Scripting with Capture Points + +#### Getting Capture Point State +```gdscript +# Initialize capture points +var capture_points = [] +var points_node = $CapturePoints + +for child in points_node.get_children(): + if child.has_method("get_state"): + var state = child.get_state() + capture_points.append(state) +``` + +#### State Dictionary Structure +```gdscript +{ + "name": "Point A", + "position": Vector3(-15, 0.5, -15), + "owner": "neutral", # or "blue", "red" + "capture_progress": 0.0, + "capturing_team": "", + "agents_present": [], + "node": +} +``` + +#### Updating Visual Feedback +```gdscript +# Update capture progress (0.0 to 1.0) +point.node.set_capture_progress(0.75, "blue") + +# Set ownership +point.node.set_owner_team("blue") + +# Reset capture state +point.node.reset_capture() +``` + +## API Reference + +### Methods + +#### `get_state() -> Dictionary` +Returns the current state of the capture point including position, ownership, and capture progress. + +#### `set_owner_team(team: String)` +Sets the owning team. Valid values: "neutral", "blue", "red" +Updates visual appearance automatically. + +#### `set_capture_progress(progress: float, team: String)` +Updates capture progress (0.0 - 1.0) and shows progress bar. +- `progress`: Float between 0.0 and 1.0 +- `team`: Team attempting capture ("blue" or "red") + +#### `reset_capture()` +Resets capture progress and hides progress bar. + +## Customization + +### Adjusting Size +Modify in the scene file or script: +- Platform radius: Edit CylinderMesh in `$Platform` +- Detection radius: Change `capture_radius` export variable +- Collision shape: Edit CylinderShape3D in `$CollisionShape3D` + +### Changing Colors +Edit materials in `_ready()` function: +```gdscript +blue_material.albedo_color = Color(0.2, 0.4, 0.9, 1.0) +blue_material.emission = Color(0.1, 0.2, 0.5, 1.0) +``` + +### Label Customization +Modify `$StatusLabel` properties: +- Font size: `font_size = 24` +- Outline: `outline_size = 8` +- Billboard mode: `billboard = 1` (always face camera) + +## Integration with Team Capture Benchmark + +The capture point scenes are designed to work seamlessly with the team capture benchmark: + +1. **Automatic Detection**: The benchmark automatically finds all CapturePoint instances +2. **Visual Updates**: Progress and ownership are updated automatically +3. **Agent Tracking**: Agents within radius are tracked and displayed +4. **Event Recording**: Captures are logged through the EventBus system + +## Tips + +- Place capture points at strategic locations to encourage team tactics +- Use odd numbers of points (3, 5, 7) to avoid stalemates +- Position points 10-15 units apart for balanced gameplay +- Consider spawn distances when placing points (teams spawn at ±20 units) +- Center point should be hotly contested - place it equidistant from both spawns diff --git a/scenes/capture_point.tscn b/scenes/capture_point.tscn new file mode 100644 index 0000000..cee3fec --- /dev/null +++ b/scenes/capture_point.tscn @@ -0,0 +1,41 @@ +[gd_scene load_steps=5 format=3 uid="uid://capture_point_scene"] + +[ext_resource type="Script" path="res://scripts/capture_point.gd" id="1_capture_point"] + +[sub_resource type="CylinderMesh" id="CylinderMesh_platform"] +top_radius = 3.0 +bottom_radius = 3.0 +height = 0.2 + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_neutral"] +albedo_color = Color(0.7, 0.7, 0.7, 1) +metallic = 0.3 +roughness = 0.7 + +[sub_resource type="CylinderShape3D" id="CylinderShape3D_area"] +radius = 3.0 +height = 5.0 + +[node name="CapturePoint" type="Area3D"] +script = ExtResource("1_capture_point") + +[node name="Platform" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0) +mesh = SubResource("CylinderMesh_platform") +surface_material_override/0 = SubResource("StandardMaterial3D_neutral") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, 0) +shape = SubResource("CylinderShape3D_area") + +[node name="CaptureProgressBar" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3.5, 0) +visible = false + +[node name="StatusLabel" type="Label3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4, 0) +billboard = 1 +text = "Neutral" +font_size = 24 +outline_size = 8 +outline_modulate = Color(0, 0, 0, 1) diff --git a/scenes/crafting_chain.tscn b/scenes/crafting_chain.tscn index a9cc07b..9fc3681 100644 --- a/scenes/crafting_chain.tscn +++ b/scenes/crafting_chain.tscn @@ -1,9 +1,18 @@ -[gd_scene load_steps=3 format=3 uid="uid://crafting_chain_scene"] +[gd_scene load_steps=8 format=3 uid="uid://b6w2wbpm323nc"] -[ext_resource type="Script" path="res://scripts/crafting_chain.gd" id="1_crafting"] +[ext_resource type="Script" uid="uid://b5jfvj0m2vh0m" path="res://scripts/crafting_chain.gd" id="1_crafting"] +[ext_resource type="PackedScene" uid="uid://ds214tpdao70a" path="res://scenes/resources/iron_ore.tscn" id="2_pxew1"] +[ext_resource type="PackedScene" uid="uid://0rkuoje480am" path="res://scenes/resources/wood.tscn" id="3_fmpvf"] +[ext_resource type="PackedScene" uid="uid://b6a6y5yl011cr" path="res://scenes/stations/anvil.tscn" id="4_d1mqj"] +[ext_resource type="PackedScene" uid="uid://5pkkwbyi8esy" path="res://scenes/stations/furnace.tscn" id="5_mp2gt"] +[ext_resource type="PackedScene" uid="uid://lmo3kerl5nym" path="res://scenes/stations/workbench.tscn" id="6_8dtr0"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ground"] +albedo_color = Color(0.5, 0.5, 0.5, 1) [sub_resource type="BoxMesh" id="BoxMesh_ground"] size = Vector3(40, 0.5, 40) +material = SubResource("StandardMaterial3D_ground") [node name="CraftingChainScene" type="Node3D"] script = ExtResource("1_crafting") @@ -26,66 +35,28 @@ shadow_enabled = true [node name="BaseResources" type="Node3D" parent="."] -[node name="IronOre1" type="Area3D" parent="BaseResources"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10, 0.5, -10) - -[node name="MeshInstance3D" type="MeshInstance3D" parent="BaseResources/IronOre1"] -mesh = SubResource("BoxMesh_ground") +[node name="IronOre1" parent="BaseResources" instance=ExtResource("2_pxew1")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8, 0.5, -5) -[node name="IronOre2" type="Area3D" parent="BaseResources"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -12, 0.5, -8) - -[node name="MeshInstance3D" type="MeshInstance3D" parent="BaseResources/IronOre2"] -mesh = SubResource("BoxMesh_ground") - -[node name="Wood1" type="Area3D" parent="BaseResources"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8, 0.5, -12) - -[node name="MeshInstance3D" type="MeshInstance3D" parent="BaseResources/Wood1"] -mesh = SubResource("BoxMesh_ground") - -[node name="Wood2" type="Area3D" parent="BaseResources"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10, 0.5, -14) - -[node name="MeshInstance3D" type="MeshInstance3D" parent="BaseResources/Wood2"] -mesh = SubResource("BoxMesh_ground") - -[node name="Coal1" type="Area3D" parent="BaseResources"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 10, 0.5, -10) - -[node name="MeshInstance3D" type="MeshInstance3D" parent="BaseResources/Coal1"] -mesh = SubResource("BoxMesh_ground") - -[node name="Coal2" type="Area3D" parent="BaseResources"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 12, 0.5, -12) - -[node name="MeshInstance3D" type="MeshInstance3D" parent="BaseResources/Coal2"] -mesh = SubResource("BoxMesh_ground") +[node name="Wood1" parent="BaseResources" instance=ExtResource("3_fmpvf")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8, 0.5, 5) [node name="CraftingStations" type="Node3D" parent="."] -[node name="Furnace" type="Area3D" parent="CraftingStations"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, -5) - -[node name="MeshInstance3D" type="MeshInstance3D" parent="CraftingStations/Furnace"] -mesh = SubResource("BoxMesh_ground") - -[node name="Anvil" type="Area3D" parent="CraftingStations"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) - -[node name="MeshInstance3D" type="MeshInstance3D" parent="CraftingStations/Anvil"] -mesh = SubResource("BoxMesh_ground") +[node name="Anvil" parent="CraftingStations" instance=ExtResource("4_d1mqj")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5, 0.5, -5) -[node name="Workbench" type="Area3D" parent="CraftingStations"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 5) +[node name="Furnace" parent="CraftingStations" instance=ExtResource("5_mp2gt")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5, 0.75, 0) -[node name="MeshInstance3D" type="MeshInstance3D" parent="CraftingStations/Workbench"] -mesh = SubResource("BoxMesh_ground") +[node name="Workbench" parent="CraftingStations" instance=ExtResource("6_8dtr0")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5, 0.5, 5) [node name="Agents" type="Node3D" parent="."] [node name="Agent1" type="Agent" parent="Agents"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 10) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) +agent_id = "agent_9033" [node name="Camera3D" type="Camera3D" parent="."] transform = Transform3D(1, 0, 0, 0, 0.707107, 0.707107, 0, -0.707107, 0.707107, 0, 20, 20) diff --git a/scenes/foraging.tscn b/scenes/foraging.tscn index 1186f09..8f9906f 100644 --- a/scenes/foraging.tscn +++ b/scenes/foraging.tscn @@ -1,6 +1,10 @@ -[gd_scene load_steps=3 format=3 uid="uid://foraging_scene"] +[gd_scene load_steps=7 format=3 uid="uid://dyr7xuv3evk0g"] -[ext_resource type="Script" path="res://scripts/foraging.gd" id="1_foraging"] +[ext_resource type="Script" uid="uid://cuvvv5nbixqy8" path="res://scripts/foraging.gd" id="1_foraging"] +[ext_resource type="PackedScene" path="res://scenes/resources/berry.tscn" id="2_nlo2w"] +[ext_resource type="PackedScene" path="res://scenes/resources/stone.tscn" id="3_qjgy7"] +[ext_resource type="PackedScene" uid="uid://0rkuoje480am" path="res://scenes/resources/wood.tscn" id="4_jq1ou"] +[ext_resource type="PackedScene" path="res://scenes/resources/pit.tscn" id="5_jrjj6"] [sub_resource type="BoxMesh" id="BoxMesh_ground"] size = Vector3(50, 0.5, 50) @@ -17,6 +21,7 @@ script = ExtResource("1_foraging") [node name="Environment" type="Node3D" parent="."] [node name="Ground" type="MeshInstance3D" parent="Environment"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.13587832, -0.7860099, 0.56352854) mesh = SubResource("BoxMesh_ground") skeleton = NodePath("../..") @@ -26,82 +31,36 @@ shadow_enabled = true [node name="Resources" type="Node3D" parent="."] -[node name="Berry1" type="Area3D" parent="Resources"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5, 0.5, 5) +[node name="Berry" parent="Resources" instance=ExtResource("2_nlo2w")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.2767699, 0.97824025, 0.6348424) -[node name="MeshInstance3D" type="MeshInstance3D" parent="Resources/Berry1"] -mesh = SubResource("BoxMesh_ground") -skeleton = NodePath("../../..") - -[node name="Berry2" type="Area3D" parent="Resources"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8, 0.5, 3) - -[node name="MeshInstance3D" type="MeshInstance3D" parent="Resources/Berry2"] -mesh = SubResource("BoxMesh_ground") -skeleton = NodePath("../../..") - -[node name="Berry3" type="Area3D" parent="Resources"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 10, 0.5, -7) - -[node name="MeshInstance3D" type="MeshInstance3D" parent="Resources/Berry3"] -mesh = SubResource("BoxMesh_ground") -skeleton = NodePath("../../..") - -[node name="Wood1" type="Area3D" parent="Resources"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 0.5, -5) - -[node name="MeshInstance3D" type="MeshInstance3D" parent="Resources/Wood1"] -mesh = SubResource("BoxMesh_ground") -skeleton = NodePath("../../..") - -[node name="Wood2" type="Area3D" parent="Resources"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 12, 0.5, 8) +[node name="Berry2" parent="Resources" instance=ExtResource("2_nlo2w")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.4710245, 1.2601786, -0.5271497) -[node name="MeshInstance3D" type="MeshInstance3D" parent="Resources/Wood2"] -mesh = SubResource("BoxMesh_ground") -skeleton = NodePath("../../..") - -[node name="Stone1" type="Area3D" parent="Resources"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 10) +[node name="Berry3" parent="Resources" instance=ExtResource("2_nlo2w")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.2352296, 1.2772655, -0.11761141) -[node name="MeshInstance3D" type="MeshInstance3D" parent="Resources/Stone1"] -mesh = SubResource("BoxMesh_ground") -skeleton = NodePath("../../..") +[node name="Stone" parent="Resources" instance=ExtResource("3_qjgy7")] +transform = Transform3D(1, 0, 0, 0, 0.9979949, -0.06329565, 0, 0.06329565, 0.9979949, -2.3462286, -0.2733947, 1.451941) -[node name="Stone2" type="Area3D" parent="Resources"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10, 0.5, -8) +[node name="Stone2" parent="Resources" instance=ExtResource("3_qjgy7")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.09641945, -0.15378493, 0.14840579) -[node name="MeshInstance3D" type="MeshInstance3D" parent="Resources/Stone2"] -mesh = SubResource("BoxMesh_ground") -skeleton = NodePath("../../..") +[node name="Wood" parent="Resources" instance=ExtResource("4_jq1ou")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.5196384, 0.18368697, -0.9445286) [node name="Hazards" type="Node3D" parent="."] -[node name="Fire1" type="Area3D" parent="Hazards"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7, 0.5, -3) - -[node name="MeshInstance3D" type="MeshInstance3D" parent="Hazards/Fire1"] -mesh = SubResource("BoxMesh_ground") -skeleton = NodePath("../../..") +[node name="Pit" parent="Hazards" instance=ExtResource("5_jrjj6")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.248175, -0.2904817, 0.86270857) -[node name="Fire2" type="Area3D" parent="Hazards"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 0.5, 7) - -[node name="MeshInstance3D" type="MeshInstance3D" parent="Hazards/Fire2"] -mesh = SubResource("BoxMesh_ground") -skeleton = NodePath("../../..") - -[node name="Pit1" type="Area3D" parent="Hazards"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, -12) - -[node name="MeshInstance3D" type="MeshInstance3D" parent="Hazards/Pit1"] -mesh = SubResource("BoxMesh_ground") -skeleton = NodePath("../../..") +[node name="Stone" parent="Hazards" instance=ExtResource("3_qjgy7")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.29249334, -0.09130466, -1.0156603) [node name="Agents" type="Node3D" parent="."] [node name="Agent1" type="Agent" parent="Agents"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) +agent_id = "agent_2080718" [node name="Camera3D" type="Camera3D" parent="."] transform = Transform3D(1, 0, 0, 0, 0.707107, 0.707107, 0, -0.707107, 0.707107, 0, 20, 20) diff --git a/scenes/resources/berry.tscn b/scenes/resources/berry.tscn new file mode 100644 index 0000000..7c9aaec --- /dev/null +++ b/scenes/resources/berry.tscn @@ -0,0 +1,24 @@ +[gd_scene load_steps=4 format=3 uid="uid://c3r4w5d6e7f8g"] + +[ext_resource type="Script" path="res://scripts/resources/berry.gd" id="1_berry"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_berry"] +albedo_color = Color(0.8, 0.2, 0.3, 1) +roughness = 0.6 + +[sub_resource type="SphereMesh" id="SphereMesh_berry"] +radius = 0.2 +height = 0.4 +material = SubResource("StandardMaterial3D_berry") + +[sub_resource type="SphereShape3D" id="SphereShape_berry"] +radius = 0.2 + +[node name="Berry" type="Area3D"] +script = ExtResource("1_berry") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("SphereMesh_berry") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("SphereShape_berry") diff --git a/scenes/resources/coal.tscn b/scenes/resources/coal.tscn new file mode 100644 index 0000000..bb2f9a3 --- /dev/null +++ b/scenes/resources/coal.tscn @@ -0,0 +1,18 @@ +[gd_scene load_steps=4 format=3 uid="uid://nyjfj2ribuww"] + +[ext_resource type="Script" uid="uid://x2ici4ychhjl" path="res://scripts/resources/coal.gd" id="1_3wt6h"] + +[sub_resource type="BoxMesh" id="BoxMesh_coal"] +size = Vector3(0.4, 0.4, 0.4) + +[sub_resource type="BoxShape3D" id="BoxShape_coal"] +size = Vector3(0.4, 0.4, 0.4) + +[node name="Coal" type="Area3D"] +script = ExtResource("1_3wt6h") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("BoxMesh_coal") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("BoxShape_coal") diff --git a/scenes/resources/fire.tscn b/scenes/resources/fire.tscn new file mode 100644 index 0000000..353db54 --- /dev/null +++ b/scenes/resources/fire.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=4 format=3 uid="uid://e843yss6vwd1"] + +[ext_resource type="Script" path="res://scripts/resources/fire.gd" id="1_fire"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_fire"] +albedo_color = Color(1, 0.5, 0.1, 1) +emission_enabled = true +emission = Color(1, 0.6, 0.2, 1) +emission_energy_multiplier = 2.0 +roughness = 0.3 + +[sub_resource type="BoxMesh" id="BoxMesh_fire"] +size = Vector3(0.4, 0.6, 0.4) +material = SubResource("StandardMaterial3D_fire") + +[sub_resource type="BoxShape3D" id="BoxShape_fire"] +size = Vector3(0.4, 0.6, 0.4) + +[node name="Fire" type="Area3D"] +script = ExtResource("1_fire") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("BoxMesh_fire") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("BoxShape_fire") diff --git a/scenes/resources/iron_ore.tscn b/scenes/resources/iron_ore.tscn new file mode 100644 index 0000000..7422a16 --- /dev/null +++ b/scenes/resources/iron_ore.tscn @@ -0,0 +1,24 @@ +[gd_scene load_steps=4 format=3 uid="uid://ds214tpdao70a"] + +[ext_resource type="Script" uid="uid://do3kh277exd84" path="res://scripts/resources/iron_ore.gd" id="1_nuofo"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ironore"] +albedo_color = Color(0.4, 0.4, 0.45, 1) +metallic = 0.7 +roughness = 0.3 + +[sub_resource type="BoxMesh" id="BoxMesh_ironore"] +size = Vector3(0.5, 0.5, 0.5) +material = SubResource("StandardMaterial3D_ironore") + +[sub_resource type="BoxShape3D" id="BoxShape_ironore"] +size = Vector3(0.5, 0.5, 0.5) + +[node name="IronOre" type="Area3D"] +script = ExtResource("1_nuofo") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("BoxMesh_ironore") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("BoxShape_ironore") diff --git a/scenes/resources/pit.tscn b/scenes/resources/pit.tscn new file mode 100644 index 0000000..492cca6 --- /dev/null +++ b/scenes/resources/pit.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=4 format=3 uid="uid://bbgca5y0d2287"] + +[ext_resource type="Script" path="res://scripts/resources/pit.gd" id="1_pit"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_pit"] +albedo_color = Color(0.3, 0.2, 0.15, 1) +roughness = 0.95 + +[sub_resource type="CylinderMesh" id="CylinderMesh_pit"] +top_radius = 0.6 +bottom_radius = 0.5 +height = 0.3 +material = SubResource("StandardMaterial3D_pit") + +[sub_resource type="CylinderShape3D" id="CylinderShape_pit"] +radius = 0.6 +height = 0.3 + +[node name="Pit" type="Area3D"] +script = ExtResource("1_pit") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("CylinderMesh_pit") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("CylinderShape_pit") diff --git a/scenes/resources/stone.tscn b/scenes/resources/stone.tscn new file mode 100644 index 0000000..f7ab26c --- /dev/null +++ b/scenes/resources/stone.tscn @@ -0,0 +1,23 @@ +[gd_scene load_steps=4 format=3 uid="uid://b8iai0j1k2l3m"] + +[ext_resource type="Script" path="res://scripts/resources/stone.gd" id="1_stone"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_stone"] +albedo_color = Color(0.6, 0.6, 0.65, 1) +roughness = 0.9 + +[sub_resource type="BoxMesh" id="BoxMesh_stone"] +size = Vector3(0.6, 0.5, 0.6) +material = SubResource("StandardMaterial3D_stone") + +[sub_resource type="BoxShape3D" id="BoxShape_stone"] +size = Vector3(0.6, 0.5, 0.6) + +[node name="Stone" type="Area3D"] +script = ExtResource("1_stone") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("BoxMesh_stone") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("BoxShape_stone") diff --git a/scenes/resources/wood.tscn b/scenes/resources/wood.tscn new file mode 100644 index 0000000..7748386 --- /dev/null +++ b/scenes/resources/wood.tscn @@ -0,0 +1,23 @@ +[gd_scene load_steps=4 format=3 uid="uid://0rkuoje480am"] + +[ext_resource type="Script" uid="uid://bmk2e1mwhok8n" path="res://scripts/resources/wood.gd" id="1_0sswb"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_wood"] +albedo_color = Color(0.6, 0.4, 0.2, 1) +roughness = 0.8 + +[sub_resource type="BoxMesh" id="BoxMesh_wood"] +size = Vector3(0.5, 0.8, 0.5) +material = SubResource("StandardMaterial3D_wood") + +[sub_resource type="BoxShape3D" id="BoxShape_wood"] +size = Vector3(0.5, 0.8, 0.5) + +[node name="Wood" type="Area3D"] +script = ExtResource("1_0sswb") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("BoxMesh_wood") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("BoxShape_wood") diff --git a/scenes/stations/anvil.tscn b/scenes/stations/anvil.tscn new file mode 100644 index 0000000..1a73a6a --- /dev/null +++ b/scenes/stations/anvil.tscn @@ -0,0 +1,24 @@ +[gd_scene load_steps=4 format=3 uid="uid://b6a6y5yl011cr"] + +[ext_resource type="Script" uid="uid://dmav7xg8036gn" path="res://scripts/stations/anvil.gd" id="1_ais4u"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_anvil"] +albedo_color = Color(0.3, 0.3, 0.35, 1) +metallic = 0.9 +roughness = 0.4 + +[sub_resource type="BoxMesh" id="BoxMesh_anvil"] +size = Vector3(1.2, 0.8, 1.2) +material = SubResource("StandardMaterial3D_anvil") + +[sub_resource type="BoxShape3D" id="BoxShape_anvil"] +size = Vector3(1.2, 0.8, 1.2) + +[node name="Anvil" type="Area3D"] +script = ExtResource("1_ais4u") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("BoxMesh_anvil") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("BoxShape_anvil") diff --git a/scenes/stations/furnace.tscn b/scenes/stations/furnace.tscn new file mode 100644 index 0000000..1eb38fd --- /dev/null +++ b/scenes/stations/furnace.tscn @@ -0,0 +1,25 @@ +[gd_scene load_steps=4 format=3 uid="uid://5pkkwbyi8esy"] + +[ext_resource type="Script" uid="uid://clba3etrgc4mn" path="res://scripts/stations/furnace.gd" id="1_vboj5"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_furnace"] +albedo_color = Color(0.8, 0.3, 0.2, 1) +emission_enabled = true +emission = Color(1, 0.4, 0.1, 1) +emission_energy_multiplier = 0.3 + +[sub_resource type="BoxMesh" id="BoxMesh_furnace"] +size = Vector3(1.5, 1.5, 1.5) +material = SubResource("StandardMaterial3D_furnace") + +[sub_resource type="BoxShape3D" id="BoxShape_furnace"] +size = Vector3(1.5, 1.5, 1.5) + +[node name="Furnace" type="Area3D"] +script = ExtResource("1_vboj5") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("BoxMesh_furnace") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("BoxShape_furnace") diff --git a/scenes/stations/workbench.tscn b/scenes/stations/workbench.tscn new file mode 100644 index 0000000..d014479 --- /dev/null +++ b/scenes/stations/workbench.tscn @@ -0,0 +1,23 @@ +[gd_scene load_steps=4 format=3 uid="uid://lmo3kerl5nym"] + +[ext_resource type="Script" uid="uid://d4k8tuntpxk7b" path="res://scripts/stations/workbench.gd" id="1_rl4sw"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_workbench"] +albedo_color = Color(0.7, 0.6, 0.4, 1) +roughness = 0.7 + +[sub_resource type="BoxMesh" id="BoxMesh_workbench"] +size = Vector3(2, 1, 1.5) +material = SubResource("StandardMaterial3D_workbench") + +[sub_resource type="BoxShape3D" id="BoxShape_workbench"] +size = Vector3(2, 1, 1.5) + +[node name="Workbench" type="Area3D"] +script = ExtResource("1_rl4sw") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("BoxMesh_workbench") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("BoxShape_workbench") diff --git a/scenes/team_capture.tscn b/scenes/team_capture.tscn index 1e0b57c..4ccfdcc 100644 --- a/scenes/team_capture.tscn +++ b/scenes/team_capture.tscn @@ -1,6 +1,7 @@ -[gd_scene load_steps=3 format=3 uid="uid://team_capture_scene"] +[gd_scene load_steps=4 format=3 uid="uid://team_capture_scene"] [ext_resource type="Script" path="res://scripts/team_capture.gd" id="1_team_capture"] +[ext_resource type="PackedScene" uid="uid://capture_point_scene" path="res://scenes/capture_point.tscn" id="2_capture_point"] [sub_resource type="BoxMesh" id="BoxMesh_ground"] size = Vector3(60, 0.5, 60) @@ -26,35 +27,25 @@ shadow_enabled = true [node name="CapturePoints" type="Node3D" parent="."] -[node name="CapturePointA" type="Area3D" parent="CapturePoints"] +[node name="PointA" parent="CapturePoints" instance=ExtResource("2_capture_point")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15, 0.5, -15) +point_name = "Point A" -[node name="MeshInstance3D" type="MeshInstance3D" parent="CapturePoints/CapturePointA"] -mesh = SubResource("BoxMesh_ground") - -[node name="CapturePointB" type="Area3D" parent="CapturePoints"] +[node name="PointB" parent="CapturePoints" instance=ExtResource("2_capture_point")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 15, 0.5, -15) +point_name = "Point B" -[node name="MeshInstance3D" type="MeshInstance3D" parent="CapturePoints/CapturePointB"] -mesh = SubResource("BoxMesh_ground") - -[node name="CapturePointC" type="Area3D" parent="CapturePoints"] +[node name="PointC" parent="CapturePoints" instance=ExtResource("2_capture_point")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) +point_name = "Center" -[node name="MeshInstance3D" type="MeshInstance3D" parent="CapturePoints/CapturePointC"] -mesh = SubResource("BoxMesh_ground") - -[node name="CapturePointD" type="Area3D" parent="CapturePoints"] +[node name="PointD" parent="CapturePoints" instance=ExtResource("2_capture_point")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15, 0.5, 15) +point_name = "Point D" -[node name="MeshInstance3D" type="MeshInstance3D" parent="CapturePoints/CapturePointD"] -mesh = SubResource("BoxMesh_ground") - -[node name="CapturePointE" type="Area3D" parent="CapturePoints"] +[node name="PointE" parent="CapturePoints" instance=ExtResource("2_capture_point")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 15, 0.5, 15) - -[node name="MeshInstance3D" type="MeshInstance3D" parent="CapturePoints/CapturePointE"] -mesh = SubResource("BoxMesh_ground") +point_name = "Point E" [node name="TeamBlue" type="Node3D" parent="."] diff --git a/scripts/add_collision_shapes.gd b/scripts/add_collision_shapes.gd new file mode 100644 index 0000000..46caf50 --- /dev/null +++ b/scripts/add_collision_shapes.gd @@ -0,0 +1,68 @@ +@tool +extends EditorScript + +## Run this script in the Godot editor via File -> Run to add collision shapes +## to all Area3D nodes in the crafting_chain scene + +func _run(): + print("Adding collision shapes to Area3D nodes...") + + var scene_path = "res://scenes/crafting_chain.tscn" + var scene = load(scene_path) + + if not scene: + print("Error: Could not load scene") + return + + var root = scene.instantiate() + + # Process all Area3D nodes + var areas = _find_all_area3d(root) + print("Found ", areas.size(), " Area3D nodes") + + for area in areas: + # Check if already has a CollisionShape3D + var has_collision = false + for child in area.get_children(): + if child is CollisionShape3D: + has_collision = true + break + + if not has_collision: + # Add CollisionShape3D + var collision_shape = CollisionShape3D.new() + collision_shape.name = "CollisionShape3D" + + # Create a box shape + var box_shape = BoxShape3D.new() + box_shape.size = Vector3(1, 1, 1) # Adjust as needed + + collision_shape.shape = box_shape + area.add_child(collision_shape) + collision_shape.owner = root + + print(" Added collision shape to: ", area.name) + + # Save the modified scene + var packed_scene = PackedScene.new() + packed_scene.pack(root) + + var save_result = ResourceSaver.save(packed_scene, scene_path) + + if save_result == OK: + print("✓ Scene saved successfully!") + else: + print("✗ Error saving scene: ", save_result) + + root.queue_free() + +func _find_all_area3d(node: Node) -> Array: + var areas = [] + + if node is Area3D: + areas.append(node) + + for child in node.get_children(): + areas.append_array(_find_all_area3d(child)) + + return areas diff --git a/scripts/add_collision_shapes.gd.uid b/scripts/add_collision_shapes.gd.uid new file mode 100644 index 0000000..ce7ed91 --- /dev/null +++ b/scripts/add_collision_shapes.gd.uid @@ -0,0 +1 @@ +uid://cgixdoxxk3b1q diff --git a/scripts/capture_point.gd b/scripts/capture_point.gd new file mode 100644 index 0000000..98bd5ca --- /dev/null +++ b/scripts/capture_point.gd @@ -0,0 +1,150 @@ +extends Area3D + +## Capture Point - Reusable scene for team capture objectives +## Provides visual feedback for ownership and capture progress + +@export var point_name: String = "CapturePoint" +@export var capture_radius: float = 3.0 + +@onready var platform: MeshInstance3D = $Platform +@onready var status_label: Label3D = $StatusLabel +@onready var progress_bar: MeshInstance3D = $CaptureProgressBar + +var progress_mesh: BoxMesh + +# State +var owner_team: String = "neutral" +var capture_progress: float = 0.0 +var capturing_team: String = "" +var agents_present: Array = [] + +# Visual materials +var neutral_material: StandardMaterial3D +var blue_material: StandardMaterial3D +var red_material: StandardMaterial3D +var capture_material: StandardMaterial3D + +func _ready(): + # Create materials for different states + neutral_material = StandardMaterial3D.new() + neutral_material.albedo_color = Color(0.7, 0.7, 0.7, 1.0) + neutral_material.metallic = 0.3 + neutral_material.roughness = 0.7 + + blue_material = StandardMaterial3D.new() + blue_material.albedo_color = Color(0.2, 0.4, 0.9, 1.0) + blue_material.metallic = 0.4 + blue_material.roughness = 0.6 + blue_material.emission_enabled = true + blue_material.emission = Color(0.1, 0.2, 0.5, 1.0) + + red_material = StandardMaterial3D.new() + red_material.albedo_color = Color(0.9, 0.2, 0.2, 1.0) + red_material.metallic = 0.4 + red_material.roughness = 0.6 + red_material.emission_enabled = true + red_material.emission = Color(0.5, 0.1, 0.1, 1.0) + + capture_material = StandardMaterial3D.new() + capture_material.albedo_color = Color(1.0, 0.8, 0.2, 1.0) + capture_material.metallic = 0.5 + capture_material.roughness = 0.5 + + # Create progress bar mesh + progress_mesh = BoxMesh.new() + progress_mesh.size = Vector3(2.0, 0.2, 0.2) + if progress_bar: + progress_bar.mesh = progress_mesh + + # Set initial state + _update_visuals() + +func _process(_delta): + # Update label to face camera + if status_label: + _update_label() + +func set_owner_team(team: String): + """Set the owning team (neutral, blue, red)""" + owner_team = team + _update_visuals() + +func set_capture_progress(progress: float, team: String): + """Update capture progress (0.0 - 1.0)""" + capture_progress = clamp(progress, 0.0, 1.0) + capturing_team = team + _update_visuals() + +func reset_capture(): + """Reset capture progress""" + capture_progress = 0.0 + capturing_team = "" + progress_bar.visible = false + _update_visuals() + +func _update_visuals(): + """Update visual appearance based on state""" + if platform == null: + return + + # Update platform color based on owner + match owner_team: + "neutral": + platform.set_surface_override_material(0, neutral_material) + "blue": + platform.set_surface_override_material(0, blue_material) + "red": + platform.set_surface_override_material(0, red_material) + + # Show progress bar if being captured + if capturing_team != "" and capture_progress > 0.0: + progress_bar.visible = true + # Update progress bar scale based on capture progress + progress_bar.scale = Vector3(capture_progress * 2.0, 0.2, 0.2) + + # Color progress bar based on capturing team + var mat = StandardMaterial3D.new() + if capturing_team == "blue": + mat.albedo_color = Color(0.3, 0.5, 1.0, 1.0) + elif capturing_team == "red": + mat.albedo_color = Color(1.0, 0.3, 0.3, 1.0) + progress_bar.set_surface_override_material(0, mat) + else: + progress_bar.visible = false + +func _update_label(): + """Update status label text""" + if status_label == null: + return + + var status_text = point_name + "\n" + + if capturing_team != "": + status_text += "Capturing: %s (%d%%)" % [capturing_team.capitalize(), int(capture_progress * 100)] + status_label.modulate = Color(1.0, 0.8, 0.2, 1.0) + else: + status_text += owner_team.capitalize() + match owner_team: + "neutral": + status_label.modulate = Color(0.7, 0.7, 0.7, 1.0) + "blue": + status_label.modulate = Color(0.4, 0.6, 1.0, 1.0) + "red": + status_label.modulate = Color(1.0, 0.4, 0.4, 1.0) + + if agents_present.size() > 0: + status_text += "\nAgents: %d" % agents_present.size() + + status_label.text = status_text + +func get_state() -> Dictionary: + """Get current state as dictionary""" + return { + "name": point_name, + "position": global_position, + "owner": owner_team, + "capture_progress": capture_progress, + "capturing_team": capturing_team, + "agents_present": agents_present, + "node": self + } diff --git a/scripts/capture_point.gd.uid b/scripts/capture_point.gd.uid new file mode 100644 index 0000000..acfa237 --- /dev/null +++ b/scripts/capture_point.gd.uid @@ -0,0 +1 @@ +uid://cpmp1sb74dgkj diff --git a/scripts/resources/base_resource.gd b/scripts/resources/base_resource.gd new file mode 100644 index 0000000..f7a6c70 --- /dev/null +++ b/scripts/resources/base_resource.gd @@ -0,0 +1,43 @@ +extends Area3D +class_name BaseResource + +## Base class for collectible resources + +@export var resource_type: String = "unknown" +@export var resource_value: int = 1 +@export var auto_collect: bool = false + +signal collected(collector: Node) + +var is_collected: bool = false + +func _ready(): + # Connect to body entered if auto-collect is enabled + if auto_collect: + body_entered.connect(_on_body_entered) + +func collect(collector: Node) -> bool: + if is_collected: + return false + + is_collected = true + collected.emit(collector) + + # Hide the resource + visible = false + + # Disable collision + monitoring = false + monitorable = false + + return true + +func reset(): + is_collected = false + visible = true + monitoring = true + monitorable = true + +func _on_body_entered(body: Node): + if auto_collect and not is_collected: + collect(body) diff --git a/scripts/resources/base_resource.gd.uid b/scripts/resources/base_resource.gd.uid new file mode 100644 index 0000000..ff93856 --- /dev/null +++ b/scripts/resources/base_resource.gd.uid @@ -0,0 +1 @@ +uid://bq4d6lt8ub1g0 diff --git a/scripts/resources/berry.gd b/scripts/resources/berry.gd new file mode 100644 index 0000000..440873b --- /dev/null +++ b/scripts/resources/berry.gd @@ -0,0 +1,9 @@ +extends BaseResource + +## Berry resource - small, collectible food item + +func _ready(): + super._ready() + + resource_type = "berry" + resource_value = 1 diff --git a/scripts/resources/berry.gd.uid b/scripts/resources/berry.gd.uid new file mode 100644 index 0000000..2a0a480 --- /dev/null +++ b/scripts/resources/berry.gd.uid @@ -0,0 +1 @@ +uid://c224tcem2fxhh diff --git a/scripts/resources/coal.gd b/scripts/resources/coal.gd new file mode 100644 index 0000000..4d14409 --- /dev/null +++ b/scripts/resources/coal.gd @@ -0,0 +1,17 @@ +extends BaseResource + +## Coal resource + +func _ready(): + super._ready() + + resource_type = "coal" + resource_value = 1 + + # Set black color for coal + var mesh_instance = $MeshInstance3D + if mesh_instance: + var material = StandardMaterial3D.new() + material.albedo_color = Color(0.1, 0.1, 0.1) # Almost black + material.roughness = 0.9 # Very rough surface + mesh_instance.material_override = material diff --git a/scripts/resources/coal.gd.uid b/scripts/resources/coal.gd.uid new file mode 100644 index 0000000..2f926cc --- /dev/null +++ b/scripts/resources/coal.gd.uid @@ -0,0 +1 @@ +uid://x2ici4ychhjl diff --git a/scripts/resources/fire.gd b/scripts/resources/fire.gd new file mode 100644 index 0000000..d0dbae2 --- /dev/null +++ b/scripts/resources/fire.gd @@ -0,0 +1,9 @@ +extends BaseResource + +## Fire resource - glowing heat source + +func _ready(): + super._ready() + + resource_type = "fire" + resource_value = 1 diff --git a/scripts/resources/fire.gd.uid b/scripts/resources/fire.gd.uid new file mode 100644 index 0000000..f3bbca5 --- /dev/null +++ b/scripts/resources/fire.gd.uid @@ -0,0 +1 @@ +uid://8xl0qbl8dxjw diff --git a/scripts/resources/iron_ore.gd b/scripts/resources/iron_ore.gd new file mode 100644 index 0000000..7b12fb9 --- /dev/null +++ b/scripts/resources/iron_ore.gd @@ -0,0 +1,18 @@ +extends BaseResource + +## Iron Ore resource + +func _ready(): + super._ready() + + resource_type = "iron_ore" + resource_value = 1 + + # Set gray/metallic color for iron ore + var mesh_instance = $MeshInstance3D + if mesh_instance: + var material = StandardMaterial3D.new() + material.albedo_color = Color(0.5, 0.5, 0.5) # Gray + material.metallic = 0.6 + material.roughness = 0.4 + mesh_instance.material_override = material diff --git a/scripts/resources/iron_ore.gd.uid b/scripts/resources/iron_ore.gd.uid new file mode 100644 index 0000000..2946e71 --- /dev/null +++ b/scripts/resources/iron_ore.gd.uid @@ -0,0 +1 @@ +uid://do3kh277exd84 diff --git a/scripts/resources/pit.gd b/scripts/resources/pit.gd new file mode 100644 index 0000000..be7ba07 --- /dev/null +++ b/scripts/resources/pit.gd @@ -0,0 +1,9 @@ +extends BaseResource + +## Pit resource - ground depression or hole + +func _ready(): + super._ready() + + resource_type = "pit" + resource_value = 1 diff --git a/scripts/resources/pit.gd.uid b/scripts/resources/pit.gd.uid new file mode 100644 index 0000000..391a7da --- /dev/null +++ b/scripts/resources/pit.gd.uid @@ -0,0 +1 @@ +uid://bnk8fyq5sed0a diff --git a/scripts/resources/stone.gd b/scripts/resources/stone.gd new file mode 100644 index 0000000..c94d770 --- /dev/null +++ b/scripts/resources/stone.gd @@ -0,0 +1,9 @@ +extends BaseResource + +## Stone resource - basic building material + +func _ready(): + super._ready() + + resource_type = "stone" + resource_value = 1 diff --git a/scripts/resources/stone.gd.uid b/scripts/resources/stone.gd.uid new file mode 100644 index 0000000..09348dd --- /dev/null +++ b/scripts/resources/stone.gd.uid @@ -0,0 +1 @@ +uid://db3f2phmuosl4 diff --git a/scripts/resources/wood.gd b/scripts/resources/wood.gd new file mode 100644 index 0000000..19e9108 --- /dev/null +++ b/scripts/resources/wood.gd @@ -0,0 +1,16 @@ +extends BaseResource + +## Wood resource + +func _ready(): + super._ready() + + resource_type = "wood" + resource_value = 1 + + # Set brown color for wood + var mesh_instance = $MeshInstance3D + if mesh_instance: + var material = StandardMaterial3D.new() + material.albedo_color = Color(0.6, 0.4, 0.2) # Brown + mesh_instance.material_override = material diff --git a/scripts/resources/wood.gd.uid b/scripts/resources/wood.gd.uid new file mode 100644 index 0000000..f622ba1 --- /dev/null +++ b/scripts/resources/wood.gd.uid @@ -0,0 +1 @@ +uid://bmk2e1mwhok8n diff --git a/scripts/stations/anvil.gd b/scripts/stations/anvil.gd new file mode 100644 index 0000000..f9617cb --- /dev/null +++ b/scripts/stations/anvil.gd @@ -0,0 +1,18 @@ +extends CraftingStation + +## Anvil-specific implementation + +func _ready(): + super._ready() + + station_type = "anvil" + station_name = "Anvil" + + # Set dark gray/metallic color for anvil + var mesh_instance = $MeshInstance3D + if mesh_instance: + var material = StandardMaterial3D.new() + material.albedo_color = Color(0.25, 0.25, 0.25) # Dark gray + material.metallic = 0.8 # Make it look metallic + material.roughness = 0.3 + mesh_instance.material_override = material diff --git a/scripts/stations/anvil.gd.uid b/scripts/stations/anvil.gd.uid new file mode 100644 index 0000000..df0a4d0 --- /dev/null +++ b/scripts/stations/anvil.gd.uid @@ -0,0 +1 @@ +uid://dmav7xg8036gn diff --git a/scripts/stations/base_station.gd b/scripts/stations/base_station.gd new file mode 100644 index 0000000..b886e6f --- /dev/null +++ b/scripts/stations/base_station.gd @@ -0,0 +1,78 @@ +extends Area3D +class_name CraftingStation + +## Base class for crafting stations (Furnace, Anvil, Workbench) + +@export var station_type: String = "unknown" +@export var station_name: String = "Crafting Station" +@export var interaction_radius: float = 2.5 + +signal agent_entered(agent: Node) +signal agent_exited(agent: Node) +signal crafting_started(recipe: String) +signal crafting_completed(item: String) + +var agents_in_range: Array[Node] = [] +var is_crafting: bool = false +var current_recipe: Dictionary = {} + +func _ready(): + body_entered.connect(_on_body_entered) + body_exited.connect(_on_body_exited) + +func _on_body_entered(body: Node): + if not agents_in_range.has(body): + agents_in_range.append(body) + agent_entered.emit(body) + print("%s: Agent entered range" % station_name) + +func _on_body_exited(body: Node): + if agents_in_range.has(body): + agents_in_range.erase(body) + agent_exited.emit(body) + print("%s: Agent left range" % station_name) + +func can_craft(recipe: Dictionary) -> bool: + """Check if this station can craft the given recipe""" + if is_crafting: + return false + + # Check if recipe requires this station type + if recipe.has("station") and recipe["station"].to_lower() == station_type.to_lower(): + return true + + return false + +func start_crafting(recipe: Dictionary) -> bool: + """Start crafting an item""" + if not can_craft(recipe): + return false + + is_crafting = true + current_recipe = recipe + crafting_started.emit(recipe.get("name", "unknown")) + + print("%s: Started crafting %s" % [station_name, recipe.get("name", "unknown")]) + return true + +func complete_crafting() -> String: + """Complete the current crafting operation""" + if not is_crafting: + return "" + + var item_name = current_recipe.get("name", "") + is_crafting = false + + crafting_completed.emit(item_name) + print("%s: Completed crafting %s" % [station_name, item_name]) + + current_recipe.clear() + return item_name + +func is_agent_in_range(agent: Node) -> bool: + """Check if a specific agent is in range""" + return agents_in_range.has(agent) + +func get_agents_in_range() -> Array[Node]: + """Get all agents currently in range""" + return agents_in_range.duplicate() diff --git a/scripts/stations/base_station.gd.uid b/scripts/stations/base_station.gd.uid new file mode 100644 index 0000000..f4ab756 --- /dev/null +++ b/scripts/stations/base_station.gd.uid @@ -0,0 +1 @@ +uid://cwl6vvwsfyjig diff --git a/scripts/stations/furnace.gd b/scripts/stations/furnace.gd new file mode 100644 index 0000000..fcfc92b --- /dev/null +++ b/scripts/stations/furnace.gd @@ -0,0 +1,16 @@ +extends CraftingStation + +## Furnace-specific implementation + +func _ready(): + super._ready() + + station_type = "furnace" + station_name = "Furnace" + + # Set orange/red color for furnace + var mesh_instance = $MeshInstance3D + if mesh_instance: + var material = StandardMaterial3D.new() + material.albedo_color = Color(1.0, 0.4, 0.0) # Orange color (RGB) + mesh_instance.material_override = material diff --git a/scripts/stations/furnace.gd.uid b/scripts/stations/furnace.gd.uid new file mode 100644 index 0000000..659cad9 --- /dev/null +++ b/scripts/stations/furnace.gd.uid @@ -0,0 +1 @@ +uid://clba3etrgc4mn diff --git a/scripts/stations/workbench.gd b/scripts/stations/workbench.gd new file mode 100644 index 0000000..9abbe58 --- /dev/null +++ b/scripts/stations/workbench.gd @@ -0,0 +1,16 @@ +extends CraftingStation + +## Workbench-specific implementation + +func _ready(): + super._ready() + + station_type = "workbench" + station_name = "Workbench" + + # Set brown/wood color for workbench + var mesh_instance = $MeshInstance3D + if mesh_instance: + var material = StandardMaterial3D.new() + material.albedo_color = Color(0.55, 0.27, 0.07) # Brown color + mesh_instance.material_override = material diff --git a/scripts/stations/workbench.gd.uid b/scripts/stations/workbench.gd.uid new file mode 100644 index 0000000..98c721a --- /dev/null +++ b/scripts/stations/workbench.gd.uid @@ -0,0 +1 @@ +uid://d4k8tuntpxk7b diff --git a/scripts/team_capture.gd b/scripts/team_capture.gd index cf5ac7d..6cceccf 100644 --- a/scripts/team_capture.gd +++ b/scripts/team_capture.gd @@ -155,16 +155,10 @@ func _initialize_scene(): # Initialize Capture Points var points_node = $CapturePoints for child in points_node.get_children(): - if child is Area3D: - capture_points.append({ - "name": child.name, - "position": child.global_position, - "owner": "neutral", - "capture_progress": 0.0, - "capturing_team": null, - "agents_present": [], - "node": child - }) + if child.has_method("get_state"): + # This is a CapturePoint scene + var state = child.get_state() + capture_points.append(state) func _process(_delta): _update_metrics_ui() @@ -240,6 +234,10 @@ func _update_capture_points(delta: float): point.agents_present.append(agent_data) red_count += 1 + # Update agents_present on the node itself for visual feedback + if point.node: + point.node.agents_present = point.agents_present + # Determine capturing team var dominant_team = null if blue_count > red_count: @@ -255,6 +253,11 @@ func _update_capture_points(delta: float): point.capture_progress = 0.0 point.capture_progress += delta + + # Update visual feedback on the node + if point.node: + point.node.set_capture_progress(point.capture_progress / CAPTURE_TIME, dominant_team) + if point.capture_progress >= CAPTURE_TIME: _capture_point(point, dominant_team) else: @@ -262,6 +265,10 @@ func _update_capture_points(delta: float): point.capturing_team = null point.capture_progress = 0.0 + # Update visual feedback + if point.node: + point.node.reset_capture() + func _capture_point(point: Dictionary, team: String): """Capture a point for a team""" var previous_owner = point.owner @@ -269,6 +276,11 @@ func _capture_point(point: Dictionary, team: String): point.capture_progress = 0.0 point.capturing_team = null + # Update visual on the node + if point.node: + point.node.set_owner_team(team) + point.node.reset_capture() + # Award points if team == "blue": blue_score += POINTS_PER_CAPTURE @@ -555,6 +567,11 @@ func _reset_scene(): point.capturing_team = null point.agents_present.clear() + # Update visual on the node + if point.node: + point.node.set_owner_team("neutral") + point.node.reset_capture() + # Reset agent positions var blue_spawn_positions = [Vector3(-20, 1, -20), Vector3(-22, 1, -18), Vector3(-18, 1, -22)] for i in range(blue_team.size()):