Name hero in low-vigor tutorial guidance (#8680)

This commit is contained in:
2026-07-17 15:01:09 -07:00
committed by GitHub
parent 467d2e2c82
commit 1f18f3296d
4 changed files with 26 additions and 12 deletions
@@ -51,7 +51,7 @@ tutorial_unit_stunned_dialogue That unit has been stunned, Sadar. Until it recov
tutorial_unit_stunned_instruction A <b>stunned</b> unit has fewer available commands. Its stun counter decreases at the end of each of its turns.
tutorial_low_morale_dialogue That battalion's morale has broken, Sadar. Troops in such low spirits will refuse many dangerous orders. Their courage should recover toward its usual level as their turns begin, provided hunger and fresh losses do not drag it down again.
tutorial_low_morale_instruction A battalion with <b>low Morale</b> has fewer available commands. Morale normally recovers toward the battalion's usual level at the start of its turn, units in castles recover morale faster, and a Paladin's <b>Holy Wave</b> can restore Morale immediately.
tutorial_low_vigor_dialogue That hero is nearly exhausted, Sadar. Heroes fight alongside their battalions while they have vigor, but below ten many orders are beyond them. Leave the unit's remaining effort unspent, and some vigor will return when the turn ends.
tutorial_low_vigor_dialogue {heroName} is nearly exhausted, Sadar. Heroes fight alongside their battalions while they have vigor, but below ten many orders are beyond them. Leave the unit's remaining effort unspent, and some vigor will return when the turn ends.
tutorial_low_vigor_instruction Current <b>Vigor</b> contributes to maximum Action Points. Below 10 Vigor, most commands are unavailable. Unspent Action Points restore Vigor when the unit's turn ends, and a Paladin's <b>Holy Wave</b> can restore it immediately.
tutorial_zero_vigor_dialogue {heroName}'s last vigor is gone, Sadar. When a hero reaches zero vigor, the entire hero-led unit is captured — even if troops remain in the battalion.
tutorial_zero_vigor_instruction At <b>0 Vigor</b>, the hero-led unit is captured and removed from active battle. Its surviving battalion does not continue fighting independently.
Can't render this file because it contains an unexpected character in line 9 and column 47.
@@ -296,12 +296,19 @@ object TacticalTutorialDialogueContent {
unitId
)
def lowVigor(marekId: Int, unitId: Option[Int]): TutorialDialogue = single(
"tutorial_low_vigor",
marekId,
"tutorial_low_vigor_dialogue",
"tutorial_low_vigor_instruction",
unitId
def lowVigor(marekId: Int, heroId: Int, unitId: Option[Int]): TutorialDialogue = TutorialDialogue(
id = "tutorial_low_vigor",
steps = Vector(
step(
marekId,
"tutorial_low_vigor_dialogue",
Some("tutorial_low_vigor_instruction"),
unitId,
replacements = Vector(
TutorialTextReplacement("{heroName}", TutorialTextReplacementValue.HeroName(heroId))
)
)
)
)
def zeroVigor(marekId: Int, capturedHeroId: Int): TutorialDialogue = TutorialDialogue(
@@ -231,8 +231,9 @@ object TacticalTutorialDialogueSelector {
.find(_.moraleLow.contains(true))
.map(unit => Content.lowMorale(heroes.marek, Some(unit.unitId)))
val lowVigor = units
.find(unit => unit.attachedHero.nonEmpty && unit.vigorLow.contains(true))
.map(unit => Content.lowVigor(heroes.marek, Some(unit.unitId)))
.flatMap(unit => heroId(unit).map(_ -> unit))
.find { case (_, unit) => unit.vigorLow.contains(true) }
.map { case (heroId, unit) => Content.lowVigor(heroes.marek, heroId, Some(unit.unitId)) }
val zeroTroops = units
.find(unit => unit.attachedHero.nonEmpty && unit.battalion.exists(_.size == 0))
.map(unit => Content.zeroTroops(heroes.marek, Some(unit.unitId)))
@@ -5,7 +5,7 @@ import net.eagle0.eagle.model.state.date.Date
import net.eagle0.eagle.model.state.game_state.{EagleMapInfo, GameState}
import net.eagle0.eagle.model.state.hero.concrete.HeroC
import net.eagle0.eagle.model.state.run_status.RunStatus
import net.eagle0.eagle.model.view.action_result.TutorialFocus
import net.eagle0.eagle.model.view.action_result.{TutorialFocus, TutorialTextReplacement, TutorialTextReplacementValue}
import net.eagle0.shardok.api.action_result_view.ActionResultView
import net.eagle0.shardok.api.command_descriptor.{AvailableCommands, CommandDescriptor}
import net.eagle0.shardok.api.game_state_view.GameStateViewDiff
@@ -273,7 +273,7 @@ class TacticalTutorialDialogueSelectorTest extends AnyFlatSpec with Matchers {
val moraleUnit = UnitView(unitId = 202, moraleLow = Some(true))
val vigorUnit = UnitView(
unitId = 203,
attachedHero = Some(HeroView(eagleHeroId = Some(30))),
attachedHero = Some(HeroView(eagleHeroId = Some(SadarId))),
vigorLow = Some(true)
)
val zeroTroops = UnitView(
@@ -307,7 +307,13 @@ class TacticalTutorialDialogueSelectorTest extends AnyFlatSpec with Matchers {
)
dialogues.find(_.id == "tutorial_unit_stunned").get.steps.head.focus.shouldBe(Some(TutorialFocus.Unit(201)))
dialogues.find(_.id == "tutorial_low_morale").get.steps.head.focus.shouldBe(Some(TutorialFocus.Unit(202)))
dialogues.find(_.id == "tutorial_low_vigor").get.steps.head.focus.shouldBe(Some(TutorialFocus.Unit(203)))
val lowVigorDialogue = dialogues.find(_.id == "tutorial_low_vigor").get
lowVigorDialogue.steps.head.focus.shouldBe(Some(TutorialFocus.Unit(203)))
lowVigorDialogue.steps.head.textReplacements.shouldBe(
Vector(
TutorialTextReplacement("{heroName}", TutorialTextReplacementValue.HeroName(SadarId))
)
)
dialogues.find(_.id == "tutorial_zero_troops").get.steps.head.focus.shouldBe(Some(TutorialFocus.Unit(204)))
}