Skip to content

Commit

Permalink
Rework forts
Browse files Browse the repository at this point in the history
- Work on #52
- Update some German unit links/locks
- Change chit style
- Anzio, St. Gloriana, and Saunders scenarios
  • Loading branch information
layagyasz committed Jun 15, 2018
1 parent cba4e2a commit bdcaddf
Show file tree
Hide file tree
Showing 22 changed files with 486 additions and 56 deletions.
3 changes: 2 additions & 1 deletion Controller/ArmyBuilder/ArmyBuilderStateController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ void HandleFinished(object Sender, EventArgs E)
if (builder.Armies.All(i => i.Validate()))
transition = new ProgramStateTransitionEventArgs(
ProgramState.MATCH,
new MatchContext(new Match(builder.BuildScenario(), new FullOrderAutomater())));
new MatchContext(
new Match(builder.BuildScenario().MakeStatic(new Random()), new FullOrderAutomater())));
else transition = new ProgramStateTransitionEventArgs(ProgramState.BUILD_ARMY, _Context);
OnProgramStateTransition(this, transition);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System;

using Cardamom.Interface;
using Cardamom.Utilities;

Expand All @@ -24,7 +26,8 @@ void HandleStartScenario(object Sender, ValuedEventArgs<Scenario> E)
{
OnProgramStateTransition(
this, new ProgramStateTransitionEventArgs(
ProgramState.MATCH, new MatchContext(new Match(E.Value, new FullOrderAutomater()))));
ProgramState.MATCH,
new MatchContext(new Match(E.Value.MakeStatic(new Random()), new FullOrderAutomater()))));
}
}
}
3 changes: 1 addition & 2 deletions Model/Orders/Attack/DirectFireAttackOrder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ public override bool MatchesTurnComponent(TurnComponent TurnComponent)

public override OrderInvalidReason Validate()
{
if (Target != AttackTarget.ALL && (TargetTile.Rules.MustAttackAllUnits
|| TargetTile.Units.Any(i => i.Configuration.UnitClass == UnitClass.FORT)))
if (Target != AttackTarget.ALL && TargetTile.Rules.MustAttackAllUnits)
return OrderInvalidReason.MUST_ATTACK_ALL;

if (Target == AttackTarget.EACH)
Expand Down
14 changes: 2 additions & 12 deletions Model/Orders/Attack/OddsCalculation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,8 @@ public OddsCalculation(
StackArmored = Defenders.Any(i => i.Configuration.UnitClass == UnitClass.FORT)
|| Tile.Rules.TreatUnitsAsArmored
|| TreatStackAsArmored(AttackOrders, Defenders);
// If there is a fort, only use its defense.
Unit fort = null;
if (AttackMethod != AttackMethod.ANTI_AIRCRAFT)
fort = Defenders.First().Position.Units.FirstOrDefault(
i => i.Configuration.UnitClass == UnitClass.FORT && i.Army == Defenders.First().Army);
if (fort != null)
{
TotalDefense = fort.Configuration.Defense;
StackArmored = fort.Configuration.IsArmored;
OddsCalculationFactors.Add(OddsCalculationFactor.FORT);
}
else TotalDefense = Defenders.Sum(i => i.Configuration.Defense);

TotalDefense = Defenders.Sum(i => i.Configuration.Defense);
foreach (SingleAttackOrder a in AttackOrders) a.TreatStackAsArmored = StackArmored;
AttackFactorCalculations = AttackOrders.Select(
i => new Tuple<SingleAttackOrder, AttackFactorCalculation>(
Expand Down
1 change: 0 additions & 1 deletion Model/Orders/Attack/OddsCalculationFactor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ public enum OddsCalculationFactor
OVERRUN,
ARMORED_STACK,
UNARMORED_STACK,
FORT,
DISRUPTED,
}
}
1 change: 1 addition & 0 deletions Model/Orders/OrderInvalidReason.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public enum OrderInvalidReason
TARGET_COVERED,
TARGET_NOT_EMPLACEABLE,
TARGET_INTERACTION_LIMIT,
TARGET_TOO_CLOSE,

OVERRUN_TERRAIN,
OVERRUN_FORT,
Expand Down
3 changes: 1 addition & 2 deletions Model/ScenarioBuilder/ScenarioBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ public Scenario BuildScenario()
Parameters.FogOfWar,
Parameters.Setting.Environment,
new RandomMapConfiguration(
Parameters.MapSize.X, Parameters.MapSize.Y, Parameters.Setting)
.MakeStatic(new Random()));
Parameters.MapSize.X, Parameters.MapSize.Y, Parameters.Setting));
}
}
}
43 changes: 32 additions & 11 deletions Model/Sight/LazySightFinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ void HandleFire(object Sender, EventArgs E)
Unit unit = (Unit)Sender;
if (unit.Army == TrackingArmy) return;

SightFiringUnit(unit);

IEnumerable<Unit> otherUnits = SightFiringUnit(unit);
var delta = UnitTracker.Update(this, unit);
foreach (var otherUnit in otherUnits) delta.AddRange(UnitTracker.Update(this, otherUnit));
if (OnSightUpdated != null)
{
OnSightUpdated(
Expand Down Expand Up @@ -93,8 +93,11 @@ void HandleMove(object Sender, MovementEventArgs E)
}
else
{
SightMovingUnit(unit, E.Path != null && E.Path.Count > 1 ? E.Path[E.Path.Count - 2] : null, E.Tile);
IEnumerable<Unit> otherUnits =
SightMovingUnit(unit, E.Path != null && E.Path.Count > 1 ? E.Path[E.Path.Count - 2] : null, E.Tile);
var delta = UnitTracker.ComputeDelta(this, unit, E);
foreach (var otherUnit in otherUnits) delta.AddRange(UnitTracker.Update(this, otherUnit));

if (OnSightUpdated != null)
{
OnSightUpdated(
Expand Down Expand Up @@ -135,12 +138,12 @@ void HandleLoad(object Sender, EventArgs E)
if (carrierOverride && !passengerOverride)
{
_OverrideVisibleUnits.Add(unit.Passenger);
unitDeltas.AddRange(UnitTracker.ComputeDelta(this, unit.Passenger, null));
unitDeltas.AddRange(UnitTracker.Update(this, unit.Passenger));
}
else if (!carrierOverride && passengerOverride)
{
_OverrideVisibleUnits.Add(unit);
unitDeltas.AddRange(UnitTracker.ComputeDelta(this, unit, null));
unitDeltas.AddRange(UnitTracker.Update(this, unit));
}

if (OnSightUpdated != null)
Expand Down Expand Up @@ -297,20 +300,38 @@ public bool IsSighted(Unit Unit)
return _OverrideVisibleUnits.Contains(Unit) || IsSighted(Unit, Unit.Position);
}

void SightFiringUnit(Unit Unit)
IEnumerable<Unit> SightFiringUnit(Unit Unit)
{
if (Unit.Army == TrackingArmy || Unit.Position == null || IsSighted(Unit)) return;
var units = new List<Unit>();
if (Unit.Army == TrackingArmy || Unit.Position == null || IsSighted(Unit)) return units;

if (Unit.Position != null && HasTileSightLevel(Unit.Position, TileSightLevel.SIGHTED))
{
_OverrideVisibleUnits.Add(Unit);
else _OverrideVisibleUnits.Remove(Unit);
foreach (var unit in Unit.Position.Units.Where(i => i.Covers(Unit) || Unit.Covers(i)))
{
_OverrideVisibleUnits.Add(Unit);
units.Add(unit);
}
}
return units;
}

void SightMovingUnit(Unit Unit, Tile MovedFrom, Tile MovedTo)
IEnumerable<Unit> SightMovingUnit(Unit Unit, Tile MovedFrom, Tile MovedTo)
{
if (Unit.Army == TrackingArmy || !MovedTo.Rules.Concealing) return;
if (IsSighted(Unit, MovedFrom)) _OverrideVisibleUnits.Add(Unit);
var units = new List<Unit>();
if (Unit.Army == TrackingArmy || !MovedTo.Rules.Concealing) return units;
if (IsSighted(Unit, MovedFrom))
{
_OverrideVisibleUnits.Add(Unit);
foreach (var unit in Unit.Position.Units.Where(i => i.Covers(Unit) || Unit.Covers(i)))
{
_OverrideVisibleUnits.Add(Unit);
units.Add(unit);
}
}
else _OverrideVisibleUnits.Remove(Unit);
return units;
}

void HandleDeltas(IEnumerable<Tuple<Tile, TileSightLevel>> Deltas)
Expand Down
18 changes: 9 additions & 9 deletions Model/Unit/Unit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,20 +112,17 @@ public OrderInvalidReason CanBeAttackedBy(Army Army, AttackMethod AttackMethod,
i => i != this && i.CanBeAttackedBy(Army, AttackMethod) == OrderInvalidReason.NONE))
return OrderInvalidReason.TARGET_COVERED;
}
if (Configuration.UnitClass == UnitClass.FORT)
{
if (Position.Units.Any(
i => i != this
&& i.Army == this.Army
&& i.CanBeAttackedBy(Army, AttackMethod) == OrderInvalidReason.NONE))
return OrderInvalidReason.NONE;
}
if (!IgnoreConcealment && !Army.SightFinder.IsSighted(this))
return OrderInvalidReason.TARGET_CONCEALED;
if (Carrier != null) return OrderInvalidReason.UNIT_NO_ACTION;
if (Carrier != null || Position.Units.Any(i => i.Covers(this))) return OrderInvalidReason.TARGET_COVERED;
return OrderInvalidReason.NONE;
}

public bool Covers(Unit Unit)
{
return this != Unit && Army == Unit.Army && Configuration.Covers(Unit.Configuration);
}

public bool CanExitDirection(Direction Direction)
{
if (Position == null) return false;
Expand Down Expand Up @@ -239,7 +236,10 @@ public void Capture(Army Army)

public void HandleCombatResult(CombatResult CombatResult, AttackMethod AttackMethod, Army AttackingArmy)
{
if (Position == null) return;
if (Passenger != null) Passenger.HandleCombatResult(CombatResult, AttackMethod, AttackingArmy);
foreach (var unit in Position.Units.Where(i => Covers(i)).ToList())
unit.HandleCombatResult(CombatResult, AttackMethod, AttackingArmy);
switch (CombatResult)
{
case CombatResult.MISS:
Expand Down
12 changes: 11 additions & 1 deletion Model/Unit/UnitConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,10 @@ public OrderInvalidReason CanDirectFireAt(bool EnemyArmored, LineOfSight LineOfS

public OrderInvalidReason CanIndirectFireAt(LineOfSight LineOfSight, bool UseSecondaryWeapon)
{
if (LineOfSight.Range > GetAdjustedRange(UseSecondaryWeapon)) return OrderInvalidReason.TARGET_OUT_OF_RANGE;
byte range = GetAdjustedRange(UseSecondaryWeapon);
if (LineOfSight.Range > range) return OrderInvalidReason.TARGET_OUT_OF_RANGE;
if (UnitClass != UnitClass.TOWED_GUN && LineOfSight.Range <= range / 2)
return OrderInvalidReason.TARGET_TOO_CLOSE;
if (!CanIndirectFire) return OrderInvalidReason.UNIT_NO_ATTACK;
return OrderInvalidReason.NONE;
}
Expand Down Expand Up @@ -490,6 +493,13 @@ public int GetRange(AttackMethod AttackMethod, bool UseSecondaryWeapon)
return 0;
}

public bool Covers(UnitConfiguration Configuration)
{
return UnitClass == UnitClass.FORT
&& Configuration.UnitClass != UnitClass.FIGHTER_BOMBER
&& Defense > Configuration.Defense;
}

public float GetMaxMovement(Environment Environment)
{
if (HasUnlimitedMovement()) return float.MaxValue;
Expand Down
10 changes: 7 additions & 3 deletions Modules/Default/Scenarios/Default/Scenario_00.blk
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
string:name { Test A }
unit-count[]:unit-counts {
unit-count:_ {
!unit-configuration:unit-configuration { unit-configurations.80mm-aa }
!unit-configuration:unit-configuration { unit-configurations.bishop }
int:count { 2 }
}
}
Expand Down Expand Up @@ -126,8 +126,12 @@
string:name { Test A }
unit-count[]:unit-counts {
unit-count:_ {
!unit-configuration:unit-configuration { unit-configurations.a6-m2 }
int:count { 2 }
!unit-configuration:unit-configuration { unit-configurations.fort-20 }
int:count { 1 }
}
unit-count:_ {
!unit-configuration:unit-configuration { unit-configurations.rifle-platoon-japanese-41 }
int:count { 1 }
}
}
}
Expand Down
135 changes: 135 additions & 0 deletions Modules/Default/Scenarios/GirlsUndPanzer/Anzio.blk
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
scenario:_ {
string:name { Anzio }
byte[]:deployment-order { 0 1 }
byte[]:turn-order { 0 1 }
byte:turns { 16 }
bool:fog-of-war { true }
!environment:environment { environments.summer-grassland }
random-map-configuration:map-configuration {
int:width { 31 }
int:height { 33 }
!match-setting:match-setting { match-settings.italy-summer }
}
army-configuration[]:army-configurations {
army-configuration:ooarai {
!faction:faction { factions.japanese }
byte:team { 1 }
victory-condition:victory-condition {
var<>:objectives {
temporal-objective:flag-tank-destroyed {
trigger-objective:objective {
int:threshold { 1 }
units-matched-objective:objective {
bool:friendly { false }
unit-matches-all:matcher {
unit-has-status:_ {
unit-status:status { destroyed }
}
unit-has-configuration:_ {
!unit-configuration:unit-configuration { unit-configurations.pesante-40 }
}
}
}
}
}
}
objective-success-trigger[]:triggers {
objective-success-trigger:_ {
objective-success-level:success-level { victory }
int:threshold { 16 }
bool:invert { true }
!var:objective { objectives.flag-tank-destroyed }
}
}
}
var[]:deployment-configurations {
convoy-deployment-configuration:_ {
tile-on-edge:matcher {
direction:edge { west }
}
unit-group:unit-group {
string:name { Ooarai }
unit-count[]:unit-counts {
unit-count:_ {
!unit-configuration:unit-configuration { unit-configurations.pzkw-iv-d }
int:count { 1 }
}
unit-count:_ {
!unit-configuration:unit-configuration { unit-configurations.stug-iii-g }
int:count { 1 }
}
unit-count:_ {
!unit-configuration:unit-configuration { unit-configurations.pzkw-38_t }
int:count { 1 }
}
unit-count:_ {
!unit-configuration:unit-configuration { unit-configurations.m-3-lee }
int:count { 1 }
}
unit-count:_ {
!unit-configuration:unit-configuration { unit-configurations.otsu }
int:count { 1 }
}
}
}
}
}
}
army-configuration:anzio {
!faction:faction { factions.italian }
byte:team { 2 }
victory-condition:victory-condition {
var<>:objectives {
temporal-objective:flag-tank-destroyed {
trigger-objective:objective {
int:threshold { 1 }
units-matched-objective:objective {
bool:friendly { false }
unit-matches-all:matcher {
unit-has-status:_ {
unit-status:status { destroyed }
}
unit-has-configuration:_ {
!unit-configuration:unit-configuration { unit-configurations.pzkw-38_t }
}
}
}
}
}
}
objective-success-trigger[]:triggers {
objective-success-trigger:_ {
objective-success-level:success-level { victory }
int:threshold { 16 }
bool:invert { true }
!var:objective { objectives.flag-tank-destroyed }
}
}
}
var[]:deployment-configurations {
convoy-deployment-configuration:_ {
tile-on-edge:matcher {
direction:edge { east }
}
unit-group:unit-group {
string:name { Anzio }
unit-count[]:unit-counts {
unit-count:_ {
!unit-configuration:unit-configuration { unit-configurations.pesante-40 }
int:count { 1 }
}
unit-count:_ {
!unit-configuration:unit-configuration { unit-configurations.semovente-75_18 }
int:count { 3 }
}
unit-count:_ {
!unit-configuration:unit-configuration { unit-configurations.leggero-3 }
int:count { 6 }
}
}
}
}
}
}
}
}
Loading

0 comments on commit bdcaddf

Please sign in to comment.