Add northern pursuit scenario
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
356
data/scenarios/018_northern_pursuit.json
Normal file
356
data/scenarios/018_northern_pursuit.json
Normal 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"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
1
scripts/core/battle_state.gd.uid
Normal file
1
scripts/core/battle_state.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://byep5djrolvxo
|
||||
1
scripts/core/campaign_state.gd.uid
Normal file
1
scripts/core/campaign_state.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cxrcmxon5btph
|
||||
1
scripts/core/data_catalog.gd.uid
Normal file
1
scripts/core/data_catalog.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b8t0h8qkc0i0r
|
||||
1
scripts/scenes/battle_scene.gd.uid
Normal file
1
scripts/scenes/battle_scene.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://c8xt6m1e70a3q
|
||||
Reference in New Issue
Block a user