mirror of
https://github.com/nolen777/eagle0.git
synced 2026-07-28 21:55:42 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07512e8077 |
@@ -28,4 +28,5 @@ enum RecruitmentStatus {
|
||||
RECRUITMENT_STATUS_HAS_QUEST = 10;
|
||||
RECRUITMENT_STATUS_EXILE = 11;
|
||||
RECRUITMENT_STATUS_MOVING_PRISONER = 12;
|
||||
RECRUITMENT_STATUS_WOULD_NEVER_JOIN = 13;
|
||||
}
|
||||
|
||||
+1
@@ -28,6 +28,7 @@ object AvailableDivineCommandsFactory extends ScalaAvailableCommandsFactory {
|
||||
) {
|
||||
val undivined = province.unaffiliatedHeroes
|
||||
.filter(_.recruitmentInfo == RecruitmentInfo.NotDivined)
|
||||
.filterNot(uh => gameState.heroes(uh.heroId).neverJoinFactionIds.contains(factionId))
|
||||
|
||||
val expandedHeroes = undivined.map(uh =>
|
||||
ExpandedUnaffiliatedHero(
|
||||
|
||||
+11
-5
@@ -29,10 +29,12 @@ object AvailableHandleCapturedHeroCommandFactory extends ScalaAvailableCommandsF
|
||||
|
||||
private def expandedCapturedHero(
|
||||
gs: GameState,
|
||||
ch: CapturedHero
|
||||
ch: CapturedHero,
|
||||
factionId: FactionId
|
||||
): ExpandedCapturedHero = {
|
||||
val isFactionLeader = FactionUtils
|
||||
.isFactionLeader(ch.heroId, gs.factions.values.toVector)
|
||||
val wouldNeverJoin = gs.heroes(ch.heroId).neverJoinFactionIds.contains(factionId)
|
||||
|
||||
ExpandedCapturedHero(
|
||||
heroId = ch.heroId,
|
||||
@@ -44,6 +46,7 @@ object AvailableHandleCapturedHeroCommandFactory extends ScalaAvailableCommandsF
|
||||
.exists(_.rulingFactionId.contains(ch.previousFactionId))
|
||||
then optionsForFactionLeader
|
||||
else if isFactionLeader then optionsWithoutRecruit
|
||||
else if wouldNeverJoin then optionsWithoutRecruit
|
||||
else optionsWithRecruit,
|
||||
messageId =
|
||||
if ch.recruitmentAttempted then ch.recruitmentRefusedMessageId
|
||||
@@ -55,14 +58,15 @@ object AvailableHandleCapturedHeroCommandFactory extends ScalaAvailableCommandsF
|
||||
private def firstOption(
|
||||
gameState: GameState,
|
||||
capturedHeroes: Vector[CapturedHero],
|
||||
provinceId: ProvinceId
|
||||
provinceId: ProvinceId,
|
||||
factionId: FactionId
|
||||
): Option[HandleCapturedHeroAvailable] =
|
||||
capturedHeroes
|
||||
.find(ch => ch.recruitmentRefusedMessageId.nonEmpty || ch.messageId.nonEmpty)
|
||||
.map { capturedHero =>
|
||||
HandleCapturedHeroAvailable(
|
||||
actingProvinceId = provinceId,
|
||||
availableHeroes = Vector(expandedCapturedHero(gameState, capturedHero))
|
||||
availableHeroes = Vector(expandedCapturedHero(gameState, capturedHero, factionId))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -82,13 +86,15 @@ object AvailableHandleCapturedHeroCommandFactory extends ScalaAvailableCommandsF
|
||||
firstOption(
|
||||
gameState = gameState,
|
||||
capturedHeroes = notRecruitedNonEmpty,
|
||||
provinceId = provinceId
|
||||
provinceId = provinceId,
|
||||
factionId = factionId
|
||||
)
|
||||
case (alreadyRecruitedNonEmpty, _) =>
|
||||
firstOption(
|
||||
gameState = gameState,
|
||||
capturedHeroes = alreadyRecruitedNonEmpty,
|
||||
provinceId = provinceId
|
||||
provinceId = provinceId,
|
||||
factionId = factionId
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -28,6 +28,7 @@ object AvailableRecruitHeroesCommandFactory extends ScalaAvailableCommandsFactor
|
||||
|
||||
val expandedRecruitable = province.unaffiliatedHeroes
|
||||
.filterNot(uh => FactionUtils.isFactionLeader(uh.heroId, gameState.factions.values.toVector))
|
||||
.filterNot(uh => gameState.heroes(uh.heroId).neverJoinFactionIds.contains(factionId))
|
||||
.filterNot(h =>
|
||||
RecruitmentOdds.scoreForUnaffiliatedHero(
|
||||
faction = faction,
|
||||
|
||||
+4
-1
@@ -57,7 +57,10 @@ object UnaffiliatedHeroUtils {
|
||||
factionId: FactionId,
|
||||
unaffiliatedHero: UnaffiliatedHeroT
|
||||
): Boolean = {
|
||||
val targetHero = gameState.heroes(unaffiliatedHero.heroId)
|
||||
val targetHero = gameState.heroes(unaffiliatedHero.heroId)
|
||||
// Heroes should not offer to join factions they'd never join
|
||||
if targetHero.neverJoinFactionIds.contains(factionId) then return false
|
||||
|
||||
val actingFaction = gameState.factions(factionId)
|
||||
val actingFactionLeader = gameState.heroes(actingFaction.factionHeadId)
|
||||
willPleaseRecruitMe(
|
||||
|
||||
@@ -6,6 +6,7 @@ import net.eagle0.eagle.library.util.province.ProvinceUtils
|
||||
import net.eagle0.eagle.library.util.StatWithConditionUtils.supportScala
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.province.{ProvinceEvent, ProvinceT}
|
||||
import net.eagle0.eagle.model.state.unaffiliated_hero.RecruitmentInfo
|
||||
import net.eagle0.eagle.model.view.incoming_army.{IncomingArmyView, UnitDetails}
|
||||
import net.eagle0.eagle.model.view.province.{FullProvinceInfo, ProvinceView, UnaffiliatedHeroBasics}
|
||||
import net.eagle0.eagle.FactionId
|
||||
@@ -323,7 +324,7 @@ object ProvinceViewFilter {
|
||||
hexMapName = province.hexMapName,
|
||||
castleCount = province.castleCount,
|
||||
heroCap = province.heroCap,
|
||||
unaffiliatedHeroes = province.unaffiliatedHeroes.map(unaffiliatedHeroInfoWithContext(_, gs, ctx)),
|
||||
unaffiliatedHeroes = province.unaffiliatedHeroes.map(unaffiliatedHeroInfoWithContext(_, gs, ctx, factionId)),
|
||||
rulerIsTraveling = province.rulerIsTraveling
|
||||
)
|
||||
|
||||
@@ -345,16 +346,24 @@ object ProvinceViewFilter {
|
||||
private def unaffiliatedHeroInfoWithContext(
|
||||
uh: net.eagle0.eagle.model.state.unaffiliated_hero.UnaffiliatedHeroT,
|
||||
gs: GameState,
|
||||
ctx: FilterContext
|
||||
ctx: FilterContext,
|
||||
viewingFactionId: Option[FactionId]
|
||||
): UnaffiliatedHeroBasics = {
|
||||
val hero = gs.heroes(uh.heroId)
|
||||
val hero = gs.heroes(uh.heroId)
|
||||
// Override recruitment info to WouldNeverJoin if the viewing faction is in the hero's neverJoinFactionIds
|
||||
val effectiveRecruitmentInfo = viewingFactionId match {
|
||||
case Some(fid) if hero.neverJoinFactionIds.contains(fid) =>
|
||||
RecruitmentInfo.WouldNeverJoin
|
||||
case _ =>
|
||||
uh.recruitmentInfo
|
||||
}
|
||||
UnaffiliatedHeroBasics(
|
||||
heroId = hero.id,
|
||||
nameTextId = hero.nameTextId,
|
||||
profession = hero.profession,
|
||||
status = uh.unaffiliatedHeroType,
|
||||
isFactionLeader = ctx.factionLeaderIds.contains(hero.id),
|
||||
recruitmentInfo = uh.recruitmentInfo
|
||||
recruitmentInfo = effectiveRecruitmentInfo
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -75,6 +75,8 @@ object UnaffiliatedHeroConverter {
|
||||
RecruitmentInfo.Exile
|
||||
case RecruitmentStatusProto.RECRUITMENT_STATUS_MOVING_PRISONER =>
|
||||
RecruitmentInfo.MovingPrisoner
|
||||
case RecruitmentStatusProto.RECRUITMENT_STATUS_WOULD_NEVER_JOIN =>
|
||||
RecruitmentInfo.WouldNeverJoin
|
||||
case RecruitmentStatusProto.Unrecognized(unrecognizedValue) =>
|
||||
throw new ProtoConversionException(
|
||||
s"Unrecognized recruitment status: $unrecognizedValue"
|
||||
@@ -137,6 +139,10 @@ object UnaffiliatedHeroConverter {
|
||||
RecruitmentInfoProto(
|
||||
status = RecruitmentStatusProto.RECRUITMENT_STATUS_MOVING_PRISONER
|
||||
)
|
||||
case RecruitmentInfo.WouldNeverJoin =>
|
||||
RecruitmentInfoProto(
|
||||
status = RecruitmentStatusProto.RECRUITMENT_STATUS_WOULD_NEVER_JOIN
|
||||
)
|
||||
}
|
||||
|
||||
def fromProto(uhProto: UnaffiliatedHeroProto): UnaffiliatedHeroT =
|
||||
|
||||
@@ -30,6 +30,7 @@ object RecruitmentInfo {
|
||||
case class HasQuest(quest: Quest) extends RecruitmentInfo
|
||||
case object Exile extends RecruitmentInfo
|
||||
case object MovingPrisoner extends RecruitmentInfo
|
||||
case object WouldNeverJoin extends RecruitmentInfo
|
||||
}
|
||||
|
||||
trait UnaffiliatedHeroT {
|
||||
|
||||
+40
@@ -172,4 +172,44 @@ class AvailableDivineCommandsFactoryTest extends AnyFlatSpec with Matchers with
|
||||
costPerHero shouldBe 110
|
||||
}
|
||||
}
|
||||
|
||||
it should "not include heroes who would never join this faction" in {
|
||||
val gs = makeGameState().copy(
|
||||
heroes = Map(
|
||||
10 -> HeroC(id = 10, factionId = Some(actingFid), nameTextId = "hero_10", vigor = 100),
|
||||
99 -> HeroC(id = 99, factionId = None, nameTextId = "hero_99", neverJoinFactionIds = Set(actingFid)),
|
||||
198 -> HeroC(id = 198, factionId = None, nameTextId = "hero_198", vigor = 100)
|
||||
)
|
||||
)
|
||||
|
||||
val command = AvailableDivineCommandsFactory
|
||||
.availableCommand(
|
||||
gameState = gs,
|
||||
factionId = actingFid,
|
||||
provinceId = actingPid
|
||||
)
|
||||
.get
|
||||
|
||||
inside(command) {
|
||||
case DivineAvailable(_, divinableHeroes, _, _) =>
|
||||
divinableHeroes should have size 1
|
||||
divinableHeroes.head.heroId shouldBe 198
|
||||
}
|
||||
}
|
||||
|
||||
it should "return None when all undivined heroes would never join this faction" in {
|
||||
val gs = makeGameState().copy(
|
||||
heroes = Map(
|
||||
10 -> HeroC(id = 10, factionId = Some(actingFid), nameTextId = "hero_10", vigor = 100),
|
||||
99 -> HeroC(id = 99, factionId = None, nameTextId = "hero_99", neverJoinFactionIds = Set(actingFid)),
|
||||
198 -> HeroC(id = 198, factionId = None, nameTextId = "hero_198", neverJoinFactionIds = Set(actingFid))
|
||||
)
|
||||
)
|
||||
|
||||
AvailableDivineCommandsFactory.availableCommand(
|
||||
gameState = gs,
|
||||
factionId = actingFid,
|
||||
provinceId = actingPid
|
||||
) shouldBe None
|
||||
}
|
||||
}
|
||||
|
||||
+39
@@ -217,4 +217,43 @@ class AvailableRecruitHeroesCommandFactoryTest extends AnyFlatSpec with Matchers
|
||||
provinceId = provinceId
|
||||
) shouldBe None
|
||||
}
|
||||
|
||||
it should "not include heroes who would never join this faction" in {
|
||||
val gs = makeGameState(
|
||||
heroes = Map(
|
||||
9 -> HeroC(id = 9, factionId = Some(factionId), nameTextId = "hn_9"),
|
||||
11 -> HeroC(id = 11, factionId = None, nameTextId = "hn_11", neverJoinFactionIds = Set(factionId))
|
||||
)
|
||||
)
|
||||
|
||||
AvailableRecruitHeroesCommandFactory.availableCommand(
|
||||
gameState = gs,
|
||||
factionId = factionId,
|
||||
provinceId = provinceId
|
||||
) shouldBe None
|
||||
}
|
||||
|
||||
it should "include heroes who would never join a different faction" in {
|
||||
val otherFactionId: FactionId = 99
|
||||
val gs = makeGameState(
|
||||
heroes = Map(
|
||||
9 -> HeroC(id = 9, factionId = Some(factionId), nameTextId = "hn_9"),
|
||||
11 -> HeroC(id = 11, factionId = None, nameTextId = "hn_11", neverJoinFactionIds = Set(otherFactionId))
|
||||
)
|
||||
)
|
||||
|
||||
val command = AvailableRecruitHeroesCommandFactory
|
||||
.availableCommand(
|
||||
gameState = gs,
|
||||
factionId = factionId,
|
||||
provinceId = provinceId
|
||||
)
|
||||
.get
|
||||
|
||||
inside(command) {
|
||||
case RecruitHeroesAvailable(availableHeroes, _) =>
|
||||
availableHeroes should have size 1
|
||||
availableHeroes.head.heroId shouldBe 11
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+78
@@ -943,4 +943,82 @@ class ProvinceViewFilterTest extends AnyFlatSpec with BeforeAndAfterEach with Ma
|
||||
uhs.map(_.heroId) should contain theSameElementsAs Vector(6)
|
||||
}
|
||||
}
|
||||
|
||||
it should "show WouldNeverJoin status for heroes who would never join viewing faction" in {
|
||||
val viewingFactionId = 11
|
||||
val province = ProvinceC(
|
||||
id = 5,
|
||||
rulingFactionId = Some(viewingFactionId),
|
||||
unaffiliatedHeroes = Vector(
|
||||
UnaffiliatedHeroC(
|
||||
heroId = 1,
|
||||
unaffiliatedHeroType = UnaffiliatedHeroType.Resident,
|
||||
recruitmentInfo = RecruitmentInfo.WouldJoin
|
||||
),
|
||||
UnaffiliatedHeroC(
|
||||
heroId = 2,
|
||||
unaffiliatedHeroType = UnaffiliatedHeroType.Resident,
|
||||
recruitmentInfo = RecruitmentInfo.NotDivined
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val heroes = Map(
|
||||
1 -> HeroC(id = 1, nameTextId = "hn_1", neverJoinFactionIds = Set(viewingFactionId)),
|
||||
2 -> HeroC(id = 2, nameTextId = "hn_2", neverJoinFactionIds = Set(viewingFactionId))
|
||||
)
|
||||
|
||||
val gs = minimalGameState(provinces = Map(5 -> province), heroes = heroes)
|
||||
|
||||
val filtered = filteredProvinceView(province, gs, viewingFactionId)
|
||||
|
||||
inside(filtered.fullInfo.get.unaffiliatedHeroes) {
|
||||
case uhs: Vector[UnaffiliatedHeroBasics] =>
|
||||
uhs should have size 2
|
||||
// Both heroes should show WouldNeverJoin, overriding their underlying status
|
||||
uhs.foreach(_.recruitmentInfo shouldBe RecruitmentInfo.WouldNeverJoin)
|
||||
}
|
||||
}
|
||||
|
||||
it should "not override status to WouldNeverJoin for heroes who can join viewing faction" in {
|
||||
val viewingFactionId = 11
|
||||
val otherFactionId = 99
|
||||
val province = ProvinceC(
|
||||
id = 5,
|
||||
rulingFactionId = Some(viewingFactionId),
|
||||
unaffiliatedHeroes = Vector(
|
||||
UnaffiliatedHeroC(
|
||||
heroId = 1,
|
||||
unaffiliatedHeroType = UnaffiliatedHeroType.Resident,
|
||||
recruitmentInfo = RecruitmentInfo.WouldJoin
|
||||
),
|
||||
UnaffiliatedHeroC(
|
||||
heroId = 2,
|
||||
unaffiliatedHeroType = UnaffiliatedHeroType.Resident,
|
||||
recruitmentInfo = RecruitmentInfo.NotDivined
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val heroes = Map(
|
||||
// Hero 1 would never join a different faction, not the viewing faction
|
||||
1 -> HeroC(id = 1, nameTextId = "hn_1", neverJoinFactionIds = Set(otherFactionId)),
|
||||
// Hero 2 has no restrictions
|
||||
2 -> HeroC(id = 2, nameTextId = "hn_2")
|
||||
)
|
||||
|
||||
val gs = minimalGameState(provinces = Map(5 -> province), heroes = heroes)
|
||||
|
||||
val filtered = filteredProvinceView(province, gs, viewingFactionId)
|
||||
|
||||
inside(filtered.fullInfo.get.unaffiliatedHeroes) {
|
||||
case uhs: Vector[UnaffiliatedHeroBasics] =>
|
||||
uhs should have size 2
|
||||
val hero1 = uhs.find(_.heroId == 1).get
|
||||
val hero2 = uhs.find(_.heroId == 2).get
|
||||
// These should keep their original status since viewing faction is not in neverJoinFactionIds
|
||||
hero1.recruitmentInfo shouldBe RecruitmentInfo.WouldJoin
|
||||
hero2.recruitmentInfo shouldBe RecruitmentInfo.NotDivined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user