Skip to content

Commit

Permalink
Add 2022 General's Handbook (#1528)
Browse files Browse the repository at this point in the history
* Add Gallet to realms, add basic rules

* Update core_battalions.ts

* Update grand_strategies.ts

* Remove Ghur

* Move battle tactics to realmscapes
  • Loading branch information
daviseford authored Jun 28, 2022
1 parent 3af4ac4 commit 215e4d4
Show file tree
Hide file tree
Showing 21 changed files with 313 additions and 1,804 deletions.
4 changes: 2 additions & 2 deletions src/components/info/banners/app_banner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useTheme } from 'context/useTheme'

const AppBanner = () => {
const { isDark } = useTheme()
const name = 'aos-3-idoneth-deepkin-fyreslayers-battletome-release'
const name = 'aos-3-ghb-2022-release'

return (
<NotificationBanner
Expand All @@ -14,7 +14,7 @@ const AppBanner = () => {
variant={isDark ? `info` : `info`}
>
<span>
<strong>NEW: </strong>The newly-released Idoneth Deepkin and Fyreslayers battletomes have been added!
<strong>NEW: </strong>General's Handbook (2022) has been added. Sylvaneth and Skaven are coming soon!
</span>
</NotificationBanner>
)
Expand Down
4 changes: 2 additions & 2 deletions src/components/input/army_builder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { CardMultiSelect, CardSingleSelect } from 'components/info/card'
import { armyActions, selectors } from 'ducks'
import { Fragment, useEffect, useMemo } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { TOriginRealms } from 'types/realmscapes'
import { RealmscapesEnum } from 'types/realmscapes'
import useGetArmy from 'utils/hooks/useGetArmy'
import useGetArmyBuilderCards from 'utils/hooks/useGetArmyBuilderCards'
import useWindowSize from 'utils/hooks/useWindowSize'
Expand Down Expand Up @@ -48,7 +48,7 @@ const ArmyBuilder = () => {
key={card.title}
label={factionName}
mobileTitle={card.mobileTitle || null}
setValue={withSelectOne(value => dispatch(card.setValue(value as TOriginRealms | null)))}
setValue={withSelectOne(value => dispatch(card.setValue(value as RealmscapesEnum | null)))}
title={card.title}
value={card.value}
selectionCount={0}
Expand Down
6 changes: 3 additions & 3 deletions src/components/routes/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { lazy, Suspense, useEffect } from 'react'
import { logPageView } from 'utils/analytics'

const AlliedArmies = lazy(() => import('components/input/ally_armies'))
// const AppBanner = lazy(() => import('components/info/banners/app_banner'))
const AppBanner = lazy(() => import('components/info/banners/app_banner'))
const ArmyBuilder = lazy(() => import('components/input/army_builder'))
const FooterComponent = lazy(() => import('components/page/footer'))
const LoadedArmyHeader = lazy(() => import('components/input/savedArmies/loaded_army_header'))
Expand All @@ -34,9 +34,9 @@ const Home = () => {
<div className={theme.bgColor}>
<Header />

{/* <Suspense fallback={<></>}>
<Suspense fallback={<></>}>
<AppBanner />
</Suspense> */}
</Suspense>

<Suspense fallback={<></>}>
<UpdateBanner />
Expand Down
10 changes: 5 additions & 5 deletions src/ducks/realmscape.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import DefaultAppState from 'store/initialAppState'
import { SUPPORTED_BATTLE_REALMS, TBattleRealms, TOriginRealms } from 'types/realmscapes'
import { RealmscapesEnum, SUPPORTED_REALMSCAPES } from 'types/realmscapes'

const getRealmscapeFromFeature = (feature: string): TBattleRealms | null => {
return SUPPORTED_BATTLE_REALMS.find(realm => feature.includes(realm)) || null
const getRealmscapeFromFeature = (feature: string): RealmscapesEnum | null => {
return SUPPORTED_REALMSCAPES.find(realm => feature.includes(realm)) || null
}

const realmscape = createSlice({
Expand All @@ -12,11 +12,11 @@ const realmscape = createSlice({
reducers: {
resetRealmscapeStore: () => DefaultAppState.realmscape,

setOriginRealm: (state, action: PayloadAction<TOriginRealms | null>) => {
setOriginRealm: (state, action: PayloadAction<RealmscapesEnum | null>) => {
state.origin_realm = action.payload
},

setRealmscape: (state, action: PayloadAction<TBattleRealms | null>) => {
setRealmscape: (state, action: PayloadAction<RealmscapesEnum | null>) => {
const realmscape = action.payload
let realmscape_feature = state.realmscape_feature
if (realmscape && realmscape_feature && !realmscape_feature.includes(realmscape)) {
Expand Down
27 changes: 27 additions & 0 deletions src/generic_rules/core_battalions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { TEntry } from 'types/data'
import {
CHARGE_PHASE,
COMBAT_PHASE,
DURING_GAME,
END_OF_CHARGE_PHASE,
END_OF_SETUP,
MOVEMENT_PHASE,
Expand Down Expand Up @@ -82,6 +83,8 @@ const CoreBattalions: TEntry[] = [
name: 'Command Entourage - Strategists',
effects: [StrategistsBattalionEffect],
},

// GHB 2021 Battalions
{
name: 'Alpha-Beast Pack',
effects: [
Expand All @@ -104,6 +107,30 @@ const CoreBattalions: TEntry[] = [
},
],
},

// GHB 2022 Battalions
{
name: 'Expert Conquerors',
effects: [
{
name: `Dominant Force`,
desc: `GALLETIAN VETERANS units only. Each model in this battalion counts as 3 models for the purposes of contesting objectives.`,
when: [DURING_GAME],
rule_sources: [meta_rule_sources.GHB_2022],
},
],
},
{
name: 'Bounty Hunters',
effects: [
{
name: `Headhunters`,
desc: `If the target of an attack made with a melee weapon by a model in this battalion is a GALLETIAN VETERANS unit, add 1 to the Damage characteristic of that weapon for that attack.`,
when: [COMBAT_PHASE],
rule_sources: [meta_rule_sources.GHB_2022],
},
],
},
]

export default CoreBattalions
60 changes: 0 additions & 60 deletions src/generic_rules/core_rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,66 +367,6 @@ const CoreRules: TEntry[] = [
effects: [OneDropDeploymentEffect],
},

{
name: 'Battle Tactics',
effects: [
{
name: `Battle Tactics`,
desc: `At the start of your hero phase, you must pick 1 battle tactic. You must reveal your choice to your opponent, and if your battle tactics instructs you to pick something, you must tell your opponent what you pick. You have until the end of that turn to complete the battle tactic. You cannot pick the same battle tactic more than once per battle.`,
when: [START_OF_HERO_PHASE],
rule_sources: [meta_rule_sources.GHB_2021],
},
{
name: `Broken Ranks`,
desc: `When you reveal this battle tactic, pick 1 Battleline unit from your opponent's starting army on the battlefield. You complete this battle tactic if that unit is destroyed during this turn. If that unit was destroyed by an attack made by a friendly MONSTER or an ability of a friendly MONSTER, score 1 additional victory point.`,
when: [START_OF_HERO_PHASE],
rule_sources: [meta_rule_sources.GHB_2021],
},
{
name: `Conquer`,
desc: `When you reveal this battle tactic, pick 1 objective marker on the battlefield that your opponent controls. You complete this battle tactic if you control that objective marker at the end of this turn.`,
when: [START_OF_HERO_PHASE],
rule_sources: [meta_rule_sources.GHB_2021],
},
{
name: `Slay the Warlord`,
desc: `You complete this battle tactic if the model chosen to be your opponent's general is slain during this turn. If that model was destroyed by an attack made by a friendly MONSTER or an ability of a friendly MONSTER, score 1 additional victory point.`,
when: [START_OF_HERO_PHASE],
rule_sources: [meta_rule_sources.GHB_2021],
},
{
name: `Ferocious Advance`,
desc: `When you reveal this battle tactic, pick 3 different units from your starting army on the battlefield. You complete this battle tactic if all of the units your picked run in the following movement phase and finish that run within 3" of each other. If all 3 of those units are MONSTERS, score 1 additional victory point.`,
when: [START_OF_HERO_PHASE],
rule_sources: [meta_rule_sources.GHB_2021],
},
{
name: `Bring It Down!`,
desc: `When you reveal this battle tactic, pick 1 enemy MONSTER on the battlefield. You complete this battle tactic if that unit is destroyed during this turn. If that enemy MONSTER was destroyed by an attack made by a friendly MONSTER or an ability of a friendly MONSTER, score 1 additional victory point.`,
when: [START_OF_HERO_PHASE],
rule_sources: [meta_rule_sources.GHB_2021],
},
{
name: `Aggressive Expansion`,
desc: `When you reveal this battle tactic, pick 2 objective markers on the battlefield that are not wholly within your territory. You complete this battle tactic if you control both objective markers at the end of this turn.`,
when: [START_OF_HERO_PHASE],
rule_sources: [meta_rule_sources.GHB_2021],
},
{
name: `Monstrous Takeover`,
desc: `When you reveal this battle tactic, pick 1 MONSTER from your starting army on the battlefield. You complete this battle tactic if that MONSTER is contesting an objective marker that you control at the end of this turn, and that objective marker is not contested by an enemy MONSTER.`,
when: [START_OF_HERO_PHASE],
rule_sources: [meta_rule_sources.GHB_2021],
},
{
name: `Savage Spearhead`,
desc: `You complete this battle tactic if there are 2 or more units from your starting army wholly within your opponent's territory at the end of this turn. If 2 or more of those units are MONSTERS, score 1 additional victory point.`,
when: [START_OF_HERO_PHASE],
rule_sources: [meta_rule_sources.GHB_2021],
},
],
},

{
name: 'Wandering Endless Spells',
effects: [
Expand Down
70 changes: 69 additions & 1 deletion src/generic_rules/grand_strategies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import meta_rule_sources from 'meta/rule_sources'
import { TEntry } from 'types/data'
import { END_OF_GAME } from 'types/phases'

// General grand strategies available from GHB 2021
// General grand strategies
const GenericGrandStrategies: TEntry[] = [
{
name: `Sever the Head`,
Expand Down Expand Up @@ -92,6 +92,74 @@ const GenericGrandStrategies: TEntry[] = [
},
],
},

// GHB 2022 Grand Strategies
{
name: `No Place for the Weak`,
effects: [
{
name: `No Place for the Weak`,
desc: `When the battle ends, you complete this grand strategy if there are no Battleline units from your opponent's starting army on the battlefield.`,
when: [END_OF_GAME],
rule_sources: [meta_rule_sources.GHB_2022],
},
],
},
{
name: `Tame the Land`,
effects: [
{
name: `Tame the Land`,
desc: `When the battle ends, you complete this grand strategy if you control all of the objectives on the battlefield that are wholly outside your territory.`,
when: [END_OF_GAME],
rule_sources: [meta_rule_sources.GHB_2022],
},
],
},
{
name: `Defend What's Ours`,
effects: [
{
name: `Defend What's Ours`,
desc: `When the battle ends, you complete this grand strategy if there are no enemy units wholly within your territory.`,
when: [END_OF_GAME],
rule_sources: [meta_rule_sources.GHB_2022],
},
],
},
{
name: `Take What's Theirs`,
effects: [
{
name: `Take What's Theirs`,
desc: `When the battle ends, you complete this grand strategy if there are more friendly units than enemy units wholly within your opponent's territory.`,
when: [END_OF_GAME],
rule_sources: [meta_rule_sources.GHB_2022],
},
],
},
{
name: `Demonstration of Strength`,
effects: [
{
name: `Demonstration of Strength`,
desc: `When the battle ends, you complete this grand strategy if there are 3 or more GALLETIAN VETERANS units from your starting army on the battlefield.`,
when: [END_OF_GAME],
rule_sources: [meta_rule_sources.GHB_2022],
},
],
},
{
name: `Show of Dominance`,
effects: [
{
name: `Show of Dominance`,
desc: `When the battle ends, you complete this grand strategy if there are any friendly GALLETIAN VETERANS units in each quarter of the battlefield.`,
when: [END_OF_GAME],
rule_sources: [meta_rule_sources.GHB_2022],
},
],
},
]

export default GenericGrandStrategies
Loading

0 comments on commit 215e4d4

Please sign in to comment.