Add northern pursuit scenario

This commit is contained in:
2026-06-17 23:11:56 +09:00
parent b08c2ac37e
commit 1c235f7e05
11 changed files with 392 additions and 13 deletions

View File

@@ -1,10 +1,10 @@
# Heroes of Three Kingdoms
Godot 4 tactical RPG prototype inspired by classic turn-based Romance of the Three Kingdoms games. The current editor target is moving to Godot 4.6.
Godot 4 tactical RPG prototype inspired by classic turn-based Romance of the Three Kingdoms games. The current editor baseline is Godot 4.6.
## Current Slice
- Seventeen campaign scenarios.
- Eighteen campaign scenarios.
- Grid movement.
- Unit selection.
- Move, attack, wait, end turn.
@@ -38,6 +38,7 @@ Godot 4 tactical RPG prototype inspired by classic turn-based Romance of the Thr
- Ye consumes the Cangting branch flags and lets Zhang He deploy against the Yuan heirs.
- Ye Siege consumes the Ye campaign branch flags and stages an inner-gate breach.
- Ye Surrender consumes the siege branch flags and settles the city before the Yuan heirs flee north.
- Northern Pursuit consumes the Ye surrender branch flags and pushes Yuan Shang's rearguard north from Ye.
- Post-battle choices can save campaign flags that branch later briefing text, shop stock, and scenario events.
- Scenario post-battle dialogue can play before the victory result panel.
- Basic battle EXP, level-ups, and core first-tier class promotion routes.

View File

@@ -88,6 +88,11 @@
"id": "017_ye_surrender",
"title": "Ye Surrender",
"path": "res://data/scenarios/017_ye_surrender.json"
},
{
"id": "018_northern_pursuit",
"title": "Northern Pursuit",
"path": "res://data/scenarios/018_northern_pursuit.json"
}
]
}

View File

@@ -0,0 +1,356 @@
{
"id": "018_northern_pursuit",
"name": "Northern Pursuit",
"objectives": {
"victory": "Push Cao Cao to the northern road, then defeat Yuan Shang's rearguard.",
"defeat": "Cao Cao is defeated or the battle reaches Turn 15."
},
"conditions": {
"victory": { "type": "all_units_defeated", "team": "enemy", "after_event": "yuan_rearguard_formed" },
"defeat": [
{ "type": "any_officer_defeated", "team": "player", "officer_ids": ["cao_cao"] },
{ "type": "turn_reached", "turn": 15, "team": "player" }
]
},
"briefing": {
"title": "Northern Pursuit",
"location": "North Road from Ye, 203 CE",
"lines": [
"Ye has fallen, but Yuan Shang flees north with enough banners to pretend his command still exists.",
"Cao Cao sends Zhang He ahead to read the retreat road while Guo Jia watches for the moment a fleeing heir becomes a trapped one."
],
"conditional_lines": [
{
"campaign_flags": { "pursued_yuan_shang": true },
"lines": [
"The immediate pursuit catches Yuan Shang's baggage train stretched thin, but Cao Cao's own vanguard is marching hard."
]
},
{
"campaign_flags": { "stabilized_ye": true },
"lines": [
"Ye's administration now feeds the road behind Cao Cao, giving the pursuit fewer gaps for Yuan loyalists to exploit."
]
}
]
},
"shop": {
"items": [
"bean",
"wine",
"iron_sword",
"training_spear",
"short_bow",
"hand_axe",
"war_axe",
"leather_armor",
"iron_armor"
],
"conditional_items": [
{
"campaign_flags": { "pursued_yuan_shang": true },
"items": ["war_drum"]
},
{
"campaign_flags": { "stabilized_ye": true },
"items": ["imperial_seal"]
}
]
},
"roster": {
"max_units": 7,
"required_officers": ["cao_cao", "guo_jia"]
},
"formation": {
"cells": [[1, 3], [1, 4], [1, 5], [2, 2], [2, 3], [2, 4], [2, 5], [2, 6], [3, 2], [3, 3], [3, 4], [3, 5], [3, 6]]
},
"map": {
"width": 18,
"height": 11,
"terrain": [
"GGGGGHHGGGGGGGGGGG",
"GGFFGHHGGGFFGGGFFG",
"GGRRRRRRRRRRRRGFFG",
"GGGGGRGGGGRRGGGGGG",
"RRRRRRRRRRRRRRRRRR",
"GGGGGRGGGGRRGGGGGG",
"GGHHGFFFGGFFFGGHHG",
"GGHHGFFFGGFFFGGHHG",
"GGGGGGFFGGHHHGGGGG",
"GGFFGGGGGGHHHFFGGG",
"GGGGGGGGGGGGGGGGGG"
]
},
"deployments": [
{
"unit_id": "cao_cao_ch18",
"officer_id": "cao_cao",
"team": "player",
"pos": [1, 4]
},
{
"unit_id": "guo_jia_ch18",
"officer_id": "guo_jia",
"team": "player",
"requires_joined": true,
"pos": [2, 4]
},
{
"unit_id": "zhang_he_ch18",
"officer_id": "zhang_he",
"team": "player",
"requires_joined": true,
"pos": [2, 3]
},
{
"unit_id": "xiahou_dun_ch18",
"officer_id": "xiahou_dun",
"team": "player",
"pos": [1, 5]
},
{
"unit_id": "dian_wei_ch18",
"officer_id": "dian_wei",
"team": "player",
"requires_joined": true,
"pos": [2, 5]
},
{
"unit_id": "xiahou_yuan_ch18",
"officer_id": "xiahou_yuan",
"team": "player",
"requires_joined": true,
"pos": [3, 3]
},
{
"unit_id": "cao_ren_ch18",
"officer_id": "cao_ren",
"team": "player",
"requires_joined": true,
"pos": [3, 4]
},
{
"unit_id": "yuan_shang_rearguard",
"name": "Yuan Shang Rearguard",
"class_id": "commander",
"team": "enemy",
"level": 17,
"pos": [14, 4],
"base": { "hp": 84, "mp": 20, "atk": 23, "def": 17, "int": 13, "agi": 12 }
},
{
"unit_id": "northern_road_captain",
"name": "Northern Road Captain",
"class_id": "guard_captain",
"team": "enemy",
"level": 16,
"pos": [12, 4],
"base": { "hp": 64, "atk": 20, "def": 16 }
},
{
"unit_id": "yuan_retreat_advisor",
"name": "Retreat Advisor",
"class_id": "military_advisor",
"team": "enemy",
"level": 16,
"pos": [15, 5],
"skills": ["blaze", "great_mend"],
"base": { "hp": 52, "mp": 36, "atk": 7, "def": 9, "int": 19, "agi": 10 }
},
{
"unit_id": "northern_spear_north",
"name": "Northern Spear Guard",
"class_id": "infantry",
"team": "enemy",
"level": 16,
"pos": [12, 3],
"base": { "hp": 56, "atk": 19, "def": 13 }
},
{
"unit_id": "northern_spear_south",
"name": "Northern Spear Guard",
"class_id": "infantry",
"team": "enemy",
"level": 16,
"pos": [12, 5],
"base": { "hp": 56, "atk": 19, "def": 13 }
},
{
"unit_id": "northern_archer_north",
"name": "Northern Archer",
"class_id": "marksman",
"team": "enemy",
"level": 16,
"pos": [13, 2],
"base": { "hp": 46, "atk": 19, "def": 8, "agi": 15 }
},
{
"unit_id": "northern_archer_south",
"name": "Northern Archer",
"class_id": "marksman",
"team": "enemy",
"level": 16,
"pos": [14, 6],
"base": { "hp": 46, "atk": 19, "def": 8, "agi": 15 }
},
{
"unit_id": "yuan_escape_rider",
"name": "Yuan Escape Rider",
"class_id": "elite_cavalry",
"team": "enemy",
"level": 16,
"pos": [15, 3],
"base": { "hp": 60, "atk": 20, "def": 12, "agi": 15 }
}
],
"events": [
{
"id": "opening",
"once": true,
"when": { "type": "battle_start" },
"actions": [
{ "type": "log", "text": "Yuan Shang's rearguard blocks the road north from Ye." }
]
},
{
"id": "opening_dialogue",
"once": true,
"when": { "type": "battle_begin" },
"actions": [
{
"type": "dialogue",
"lines": [
{ "speaker": "Zhang He", "text": "Yuan Shang runs north, but his captains are trying to make a wall out of retreating men." },
{ "speaker": "Cao Cao", "text": "Then we break the wall before it remembers it is an army." },
{ "speaker": "Guo Jia", "text": "A fleeing heir still has value. A trapped heir has more." }
]
}
]
},
{
"id": "rapid_pursuit_strain",
"once": true,
"when": { "type": "turn_start", "team": "player", "turn": 2, "campaign_flags": { "pursued_yuan_shang": true } },
"actions": [
{
"type": "dialogue",
"lines": [
{ "speaker": "Xiahou Yuan", "text": "We caught the dust of Yuan Shang's standards. Another push and his baggage is ours." },
{ "speaker": "Guo Jia", "text": "Fast pursuit wins distance, but tired men must still win the road." }
]
}
]
},
{
"id": "ye_supply_arrives",
"once": true,
"when": { "type": "turn_start", "team": "player", "turn": 2, "campaign_flags": { "stabilized_ye": true } },
"actions": [
{
"type": "dialogue",
"lines": [
{ "speaker": "Cao Ren", "text": "Grain from Ye has reached the columns. The road behind us is quiet." },
{ "speaker": "Cao Cao", "text": "Good. A quiet rear lets the front speak plainly." }
]
}
]
},
{
"id": "turn_3_rearguard_orders",
"once": true,
"when": { "type": "turn_start", "team": "enemy", "turn": 3 },
"actions": [
{
"type": "dialogue",
"lines": [
{ "speaker": "Yuan Shang Rearguard", "text": "Hold the road until the heir reaches the next command tent. No one retreats without my order." },
{ "speaker": "Zhang He", "text": "They still protect the tent, not the province." }
]
}
]
},
{
"id": "yuan_rearguard_formed",
"once": true,
"when": { "type": "unit_reaches_tile", "team": "player", "officer_ids": ["cao_cao"], "pos": [10, 4] },
"actions": [
{
"type": "set_objective",
"victory": "The northern road is reached. Defeat Yuan Shang's formed rearguard.",
"defeat": "Cao Cao is defeated or the battle reaches Turn 15."
},
{
"type": "dialogue",
"lines": [
{ "speaker": "Cao Cao", "text": "The road is in sight. Cut down the screen before Yuan Shang grows another army behind it." },
{ "speaker": "Yuan Shang Rearguard", "text": "Close the road. If Cao Cao sees the fleeing banners, we have failed." }
]
},
{
"type": "spawn_deployments",
"deployments": [
{
"unit_id": "yuan_baggage_guard",
"name": "Baggage Guard",
"class_id": "guard_captain",
"team": "enemy",
"level": 16,
"pos": [16, 4],
"base": { "hp": 60, "atk": 19, "def": 15 }
},
{
"unit_id": "yuan_baggage_archer",
"name": "Baggage Archer",
"class_id": "archer",
"team": "enemy",
"level": 16,
"pos": [16, 5],
"base": { "hp": 40, "atk": 17, "def": 7, "agi": 13 }
}
]
}
]
},
{
"id": "turn_7_pursuit_closes",
"once": true,
"when": { "type": "turn_start", "team": "player", "turn": 7 },
"actions": [
{
"type": "dialogue",
"lines": [
{ "speaker": "Guo Jia", "text": "The rearguard is losing shape. Yuan Shang is learning that a retreat can be surrounded from behind." },
{ "speaker": "Cao Cao", "text": "Then make the lesson brief." }
]
}
]
}
],
"rewards": {
"gold": 3200,
"items": ["bean", "wine", "war_axe"]
},
"post_battle_dialogue": [
{ "speaker": "Zhang He", "text": "Yuan Shang's screen is broken, but the Yuan heirs still have northern towns that will answer a familiar seal." },
{ "speaker": "Guo Jia", "text": "Then we decide whether to chase the seal or make the towns afraid to use it." },
{ "speaker": "Cao Cao", "text": "The north will not be settled by one road. Choose the next pressure." }
],
"post_battle_choices": [
{
"id": "press_north_to_nanpi",
"label": "Press Nanpi",
"description": "Cao Cao keeps pressure on the Yuan heirs before they can gather at Nanpi.",
"set_flags": { "pressed_north_to_nanpi": true, "secured_ji_province": false },
"gold": 150,
"items": ["war_drum"]
},
{
"id": "secure_ji_province",
"label": "Secure Ji Province",
"description": "The army secures surrendered towns and supply lines before the next northern strike.",
"set_flags": { "pressed_north_to_nanpi": false, "secured_ji_province": true },
"gold": 400,
"items": ["imperial_seal"]
}
]
}

View File

@@ -28,6 +28,7 @@ data/scenarios/014_cangting_pursuit.json
data/scenarios/015_ye_campaign.json
data/scenarios/016_ye_siege.json
data/scenarios/017_ye_surrender.json
data/scenarios/018_northern_pursuit.json
```
## Campaign
@@ -57,7 +58,8 @@ The campaign file defines scenario order, resource paths, and officers who are a
{ "id": "014_cangting_pursuit", "title": "Cangting Pursuit", "path": "res://data/scenarios/014_cangting_pursuit.json" },
{ "id": "015_ye_campaign", "title": "Ye Campaign", "path": "res://data/scenarios/015_ye_campaign.json" },
{ "id": "016_ye_siege", "title": "Ye Siege", "path": "res://data/scenarios/016_ye_siege.json" },
{ "id": "017_ye_surrender", "title": "Ye Surrender", "path": "res://data/scenarios/017_ye_surrender.json" }
{ "id": "017_ye_surrender", "title": "Ye Surrender", "path": "res://data/scenarios/017_ye_surrender.json" },
{ "id": "018_northern_pursuit", "title": "Northern Pursuit", "path": "res://data/scenarios/018_northern_pursuit.json" }
]
}
```

View File

@@ -1,15 +1,16 @@
# Godot 4.6 Migration
This project targets Godot 4 and is being moved toward Godot 4.6 as the active editor baseline.
This project targets Godot 4.6 as the active editor baseline.
## Current Risk Profile
- The project is a simple Godot 4 `Node2D` application with data-driven JSON content.
- There are no addons, imported art assets, shaders, TileMaps, 3D physics scenes, or export presets yet.
- The current renderer is explicitly set to `gl_compatibility`, so new-project rendering defaults in Godot 4.6 should not silently change the existing project renderer.
- `project.godot` still advertises `config/features=PackedStringArray("4.2")`; let the Godot 4.6 editor update project files instead of editing generated scene/resource formats by hand.
- `project.godot` advertises `config/features=PackedStringArray("4.6")`.
- Godot 4.6 script UID sidecar files (`*.gd.uid`) are part of the migrated project metadata and should stay versioned.
## Before Opening In 4.6
## Before Opening In 4.6 From An Older Checkout
1. Create a backup or initialize version control before the editor writes migration changes.
2. Run the data/readiness check:
@@ -24,7 +25,7 @@ powershell -NoProfile -ExecutionPolicy Bypass -File tools\check_godot46_readines
$env:GODOT_BIN = "C:\Path\To\Godot_v4.6-stable_win64.exe"
```
## Editor Migration Steps
## Editor Migration Steps From An Older Checkout
1. Open the project folder in Godot 4.6.
2. Let the editor import the project and accept any project-file migration prompt.

View File

@@ -3,6 +3,7 @@
## Milestone 0: Project Foundation
- Godot 4 project opens and runs.
- Godot 4.6 project metadata exists.
- Main battle scene loads a JSON battle.
- Rules and presentation are separated enough to keep iterating.
@@ -20,7 +21,7 @@
- Destination victory conditions and objective map markers exist.
- Turn-limit conditions and HUD turn-limit display exist.
- Victory reward summary is visible.
- Next-battle flow exists across the current seventeen-scenario campaign.
- Next-battle flow exists across the current eighteen-scenario campaign.
- Campaign completion and new-campaign reset exist.
- Reward inventory can be brought into the next battle.
@@ -51,7 +52,7 @@
- Party roster persistence has a first save-file skeleton.
- Level, experience, and equipment persistence.
- Chapter selection and save/load.
- Linear seventeen-scenario campaign order exists.
- Linear eighteen-scenario campaign order exists.
- Save reset exists.
- Victory rewards, consumable counts, equipment stock, and equipped gear persist.
- A basic pre-battle shop with scenario-specific stock exists. Sell-back and richer item management are still planned.
@@ -76,6 +77,7 @@
- Fifteenth-scenario content exists with Ye outer defense, Zhang He as a deployable officer, and 014 branch reactions.
- Sixteenth-scenario content exists with Ye inner siege, Zhang He deployment, and 015 branch reactions.
- Seventeenth-scenario content exists with Ye surrender, last loyalist resistance, and 016 branch reactions.
- Eighteenth-scenario content exists with Northern Pursuit, Yuan Shang's rearguard, and 017 branch reactions.
## Milestone 5: Presentation

View File

@@ -1,13 +1,22 @@
; Engine configuration file.
; Prefer editing through the Godot editor when project settings become more complex.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=5
[animation]
compatibility/default_parent_skeleton_in_mesh_instance_3d=true
[application]
config/name="Heroes of Three Kingdoms"
run/main_scene="res://scenes/battle_scene.tscn"
config/features=PackedStringArray("4.2")
config/features=PackedStringArray("4.6")
[display]
@@ -17,6 +26,5 @@ window/stretch/mode="canvas_items"
[rendering]
renderer/rendering_method="gl_compatibility"
textures/canvas_textures/default_texture_filter=0
renderer/rendering_method="gl_compatibility"

View File

@@ -0,0 +1 @@
uid://byep5djrolvxo

View File

@@ -0,0 +1 @@
uid://cxrcmxon5btph

View File

@@ -0,0 +1 @@
uid://b8t0h8qkc0i0r

View File

@@ -0,0 +1 @@
uid://c8xt6m1e70a3q