Compare commits
5 Commits
48b9e8f8f3
...
835651a9cc
| Author | SHA1 | Date | |
|---|---|---|---|
| 835651a9cc | |||
| 0d3788246a | |||
| 8cae50bc11 | |||
| 7848b7a979 | |||
| cb4e4951fe |
@@ -0,0 +1,747 @@
|
|||||||
|
# Sprint 16 — Snap-Point System Implementation Plan
|
||||||
|
|
||||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||||
|
|
||||||
|
**Goal:** Add SnapPoint nodes to all furniture in all 12 rooms so characters can snap into sitting/lying poses when released near a piece of furniture.
|
||||||
|
|
||||||
|
**Architecture:** Each room `.tscn` gets one `ext_resource` entry for `snap_point.gd` and one `[node]` entry per snap position. SnapPoints are direct children of the room node (not children of ColorRect furniture, since ColorRects have no Node2D hierarchy). All SnapPoints auto-register in the `"snap_points"` group via `_ready()`. No new GDScript is written — this sprint is purely scene data.
|
||||||
|
|
||||||
|
**Tech Stack:** Godot 4.6.2, `.tscn` text format, GUT v9.6.0 (TDD), headless runner.
|
||||||
|
|
||||||
|
**GDD Reference:** `docs/game-design.md` — Kapitel 2 (Raum-Übersicht) + Kapitel 5.1 (Snap-Point System).
|
||||||
|
|
||||||
|
**Headless runner:**
|
||||||
|
```
|
||||||
|
"F:/Development/_tools/Godot_v4.6.2-stable_win64/Godot_v4.6.2-stable_win64.exe" --headless -s res://addons/gut/gut_cmdln.gd -gdir=res://test/ -gexit 2>&1
|
||||||
|
```
|
||||||
|
|
||||||
|
**Existing tests must stay green:** 90 tests passing before this sprint starts.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Map
|
||||||
|
|
||||||
|
| Action | Path | SnapPoints added |
|
||||||
|
|---|---|---|
|
||||||
|
| Modify | `scenes/rooms/floor0/Reception.tscn` | 4 × sitting (2 benches × 2) |
|
||||||
|
| Modify | `scenes/rooms/floor0/GiftShop.tscn` | 1 × sitting (counter) |
|
||||||
|
| Modify | `scenes/rooms/floor0/Restaurant.tscn` | 6 × sitting (3 tables × 2) |
|
||||||
|
| Modify | `scenes/rooms/floor0/EmergencyRoom.tscn` | 1 × lying (medical table) |
|
||||||
|
| Modify | `scenes/rooms/floor1/XRay.tscn` | 1 × lying (exam table) |
|
||||||
|
| Modify | `scenes/rooms/floor1/Pharmacy.tscn` | 1 × sitting (counter) |
|
||||||
|
| Modify | `scenes/rooms/floor1/Lab.tscn` | 2 × sitting (lab bench) |
|
||||||
|
| Modify | `scenes/rooms/floor1/PatientRoom.tscn` | 2 × lying (2 beds) |
|
||||||
|
| Modify | `scenes/rooms/floor2/Ultrasound.tscn` | 1 × lying (exam table) |
|
||||||
|
| Modify | `scenes/rooms/floor2/DeliveryRoom.tscn` | 1 × lying (delivery bed) |
|
||||||
|
| Modify | `scenes/rooms/floor2/Nursery.tscn` | 3 × lying, baby_only (3 cradles) |
|
||||||
|
| Modify | `scenes/rooms/home/GardenParty.tscn` | 2 × sitting (garden table) |
|
||||||
|
| Create | `test/unit/test_snap_points_floor0.gd` | Tests for EG (12 snap points) |
|
||||||
|
| Create | `test/unit/test_snap_points_floor1.gd` | Tests for 1.OG (6 snap points) |
|
||||||
|
| Create | `test/unit/test_snap_points_floor2.gd` | Tests for 2.OG + Garten (7 snap points) |
|
||||||
|
|
||||||
|
**Total: 25 SnapPoints across 12 rooms.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How to add a SnapPoint to a .tscn
|
||||||
|
|
||||||
|
### 1. Increment `load_steps` in the header by 1
|
||||||
|
|
||||||
|
```
|
||||||
|
[gd_scene load_steps=3 format=3 ...] ← was 2
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Add `ext_resource` for snap_point.gd after the last existing `ext_resource` line
|
||||||
|
|
||||||
|
For rooms with currently 1 ext_resource (InteractiveObject only), use id `"2_snap"`:
|
||||||
|
```
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
|
||||||
|
```
|
||||||
|
|
||||||
|
For rooms with currently 2 ext_resources, use id `"3_snap"`:
|
||||||
|
```
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="3_snap"]
|
||||||
|
```
|
||||||
|
|
||||||
|
For GardenParty (3 ext_resources), use id `"4_snap"`:
|
||||||
|
```
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="4_snap"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Append node entries at the end of the file
|
||||||
|
|
||||||
|
Sitting (default pose, no need to set pose or baby_only):
|
||||||
|
```
|
||||||
|
[node name="SnapBenchLeft1" type="Node2D" parent="."]
|
||||||
|
position = Vector2(150, 555)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
```
|
||||||
|
|
||||||
|
Lying (must set pose):
|
||||||
|
```
|
||||||
|
[node name="SnapExamTable" type="Node2D" parent="."]
|
||||||
|
position = Vector2(640, 480)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
pose = "lying"
|
||||||
|
```
|
||||||
|
|
||||||
|
Lying + baby only:
|
||||||
|
```
|
||||||
|
[node name="SnapCradle1" type="Node2D" parent="."]
|
||||||
|
position = Vector2(340, 240)
|
||||||
|
script = ExtResource("3_snap")
|
||||||
|
pose = "lying"
|
||||||
|
baby_only = true
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Helper: how tests count SnapPoints in a room
|
||||||
|
|
||||||
|
```gdscript
|
||||||
|
func _count_snaps(room: Node2D) -> int:
|
||||||
|
var count: int = 0
|
||||||
|
for child: Node in room.get_children():
|
||||||
|
if child is SnapPoint:
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
func _count_snaps_with_pose(room: Node2D, pose: String) -> int:
|
||||||
|
var count: int = 0
|
||||||
|
for child: Node in room.get_children():
|
||||||
|
var snap: SnapPoint = child as SnapPoint
|
||||||
|
if snap != null and snap.pose == pose:
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
func _count_snaps_baby_only(room: Node2D) -> int:
|
||||||
|
var count: int = 0
|
||||||
|
for child: Node in room.get_children():
|
||||||
|
var snap: SnapPoint = child as SnapPoint
|
||||||
|
if snap != null and snap.baby_only:
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 1: Floor 0 — Reception, GiftShop, Restaurant, EmergencyRoom
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `scenes/rooms/floor0/Reception.tscn`
|
||||||
|
- Modify: `scenes/rooms/floor0/GiftShop.tscn`
|
||||||
|
- Modify: `scenes/rooms/floor0/Restaurant.tscn`
|
||||||
|
- Modify: `scenes/rooms/floor0/EmergencyRoom.tscn`
|
||||||
|
- Create: `test/unit/test_snap_points_floor0.gd`
|
||||||
|
|
||||||
|
### Step 1: Write the failing tests
|
||||||
|
|
||||||
|
Create `test/unit/test_snap_points_floor0.gd`:
|
||||||
|
|
||||||
|
```gdscript
|
||||||
|
## Tests verifying SnapPoints exist in all EG (Erdgeschoss) room scenes.
|
||||||
|
extends GutTest
|
||||||
|
|
||||||
|
|
||||||
|
func _count_snaps(room: Node2D) -> int:
|
||||||
|
var count: int = 0
|
||||||
|
for child: Node in room.get_children():
|
||||||
|
if child is SnapPoint:
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
func _count_snaps_with_pose(room: Node2D, pose: String) -> int:
|
||||||
|
var count: int = 0
|
||||||
|
for child: Node in room.get_children():
|
||||||
|
var snap: SnapPoint = child as SnapPoint
|
||||||
|
if snap != null and snap.pose == pose:
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
func test_reception_has_four_snap_points() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor0/Reception.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 4)
|
||||||
|
|
||||||
|
|
||||||
|
func test_reception_all_snaps_are_sitting() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor0/Reception.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "sitting"), 4)
|
||||||
|
|
||||||
|
|
||||||
|
func test_giftshop_has_one_snap_point() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor0/GiftShop.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_giftshop_snap_is_sitting() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor0/GiftShop.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "sitting"), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_restaurant_has_six_snap_points() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor0/Restaurant.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 6)
|
||||||
|
|
||||||
|
|
||||||
|
func test_restaurant_all_snaps_are_sitting() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor0/Restaurant.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "sitting"), 6)
|
||||||
|
|
||||||
|
|
||||||
|
func test_emergency_room_has_one_snap_point() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor0/EmergencyRoom.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_emergency_room_snap_is_lying() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor0/EmergencyRoom.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "lying"), 1)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Run tests — verify they FAIL
|
||||||
|
|
||||||
|
```
|
||||||
|
"F:/Development/_tools/Godot_v4.6.2-stable_win64/Godot_v4.6.2-stable_win64.exe" --headless -s res://addons/gut/gut_cmdln.gd -gdir=res://test/ -gexit 2>&1
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: 8 new failures. 90 existing pass.
|
||||||
|
|
||||||
|
### Step 3: Edit `scenes/rooms/floor0/Reception.tscn`
|
||||||
|
|
||||||
|
Current header: `[gd_scene load_steps=2 format=3 uid="uid://cozypaw_reception"]`
|
||||||
|
|
||||||
|
Change to: `[gd_scene load_steps=3 format=3 uid="uid://cozypaw_reception"]`
|
||||||
|
|
||||||
|
After `[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]`, add:
|
||||||
|
```
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Append at the end of the file:
|
||||||
|
```
|
||||||
|
[node name="SnapBenchLeft1" type="Node2D" parent="."]
|
||||||
|
position = Vector2(150, 555)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|
||||||
|
[node name="SnapBenchLeft2" type="Node2D" parent="."]
|
||||||
|
position = Vector2(240, 555)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|
||||||
|
[node name="SnapBenchRight1" type="Node2D" parent="."]
|
||||||
|
position = Vector2(990, 555)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|
||||||
|
[node name="SnapBenchRight2" type="Node2D" parent="."]
|
||||||
|
position = Vector2(1080, 555)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4: Edit `scenes/rooms/floor0/GiftShop.tscn`
|
||||||
|
|
||||||
|
Change header to `load_steps=3`.
|
||||||
|
|
||||||
|
Add after InteractiveObject ext_resource:
|
||||||
|
```
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Append:
|
||||||
|
```
|
||||||
|
[node name="SnapCounter" type="Node2D" parent="."]
|
||||||
|
position = Vector2(640, 528)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Edit `scenes/rooms/floor0/Restaurant.tscn`
|
||||||
|
|
||||||
|
Change header to `load_steps=3`.
|
||||||
|
|
||||||
|
Add after InteractiveObject ext_resource:
|
||||||
|
```
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Append:
|
||||||
|
```
|
||||||
|
[node name="SnapTable1Left" type="Node2D" parent="."]
|
||||||
|
position = Vector2(160, 510)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|
||||||
|
[node name="SnapTable1Right" type="Node2D" parent="."]
|
||||||
|
position = Vector2(280, 510)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|
||||||
|
[node name="SnapTable2Left" type="Node2D" parent="."]
|
||||||
|
position = Vector2(580, 510)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|
||||||
|
[node name="SnapTable2Right" type="Node2D" parent="."]
|
||||||
|
position = Vector2(700, 510)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|
||||||
|
[node name="SnapTable3Left" type="Node2D" parent="."]
|
||||||
|
position = Vector2(1000, 510)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|
||||||
|
[node name="SnapTable3Right" type="Node2D" parent="."]
|
||||||
|
position = Vector2(1120, 510)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 6: Edit `scenes/rooms/floor0/EmergencyRoom.tscn`
|
||||||
|
|
||||||
|
Current header: `load_steps=3` (has Ambulance ext_resource). Change to `load_steps=4`.
|
||||||
|
|
||||||
|
Add after the last ext_resource line (Ambulance):
|
||||||
|
```
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="3_snap"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Append:
|
||||||
|
```
|
||||||
|
[node name="SnapMedicalTable" type="Node2D" parent="."]
|
||||||
|
position = Vector2(310, 480)
|
||||||
|
script = ExtResource("3_snap")
|
||||||
|
pose = "lying"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 7: Run tests — verify 8 new tests PASS (98 total)
|
||||||
|
|
||||||
|
Run `--headless --import` first if needed, then the test runner.
|
||||||
|
|
||||||
|
Expected: 98/98 passed.
|
||||||
|
|
||||||
|
### Step 8: Commit
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd "F:/Development/_gameDev/Cozypaw-Hospital/.worktrees/sprint-16-snap-points"
|
||||||
|
git add scenes/rooms/floor0/Reception.tscn scenes/rooms/floor0/GiftShop.tscn
|
||||||
|
git add scenes/rooms/floor0/Restaurant.tscn scenes/rooms/floor0/EmergencyRoom.tscn
|
||||||
|
git add test/unit/test_snap_points_floor0.gd
|
||||||
|
git commit -m "feat(snap-points): add SnapPoints to all EG rooms (Reception, GiftShop, Restaurant, EmergencyRoom)"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 2: Floor 1 — XRay, Pharmacy, Lab, PatientRoom
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `scenes/rooms/floor1/XRay.tscn`
|
||||||
|
- Modify: `scenes/rooms/floor1/Pharmacy.tscn`
|
||||||
|
- Modify: `scenes/rooms/floor1/Lab.tscn`
|
||||||
|
- Modify: `scenes/rooms/floor1/PatientRoom.tscn`
|
||||||
|
- Create: `test/unit/test_snap_points_floor1.gd`
|
||||||
|
|
||||||
|
### Step 1: Write the failing tests
|
||||||
|
|
||||||
|
Create `test/unit/test_snap_points_floor1.gd`:
|
||||||
|
|
||||||
|
```gdscript
|
||||||
|
## Tests verifying SnapPoints exist in all 1.OG room scenes.
|
||||||
|
extends GutTest
|
||||||
|
|
||||||
|
|
||||||
|
func _count_snaps(room: Node2D) -> int:
|
||||||
|
var count: int = 0
|
||||||
|
for child: Node in room.get_children():
|
||||||
|
if child is SnapPoint:
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
func _count_snaps_with_pose(room: Node2D, pose: String) -> int:
|
||||||
|
var count: int = 0
|
||||||
|
for child: Node in room.get_children():
|
||||||
|
var snap: SnapPoint = child as SnapPoint
|
||||||
|
if snap != null and snap.pose == pose:
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
func test_xray_has_one_snap_point() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor1/XRay.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_xray_snap_is_lying() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor1/XRay.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "lying"), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_pharmacy_has_one_snap_point() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor1/Pharmacy.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_pharmacy_snap_is_sitting() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor1/Pharmacy.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "sitting"), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_lab_has_two_snap_points() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor1/Lab.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 2)
|
||||||
|
|
||||||
|
|
||||||
|
func test_lab_all_snaps_are_sitting() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor1/Lab.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "sitting"), 2)
|
||||||
|
|
||||||
|
|
||||||
|
func test_patient_room_has_two_snap_points() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor1/PatientRoom.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 2)
|
||||||
|
|
||||||
|
|
||||||
|
func test_patient_room_all_snaps_are_lying() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor1/PatientRoom.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "lying"), 2)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Run tests — verify 8 new tests FAIL
|
||||||
|
|
||||||
|
Expected: 8 failures. 98 existing pass.
|
||||||
|
|
||||||
|
### Step 3: Edit `scenes/rooms/floor1/XRay.tscn`
|
||||||
|
|
||||||
|
Current header: `load_steps=3` (has XRayMachine). Change to `load_steps=4`.
|
||||||
|
|
||||||
|
Add after the last ext_resource:
|
||||||
|
```
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="3_snap"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Append:
|
||||||
|
```
|
||||||
|
[node name="SnapExamTable" type="Node2D" parent="."]
|
||||||
|
position = Vector2(640, 480)
|
||||||
|
script = ExtResource("3_snap")
|
||||||
|
pose = "lying"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4: Edit `scenes/rooms/floor1/Pharmacy.tscn`
|
||||||
|
|
||||||
|
Current header: `load_steps=2`. Change to `load_steps=3`.
|
||||||
|
|
||||||
|
Add after ext_resource:
|
||||||
|
```
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Append:
|
||||||
|
```
|
||||||
|
[node name="SnapCounter" type="Node2D" parent="."]
|
||||||
|
position = Vector2(640, 520)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Edit `scenes/rooms/floor1/Lab.tscn`
|
||||||
|
|
||||||
|
Current header: `load_steps=2`. Change to `load_steps=3`.
|
||||||
|
|
||||||
|
Add after ext_resource:
|
||||||
|
```
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Append:
|
||||||
|
```
|
||||||
|
[node name="SnapLabBench1" type="Node2D" parent="."]
|
||||||
|
position = Vector2(450, 470)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|
||||||
|
[node name="SnapLabBench2" type="Node2D" parent="."]
|
||||||
|
position = Vector2(750, 470)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 6: Edit `scenes/rooms/floor1/PatientRoom.tscn`
|
||||||
|
|
||||||
|
Current header: `load_steps=2`. Change to `load_steps=3`.
|
||||||
|
|
||||||
|
Add after ext_resource:
|
||||||
|
```
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Append:
|
||||||
|
```
|
||||||
|
[node name="SnapBed1" type="Node2D" parent="."]
|
||||||
|
position = Vector2(250, 465)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
pose = "lying"
|
||||||
|
|
||||||
|
[node name="SnapBed2" type="Node2D" parent="."]
|
||||||
|
position = Vector2(810, 465)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
pose = "lying"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 7: Run tests — verify 8 new tests PASS (106 total)
|
||||||
|
|
||||||
|
Run `--headless --import` first if needed, then the test runner.
|
||||||
|
|
||||||
|
Expected: 106/106 passed.
|
||||||
|
|
||||||
|
### Step 8: Commit
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd "F:/Development/_gameDev/Cozypaw-Hospital/.worktrees/sprint-16-snap-points"
|
||||||
|
git add scenes/rooms/floor1/XRay.tscn scenes/rooms/floor1/Pharmacy.tscn
|
||||||
|
git add scenes/rooms/floor1/Lab.tscn scenes/rooms/floor1/PatientRoom.tscn
|
||||||
|
git add test/unit/test_snap_points_floor1.gd
|
||||||
|
git commit -m "feat(snap-points): add SnapPoints to all 1.OG rooms (XRay, Pharmacy, Lab, PatientRoom)"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 3: Floor 2 + Garten — Ultrasound, DeliveryRoom, Nursery, GardenParty
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `scenes/rooms/floor2/Ultrasound.tscn`
|
||||||
|
- Modify: `scenes/rooms/floor2/DeliveryRoom.tscn`
|
||||||
|
- Modify: `scenes/rooms/floor2/Nursery.tscn`
|
||||||
|
- Modify: `scenes/rooms/home/GardenParty.tscn`
|
||||||
|
- Create: `test/unit/test_snap_points_floor2.gd`
|
||||||
|
|
||||||
|
### Step 1: Write the failing tests
|
||||||
|
|
||||||
|
Create `test/unit/test_snap_points_floor2.gd`:
|
||||||
|
|
||||||
|
```gdscript
|
||||||
|
## Tests verifying SnapPoints exist in all 2.OG and Garten room scenes.
|
||||||
|
extends GutTest
|
||||||
|
|
||||||
|
|
||||||
|
func _count_snaps(room: Node2D) -> int:
|
||||||
|
var count: int = 0
|
||||||
|
for child: Node in room.get_children():
|
||||||
|
if child is SnapPoint:
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
func _count_snaps_with_pose(room: Node2D, pose: String) -> int:
|
||||||
|
var count: int = 0
|
||||||
|
for child: Node in room.get_children():
|
||||||
|
var snap: SnapPoint = child as SnapPoint
|
||||||
|
if snap != null and snap.pose == pose:
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
func _count_snaps_baby_only(room: Node2D) -> int:
|
||||||
|
var count: int = 0
|
||||||
|
for child: Node in room.get_children():
|
||||||
|
var snap: SnapPoint = child as SnapPoint
|
||||||
|
if snap != null and snap.baby_only:
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
func test_ultrasound_has_one_snap_point() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor2/Ultrasound.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_ultrasound_snap_is_lying() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor2/Ultrasound.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "lying"), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_delivery_room_has_one_snap_point() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor2/DeliveryRoom.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_delivery_room_snap_is_lying() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor2/DeliveryRoom.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "lying"), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_nursery_has_three_snap_points() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor2/Nursery.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 3)
|
||||||
|
|
||||||
|
|
||||||
|
func test_nursery_all_snaps_are_baby_only() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor2/Nursery.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_baby_only(room), 3)
|
||||||
|
|
||||||
|
|
||||||
|
func test_nursery_all_snaps_are_lying() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor2/Nursery.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "lying"), 3)
|
||||||
|
|
||||||
|
|
||||||
|
func test_garden_party_has_two_snap_points() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/home/GardenParty.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 2)
|
||||||
|
|
||||||
|
|
||||||
|
func test_garden_party_all_snaps_are_sitting() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/home/GardenParty.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "sitting"), 2)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Run tests — verify 9 new tests FAIL
|
||||||
|
|
||||||
|
Expected: 9 failures. 106 existing pass.
|
||||||
|
|
||||||
|
### Step 3: Edit `scenes/rooms/floor2/Ultrasound.tscn`
|
||||||
|
|
||||||
|
Current header: `load_steps=3` (has UltrasoundMachine). Change to `load_steps=4`.
|
||||||
|
|
||||||
|
Add after last ext_resource:
|
||||||
|
```
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="3_snap"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Append:
|
||||||
|
```
|
||||||
|
[node name="SnapExamTable" type="Node2D" parent="."]
|
||||||
|
position = Vector2(470, 480)
|
||||||
|
script = ExtResource("3_snap")
|
||||||
|
pose = "lying"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4: Edit `scenes/rooms/floor2/DeliveryRoom.tscn`
|
||||||
|
|
||||||
|
Current header: `load_steps=3` (has DeliveryBed). Change to `load_steps=4`.
|
||||||
|
|
||||||
|
Add after last ext_resource:
|
||||||
|
```
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="3_snap"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Append:
|
||||||
|
```
|
||||||
|
[node name="SnapDeliveryBed" type="Node2D" parent="."]
|
||||||
|
position = Vector2(540, 480)
|
||||||
|
script = ExtResource("3_snap")
|
||||||
|
pose = "lying"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Edit `scenes/rooms/floor2/Nursery.tscn`
|
||||||
|
|
||||||
|
Current header: `load_steps=3` (has Cradle). Change to `load_steps=4`.
|
||||||
|
|
||||||
|
Add after last ext_resource:
|
||||||
|
```
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="3_snap"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Append:
|
||||||
|
```
|
||||||
|
[node name="SnapCradle1" type="Node2D" parent="."]
|
||||||
|
position = Vector2(340, 240)
|
||||||
|
script = ExtResource("3_snap")
|
||||||
|
pose = "lying"
|
||||||
|
baby_only = true
|
||||||
|
|
||||||
|
[node name="SnapCradle2" type="Node2D" parent="."]
|
||||||
|
position = Vector2(600, 240)
|
||||||
|
script = ExtResource("3_snap")
|
||||||
|
pose = "lying"
|
||||||
|
baby_only = true
|
||||||
|
|
||||||
|
[node name="SnapCradle3" type="Node2D" parent="."]
|
||||||
|
position = Vector2(860, 240)
|
||||||
|
script = ExtResource("3_snap")
|
||||||
|
pose = "lying"
|
||||||
|
baby_only = true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 6: Edit `scenes/rooms/home/GardenParty.tscn`
|
||||||
|
|
||||||
|
Current header: `load_steps=4` (has GiftBox, TeaPot, HomeButton). Change to `load_steps=5`.
|
||||||
|
|
||||||
|
Add after the last ext_resource (HomeButton):
|
||||||
|
```
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="4_snap"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Append:
|
||||||
|
```
|
||||||
|
[node name="SnapTableLeft" type="Node2D" parent="."]
|
||||||
|
position = Vector2(530, 455)
|
||||||
|
script = ExtResource("4_snap")
|
||||||
|
|
||||||
|
[node name="SnapTableRight" type="Node2D" parent="."]
|
||||||
|
position = Vector2(750, 455)
|
||||||
|
script = ExtResource("4_snap")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 7: Run tests — verify 9 new tests PASS (115 total)
|
||||||
|
|
||||||
|
Run `--headless --import` first, then the test runner.
|
||||||
|
|
||||||
|
Expected: 115/115 passed.
|
||||||
|
|
||||||
|
### Step 8: Commit
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd "F:/Development/_gameDev/Cozypaw-Hospital/.worktrees/sprint-16-snap-points"
|
||||||
|
git add scenes/rooms/floor2/Ultrasound.tscn scenes/rooms/floor2/DeliveryRoom.tscn
|
||||||
|
git add scenes/rooms/floor2/Nursery.tscn scenes/rooms/home/GardenParty.tscn
|
||||||
|
git add test/unit/test_snap_points_floor2.gd
|
||||||
|
git commit -m "feat(snap-points): add SnapPoints to all 2.OG and Garten rooms (Ultrasound, DeliveryRoom, Nursery, GardenParty)"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Final Check
|
||||||
|
|
||||||
|
- [ ] **Run full test suite one last time**
|
||||||
|
|
||||||
|
```
|
||||||
|
"F:/Development/_tools/Godot_v4.6.2-stable_win64/Godot_v4.6.2-stable_win64.exe" --headless -s res://addons/gut/gut_cmdln.gd -gdir=res://test/ -gexit 2>&1
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected output:
|
||||||
|
```
|
||||||
|
Scripts 10
|
||||||
|
Tests 115
|
||||||
|
Passing Tests 115
|
||||||
|
---- All tests passed! ----
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Verify git log shows 3 clean commits**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git log --oneline -4
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
```
|
||||||
|
feat(snap-points): add SnapPoints to all 2.OG and Garten rooms...
|
||||||
|
feat(snap-points): add SnapPoints to all 1.OG rooms...
|
||||||
|
feat(snap-points): add SnapPoints to all EG rooms...
|
||||||
|
```
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
[gd_scene load_steps=3 format=3 uid="uid://cozypaw_emergency"]
|
[gd_scene load_steps=4 format=3 uid="uid://cozypaw_emergency"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/Ambulance.tscn" id="2_ambulance"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/Ambulance.tscn" id="2_ambulance"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="3_snap"]
|
||||||
|
|
||||||
[node name="EmergencyRoom" type="Node2D"]
|
[node name="EmergencyRoom" type="Node2D"]
|
||||||
|
|
||||||
@@ -73,3 +74,8 @@ position = Vector2(550, 440)
|
|||||||
position = Vector2(500, 570)
|
position = Vector2(500, 570)
|
||||||
trigger_floor = 0
|
trigger_floor = 0
|
||||||
trigger_room = 3
|
trigger_room = 3
|
||||||
|
|
||||||
|
[node name="SnapMedicalTable" type="Node2D" parent="."]
|
||||||
|
position = Vector2(310, 480)
|
||||||
|
script = ExtResource("3_snap")
|
||||||
|
pose = "lying"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
[gd_scene load_steps=2 format=3 uid="uid://cozypaw_giftshop"]
|
[gd_scene load_steps=3 format=3 uid="uid://cozypaw_giftshop"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
|
||||||
|
|
||||||
[node name="GiftShop" type="Node2D"]
|
[node name="GiftShop" type="Node2D"]
|
||||||
|
|
||||||
@@ -63,3 +64,7 @@ position = Vector2(900, 330)
|
|||||||
|
|
||||||
[node name="GiftBox" parent="." instance=ExtResource("1_iobj")]
|
[node name="GiftBox" parent="." instance=ExtResource("1_iobj")]
|
||||||
position = Vector2(640, 510)
|
position = Vector2(640, 510)
|
||||||
|
|
||||||
|
[node name="SnapCounter" type="Node2D" parent="."]
|
||||||
|
position = Vector2(640, 528)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
[gd_scene load_steps=2 format=3 uid="uid://cozypaw_reception"]
|
[gd_scene load_steps=3 format=3 uid="uid://cozypaw_reception"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
|
||||||
|
|
||||||
[node name="Reception" type="Node2D"]
|
[node name="Reception" type="Node2D"]
|
||||||
|
|
||||||
@@ -85,3 +86,19 @@ position = Vector2(530, 510)
|
|||||||
|
|
||||||
[node name="PottedPlant" parent="." instance=ExtResource("1_iobj")]
|
[node name="PottedPlant" parent="." instance=ExtResource("1_iobj")]
|
||||||
position = Vector2(1180, 560)
|
position = Vector2(1180, 560)
|
||||||
|
|
||||||
|
[node name="SnapBenchLeft1" type="Node2D" parent="."]
|
||||||
|
position = Vector2(150, 555)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|
||||||
|
[node name="SnapBenchLeft2" type="Node2D" parent="."]
|
||||||
|
position = Vector2(240, 555)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|
||||||
|
[node name="SnapBenchRight1" type="Node2D" parent="."]
|
||||||
|
position = Vector2(990, 555)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|
||||||
|
[node name="SnapBenchRight2" type="Node2D" parent="."]
|
||||||
|
position = Vector2(1080, 555)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
[gd_scene load_steps=2 format=3 uid="uid://cozypaw_restaurant"]
|
[gd_scene load_steps=3 format=3 uid="uid://cozypaw_restaurant"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
|
||||||
|
|
||||||
[node name="Restaurant" type="Node2D"]
|
[node name="Restaurant" type="Node2D"]
|
||||||
|
|
||||||
@@ -93,3 +94,27 @@ position = Vector2(1060, 490)
|
|||||||
|
|
||||||
[node name="CashRegister" parent="." instance=ExtResource("1_iobj")]
|
[node name="CashRegister" parent="." instance=ExtResource("1_iobj")]
|
||||||
position = Vector2(640, 210)
|
position = Vector2(640, 210)
|
||||||
|
|
||||||
|
[node name="SnapTable1Left" type="Node2D" parent="."]
|
||||||
|
position = Vector2(160, 510)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|
||||||
|
[node name="SnapTable1Right" type="Node2D" parent="."]
|
||||||
|
position = Vector2(280, 510)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|
||||||
|
[node name="SnapTable2Left" type="Node2D" parent="."]
|
||||||
|
position = Vector2(580, 510)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|
||||||
|
[node name="SnapTable2Right" type="Node2D" parent="."]
|
||||||
|
position = Vector2(700, 510)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|
||||||
|
[node name="SnapTable3Left" type="Node2D" parent="."]
|
||||||
|
position = Vector2(1000, 510)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|
||||||
|
[node name="SnapTable3Right" type="Node2D" parent="."]
|
||||||
|
position = Vector2(1120, 510)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
[gd_scene load_steps=2 format=3 uid="uid://cozypaw_lab"]
|
[gd_scene load_steps=3 format=3 uid="uid://cozypaw_lab"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
|
||||||
|
|
||||||
[node name="Lab" type="Node2D"]
|
[node name="Lab" type="Node2D"]
|
||||||
|
|
||||||
@@ -68,3 +69,11 @@ position = Vector2(820, 450)
|
|||||||
|
|
||||||
[node name="PetriDish" parent="." instance=ExtResource("1_iobj")]
|
[node name="PetriDish" parent="." instance=ExtResource("1_iobj")]
|
||||||
position = Vector2(490, 450)
|
position = Vector2(490, 450)
|
||||||
|
|
||||||
|
[node name="SnapLabBench1" type="Node2D" parent="."]
|
||||||
|
position = Vector2(450, 470)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|
||||||
|
[node name="SnapLabBench2" type="Node2D" parent="."]
|
||||||
|
position = Vector2(750, 470)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
[gd_scene load_steps=2 format=3 uid="uid://cozypaw_patientroom"]
|
[gd_scene load_steps=3 format=3 uid="uid://cozypaw_patientroom"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
|
||||||
|
|
||||||
[node name="PatientRoom" type="Node2D"]
|
[node name="PatientRoom" type="Node2D"]
|
||||||
|
|
||||||
@@ -82,3 +83,13 @@ position = Vector2(1100, 265)
|
|||||||
|
|
||||||
[node name="BedsideTable" parent="." instance=ExtResource("1_iobj")]
|
[node name="BedsideTable" parent="." instance=ExtResource("1_iobj")]
|
||||||
position = Vector2(500, 540)
|
position = Vector2(500, 540)
|
||||||
|
|
||||||
|
[node name="SnapBed1" type="Node2D" parent="."]
|
||||||
|
position = Vector2(250, 465)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
pose = "lying"
|
||||||
|
|
||||||
|
[node name="SnapBed2" type="Node2D" parent="."]
|
||||||
|
position = Vector2(810, 465)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
pose = "lying"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
[gd_scene load_steps=2 format=3 uid="uid://cozypaw_pharmacy"]
|
[gd_scene load_steps=3 format=3 uid="uid://cozypaw_pharmacy"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
|
||||||
|
|
||||||
[node name="Pharmacy" type="Node2D"]
|
[node name="Pharmacy" type="Node2D"]
|
||||||
|
|
||||||
@@ -68,3 +69,7 @@ position = Vector2(900, 270)
|
|||||||
|
|
||||||
[node name="MedicineBox" parent="." instance=ExtResource("1_iobj")]
|
[node name="MedicineBox" parent="." instance=ExtResource("1_iobj")]
|
||||||
position = Vector2(640, 430)
|
position = Vector2(640, 430)
|
||||||
|
|
||||||
|
[node name="SnapCounter" type="Node2D" parent="."]
|
||||||
|
position = Vector2(640, 520)
|
||||||
|
script = ExtResource("2_snap")
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
[gd_scene load_steps=3 format=3 uid="uid://cozypaw_xray"]
|
[gd_scene load_steps=4 format=3 uid="uid://cozypaw_xray"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/XRayMachine.tscn" id="2_xraymachine"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/XRayMachine.tscn" id="2_xraymachine"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="3_snap"]
|
||||||
|
|
||||||
[node name="XRay" type="Node2D"]
|
[node name="XRay" type="Node2D"]
|
||||||
|
|
||||||
@@ -53,3 +54,8 @@ position = Vector2(500, 510)
|
|||||||
|
|
||||||
[node name="PlasterStation" parent="." instance=ExtResource("1_iobj")]
|
[node name="PlasterStation" parent="." instance=ExtResource("1_iobj")]
|
||||||
position = Vector2(900, 560)
|
position = Vector2(900, 560)
|
||||||
|
|
||||||
|
[node name="SnapExamTable" type="Node2D" parent="."]
|
||||||
|
position = Vector2(640, 480)
|
||||||
|
script = ExtResource("3_snap")
|
||||||
|
pose = "lying"
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
[gd_scene load_steps=3 format=3 uid="uid://cozypaw_deliveryroom"]
|
[gd_scene load_steps=4 format=3 uid="uid://cozypaw_deliveryroom"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/DeliveryBed.tscn" id="2_deliverybed"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/DeliveryBed.tscn" id="2_deliverybed"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="3_snap"]
|
||||||
|
|
||||||
[node name="DeliveryRoom" type="Node2D"]
|
[node name="DeliveryRoom" type="Node2D"]
|
||||||
|
|
||||||
@@ -36,3 +37,8 @@ position = Vector2(1020, 540)
|
|||||||
|
|
||||||
[node name="BabyBlanket" parent="." instance=ExtResource("1_iobj")]
|
[node name="BabyBlanket" parent="." instance=ExtResource("1_iobj")]
|
||||||
position = Vector2(880, 540)
|
position = Vector2(880, 540)
|
||||||
|
|
||||||
|
[node name="SnapDeliveryBed" type="Node2D" parent="."]
|
||||||
|
position = Vector2(540, 480)
|
||||||
|
script = ExtResource("3_snap")
|
||||||
|
pose = "lying"
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
[gd_scene load_steps=3 format=3 uid="uid://cozypaw_nursery"]
|
[gd_scene load_steps=4 format=3 uid="uid://cozypaw_nursery"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/Cradle.tscn" id="2_cradle"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/Cradle.tscn" id="2_cradle"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="3_snap"]
|
||||||
|
|
||||||
[node name="Nursery" type="Node2D"]
|
[node name="Nursery" type="Node2D"]
|
||||||
|
|
||||||
@@ -47,3 +48,21 @@ position = Vector2(1100, 540)
|
|||||||
|
|
||||||
[node name="MilkBottle" parent="." instance=ExtResource("1_iobj")]
|
[node name="MilkBottle" parent="." instance=ExtResource("1_iobj")]
|
||||||
position = Vector2(960, 540)
|
position = Vector2(960, 540)
|
||||||
|
|
||||||
|
[node name="SnapCradle1" type="Node2D" parent="."]
|
||||||
|
position = Vector2(340, 240)
|
||||||
|
script = ExtResource("3_snap")
|
||||||
|
pose = "lying"
|
||||||
|
baby_only = true
|
||||||
|
|
||||||
|
[node name="SnapCradle2" type="Node2D" parent="."]
|
||||||
|
position = Vector2(600, 240)
|
||||||
|
script = ExtResource("3_snap")
|
||||||
|
pose = "lying"
|
||||||
|
baby_only = true
|
||||||
|
|
||||||
|
[node name="SnapCradle3" type="Node2D" parent="."]
|
||||||
|
position = Vector2(860, 240)
|
||||||
|
script = ExtResource("3_snap")
|
||||||
|
pose = "lying"
|
||||||
|
baby_only = true
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
[gd_scene load_steps=3 format=3 uid="uid://cozypaw_ultrasound"]
|
[gd_scene load_steps=4 format=3 uid="uid://cozypaw_ultrasound"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/UltrasoundMachine.tscn" id="2_ultrasound"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/UltrasoundMachine.tscn" id="2_ultrasound"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="3_snap"]
|
||||||
|
|
||||||
[node name="Ultrasound" type="Node2D"]
|
[node name="Ultrasound" type="Node2D"]
|
||||||
|
|
||||||
@@ -51,3 +52,8 @@ position = Vector2(920, 450)
|
|||||||
|
|
||||||
[node name="Blanket" parent="." instance=ExtResource("1_iobj")]
|
[node name="Blanket" parent="." instance=ExtResource("1_iobj")]
|
||||||
position = Vector2(480, 450)
|
position = Vector2(480, 450)
|
||||||
|
|
||||||
|
[node name="SnapExamTable" type="Node2D" parent="."]
|
||||||
|
position = Vector2(470, 480)
|
||||||
|
script = ExtResource("3_snap")
|
||||||
|
pose = "lying"
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
[gd_scene load_steps=4 format=3 uid="uid://cozypaw_gardenparty"]
|
[gd_scene load_steps=5 format=3 uid="uid://cozypaw_gardenparty"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/GiftBox.tscn" id="1_giftbox"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/GiftBox.tscn" id="1_giftbox"]
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/TeaPot.tscn" id="2_teapot"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/TeaPot.tscn" id="2_teapot"]
|
||||||
[ext_resource type="PackedScene" path="res://scenes/objects/HomeButton.tscn" id="3_homebtn"]
|
[ext_resource type="PackedScene" path="res://scenes/objects/HomeButton.tscn" id="3_homebtn"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="4_snap"]
|
||||||
|
|
||||||
[node name="GardenParty" type="Node2D"]
|
[node name="GardenParty" type="Node2D"]
|
||||||
|
|
||||||
@@ -84,3 +85,11 @@ color = Color(0.56, 0.76, 0.96, 1)
|
|||||||
[node name="HomeButtonReturn" parent="." instance=ExtResource("3_homebtn")]
|
[node name="HomeButtonReturn" parent="." instance=ExtResource("3_homebtn")]
|
||||||
position = Vector2(100, 620)
|
position = Vector2(100, 620)
|
||||||
go_to_garden = false
|
go_to_garden = false
|
||||||
|
|
||||||
|
[node name="SnapTableLeft" type="Node2D" parent="."]
|
||||||
|
position = Vector2(530, 455)
|
||||||
|
script = ExtResource("4_snap")
|
||||||
|
|
||||||
|
[node name="SnapTableRight" type="Node2D" parent="."]
|
||||||
|
position = Vector2(750, 455)
|
||||||
|
script = ExtResource("4_snap")
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
## Tests verifying SnapPoints exist in all EG (Erdgeschoss) room scenes.
|
||||||
|
extends GutTest
|
||||||
|
|
||||||
|
|
||||||
|
func _count_snaps(room: Node2D) -> int:
|
||||||
|
var count: int = 0
|
||||||
|
for child: Node in room.get_children():
|
||||||
|
if child is SnapPoint:
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
func _count_snaps_with_pose(room: Node2D, pose: String) -> int:
|
||||||
|
var count: int = 0
|
||||||
|
for child: Node in room.get_children():
|
||||||
|
var snap: SnapPoint = child as SnapPoint
|
||||||
|
if snap != null and snap.pose == pose:
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
func test_reception_has_four_snap_points() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor0/Reception.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 4)
|
||||||
|
|
||||||
|
|
||||||
|
func test_reception_all_snaps_are_sitting() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor0/Reception.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "sitting"), 4)
|
||||||
|
|
||||||
|
|
||||||
|
func test_giftshop_has_one_snap_point() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor0/GiftShop.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_giftshop_snap_is_sitting() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor0/GiftShop.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "sitting"), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_restaurant_has_six_snap_points() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor0/Restaurant.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 6)
|
||||||
|
|
||||||
|
|
||||||
|
func test_restaurant_all_snaps_are_sitting() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor0/Restaurant.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "sitting"), 6)
|
||||||
|
|
||||||
|
|
||||||
|
func test_emergency_room_has_one_snap_point() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor0/EmergencyRoom.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_emergency_room_snap_is_lying() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor0/EmergencyRoom.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "lying"), 1)
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
## Tests verifying SnapPoints exist in all 1.OG room scenes.
|
||||||
|
extends GutTest
|
||||||
|
|
||||||
|
|
||||||
|
func _count_snaps(room: Node2D) -> int:
|
||||||
|
var count: int = 0
|
||||||
|
for child: Node in room.get_children():
|
||||||
|
if child is SnapPoint:
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
func _count_snaps_with_pose(room: Node2D, pose: String) -> int:
|
||||||
|
var count: int = 0
|
||||||
|
for child: Node in room.get_children():
|
||||||
|
var snap: SnapPoint = child as SnapPoint
|
||||||
|
if snap != null and snap.pose == pose:
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
func test_xray_has_one_snap_point() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor1/XRay.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_xray_snap_is_lying() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor1/XRay.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "lying"), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_pharmacy_has_one_snap_point() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor1/Pharmacy.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_pharmacy_snap_is_sitting() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor1/Pharmacy.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "sitting"), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_lab_has_two_snap_points() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor1/Lab.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 2)
|
||||||
|
|
||||||
|
|
||||||
|
func test_lab_all_snaps_are_sitting() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor1/Lab.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "sitting"), 2)
|
||||||
|
|
||||||
|
|
||||||
|
func test_patient_room_has_two_snap_points() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor1/PatientRoom.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 2)
|
||||||
|
|
||||||
|
|
||||||
|
func test_patient_room_all_snaps_are_lying() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor1/PatientRoom.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "lying"), 2)
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
## Tests verifying SnapPoints exist in all 2.OG and Garten room scenes.
|
||||||
|
extends GutTest
|
||||||
|
|
||||||
|
|
||||||
|
func _count_snaps(room: Node2D) -> int:
|
||||||
|
var count: int = 0
|
||||||
|
for child: Node in room.get_children():
|
||||||
|
if child is SnapPoint:
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
func _count_snaps_with_pose(room: Node2D, pose: String) -> int:
|
||||||
|
var count: int = 0
|
||||||
|
for child: Node in room.get_children():
|
||||||
|
var snap: SnapPoint = child as SnapPoint
|
||||||
|
if snap != null and snap.pose == pose:
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
func _count_snaps_baby_only(room: Node2D) -> int:
|
||||||
|
var count: int = 0
|
||||||
|
for child: Node in room.get_children():
|
||||||
|
var snap: SnapPoint = child as SnapPoint
|
||||||
|
if snap != null and snap.baby_only:
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
func test_ultrasound_has_one_snap_point() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor2/Ultrasound.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_ultrasound_snap_is_lying() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor2/Ultrasound.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "lying"), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_delivery_room_has_one_snap_point() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor2/DeliveryRoom.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_delivery_room_snap_is_lying() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor2/DeliveryRoom.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "lying"), 1)
|
||||||
|
|
||||||
|
|
||||||
|
func test_nursery_has_three_snap_points() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor2/Nursery.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 3)
|
||||||
|
|
||||||
|
|
||||||
|
func test_nursery_all_snaps_are_baby_only() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor2/Nursery.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_baby_only(room), 3)
|
||||||
|
|
||||||
|
|
||||||
|
func test_nursery_all_snaps_are_lying() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/floor2/Nursery.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "lying"), 3)
|
||||||
|
|
||||||
|
|
||||||
|
func test_garden_party_has_two_snap_points() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/home/GardenParty.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps(room), 2)
|
||||||
|
|
||||||
|
|
||||||
|
func test_garden_party_all_snaps_are_sitting() -> void:
|
||||||
|
var room: Node2D = preload("res://scenes/rooms/home/GardenParty.tscn").instantiate() as Node2D
|
||||||
|
add_child_autofree(room)
|
||||||
|
assert_eq(_count_snaps_with_pose(room, "sitting"), 2)
|
||||||
Reference in New Issue
Block a user