From d8b3451b63fe2ee51abbab9de40e0566f00737b7 Mon Sep 17 00:00:00 2001 From: Lesueur Benjamin Date: Thu, 19 Mar 2020 11:06:43 +0100 Subject: [PATCH 01/11] New Trait - Garrison Author: Devon Dieffenbach (darky) Credit: DnAp (https://github.com/DnAp) - Original PR: OpenRA/OpenRA#12774 --- OpenRA.Mods.RA2/Activities/EnterGarrison.cs | 191 ++++++ OpenRA.Mods.RA2/Activities/UnloadGarrison.cs | 150 +++++ OpenRA.Mods.RA2/OpenRA.Mods.RA2.csproj | 4 + .../Orders/EnterGarrisonOrderTargeter.cs | 54 ++ OpenRA.Mods.RA2/Traits/AttackGarrisonedRV.cs | 221 +++++++ OpenRA.Mods.RA2/Traits/ChangeOwner.cs | 29 + .../Traits/ChangeOwnerOnGarrisoner.cs | 67 +++ OpenRA.Mods.RA2/Traits/Garrisonable.cs | 563 ++++++++++++++++++ OpenRA.Mods.RA2/Traits/Garrisoner.cs | 227 +++++++ OpenRA.Mods.RA2/Traits/TraitsInterfaces.cs | 28 + mods/ra2/rules/allied-infantry.yaml | 2 + mods/ra2/rules/civilian-structures.yaml | 4 +- mods/ra2/rules/defaults.yaml | 18 + mods/ra2/rules/soviet-infantry.yaml | 6 + 14 files changed, 1562 insertions(+), 2 deletions(-) create mode 100644 OpenRA.Mods.RA2/Activities/EnterGarrison.cs create mode 100644 OpenRA.Mods.RA2/Activities/UnloadGarrison.cs create mode 100644 OpenRA.Mods.RA2/Orders/EnterGarrisonOrderTargeter.cs create mode 100644 OpenRA.Mods.RA2/Traits/AttackGarrisonedRV.cs create mode 100644 OpenRA.Mods.RA2/Traits/ChangeOwner.cs create mode 100644 OpenRA.Mods.RA2/Traits/ChangeOwnerOnGarrisoner.cs create mode 100644 OpenRA.Mods.RA2/Traits/Garrisonable.cs create mode 100644 OpenRA.Mods.RA2/Traits/Garrisoner.cs create mode 100644 OpenRA.Mods.RA2/Traits/TraitsInterfaces.cs diff --git a/OpenRA.Mods.RA2/Activities/EnterGarrison.cs b/OpenRA.Mods.RA2/Activities/EnterGarrison.cs new file mode 100644 index 000000000..2de56f784 --- /dev/null +++ b/OpenRA.Mods.RA2/Activities/EnterGarrison.cs @@ -0,0 +1,191 @@ +#region Copyright & License Information +/* + * Copyright 2007-2019 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System.Collections.Generic; +using System.Linq; +using OpenRA.Activities; +using OpenRA.Mods.Common; +using OpenRA.Mods.Common.Traits; +using OpenRA.Mods.RA2.Traits; +using OpenRA.Primitives; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA2.Activities +{ + class EnterGarrison : Activity + { + enum EnterState { Approaching, Entering, Exiting, Finished } + + readonly IMove move; + readonly Color? targetLineColor; + readonly Garrisoner garrisoner; + Target target; + Target lastVisibleTarget; + bool useLastVisibleTarget; + EnterState lastState = EnterState.Approaching; + + // EnterGarrison Properties + Actor enterActor; + Garrisonable enterGarrison; + Aircraft enterAircraft; + + public EnterGarrison(Actor self, Target target, Color? targetLineColor = null) + { + // Base - Enter Properties + move = self.Trait(); + this.target = target; + this.targetLineColor = targetLineColor; + + // EnterGarrison Properties + garrisoner = self.TraitsImplementing().Single(); + } + + protected bool TryStartEnter(Actor self, Actor targetActor) + { + enterActor = targetActor; + enterGarrison = targetActor.TraitOrDefault(); + enterAircraft = targetActor.TraitOrDefault(); + + // Make sure we can still enter the transport + // (but not before, because this may stop the actor in the middle of nowhere) + if (enterGarrison == null || enterGarrison.IsTraitDisabled || enterGarrison.IsTraitPaused || !garrisoner.Reserve(self, enterGarrison)) + { + Cancel(self, true); + return false; + } + + if (enterAircraft != null && !enterAircraft.AtLandAltitude) + return false; + + return true; + } + + protected void OnCancel(Actor self) { } + + protected void OnEnterComplete(Actor self, Actor targetActor) + { + self.World.AddFrameEndTask(w => + { + if (self.IsDead) + return; + + // Make sure the target hasn't changed while entering + // OnEnterComplete is only called if targetActor is alive + if (targetActor != enterActor) + return; + + if (!enterGarrison.CanLoad(enterActor, self)) + return; + + enterGarrison.Load(enterActor, self); + w.Remove(self); + }); + } + + // Base Enter Methods Below + public override bool Tick(Actor self) + { + // Update our view of the target + bool targetIsHiddenActor; + target = target.Recalculate(self.Owner, out targetIsHiddenActor); + + // Re-acquire the target after change owner has happened. + if (target.Type == TargetType.Invalid) + target = Target.FromActor(target.Actor); + + if (!targetIsHiddenActor && target.Type == TargetType.Actor) + lastVisibleTarget = Target.FromTargetPositions(target); + + var oldUseLastVisibleTarget = useLastVisibleTarget; + useLastVisibleTarget = targetIsHiddenActor || !target.IsValidFor(self); + + // Cancel immediately if the target died while we were entering it + if (!IsCanceling && useLastVisibleTarget && lastState == EnterState.Entering) + Cancel(self, true); + + // We need to wait for movement to finish before transitioning to + // the next state or next activity + if (!TickChild(self)) + return false; + + // Note that lastState refers to what we have just *finished* doing + switch (lastState) + { + case EnterState.Approaching: + { + // NOTE: We can safely cancel in this case because we know the + // actor has finished any in-progress move activities + if (IsCanceling) + return true; + + // Lost track of the target + if (useLastVisibleTarget && lastVisibleTarget.Type == TargetType.Invalid) + return true; + + // We are not next to the target - lets fix that + if (target.Type != TargetType.Invalid && !move.CanEnterTargetNow(self, target)) + { + // Target lines are managed by this trait, so we do not pass targetLineColor + var initialTargetPosition = (useLastVisibleTarget ? lastVisibleTarget : target).CenterPosition; + QueueChild(move.MoveToTarget(self, target, initialTargetPosition)); + return false; + } + + // We are next to where we thought the target should be, but it isn't here + // There's not much more we can do here + if (useLastVisibleTarget || target.Type != TargetType.Actor) + return true; + + // Are we ready to move into the target? + if (TryStartEnter(self, target.Actor)) + { + lastState = EnterState.Entering; + QueueChild(move.MoveIntoTarget(self, target)); + return false; + } + + // Subclasses can cancel the activity during TryStartEnter + // Return immediately to avoid an extra tick's delay + if (IsCanceling) + return true; + + return false; + } + + case EnterState.Entering: + { + // Check that we reached the requested position + var targetPos = target.Positions.PositionClosestTo(self.CenterPosition); + if (!IsCanceling && self.CenterPosition == targetPos && target.Type == TargetType.Actor) + OnEnterComplete(self, target.Actor); + + lastState = EnterState.Exiting; + return false; + } + + case EnterState.Exiting: + { + QueueChild(move.ReturnToCell(self)); + lastState = EnterState.Finished; + return false; + } + } + + return true; + } + + public override IEnumerable TargetLineNodes(Actor self) + { + if (targetLineColor != null) + yield return new TargetLineNode(useLastVisibleTarget ? lastVisibleTarget : target, targetLineColor.Value); + } + } +} diff --git a/OpenRA.Mods.RA2/Activities/UnloadGarrison.cs b/OpenRA.Mods.RA2/Activities/UnloadGarrison.cs new file mode 100644 index 000000000..bcb279a8c --- /dev/null +++ b/OpenRA.Mods.RA2/Activities/UnloadGarrison.cs @@ -0,0 +1,150 @@ +#region Copyright & License Information +/* + * Copyright 2007-2018 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System.Collections.Generic; +using System.Linq; +using OpenRA.Activities; +using OpenRA.Mods.Common; +using OpenRA.Mods.Common.Activities; +using OpenRA.Mods.Common.Traits; +using OpenRA.Mods.RA2.Traits; +using OpenRA.Primitives; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA2.Activities +{ + public class UnloadGarrison : Activity + { + readonly Actor self; + readonly Garrisonable garrison; + readonly INotifyUnload[] notifiers; + readonly bool unloadAll; + readonly Aircraft aircraft; + readonly Mobile mobile; + readonly bool assignTargetOnFirstRun; + readonly WDist unloadRange; + + Target destination; + bool takeOffAfterUnload; + + public UnloadGarrison(Actor self, WDist unloadRange, bool unloadAll = true) + : this(self, Target.Invalid, unloadRange, unloadAll) + { + assignTargetOnFirstRun = true; + } + + public UnloadGarrison(Actor self, Target destination, WDist unloadRange, bool unloadAll = true) + { + this.self = self; + garrison = self.Trait(); + notifiers = self.TraitsImplementing().ToArray(); + this.unloadAll = unloadAll; + aircraft = self.TraitOrDefault(); + mobile = self.TraitOrDefault(); + this.destination = destination; + this.unloadRange = unloadRange; + } + + public Pair? ChooseExitSubCell(Actor passenger) + { + var pos = passenger.Trait(); + + return garrison.CurrentAdjacentCells + .Shuffle(self.World.SharedRandom) + .Select(c => Pair.New(c, pos.GetAvailableSubCell(c))) + .Cast?>() + .FirstOrDefault(s => s.Value.Second != SubCell.Invalid); + } + + IEnumerable BlockedExitCells(Actor passenger) + { + var pos = passenger.Trait(); + + // Find the cells that are blocked by transient actors + return garrison.CurrentAdjacentCells + .Where(c => pos.CanEnterCell(c, null, true) != pos.CanEnterCell(c, null, false)); + } + + protected override void OnFirstRun(Actor self) + { + if (assignTargetOnFirstRun) + destination = Target.FromCell(self.World, self.Location); + + // Move to the target destination + if (aircraft != null) + { + // Queue the activity even if already landed in case self.Location != destination + QueueChild(new Land(self, destination, unloadRange)); + takeOffAfterUnload = !aircraft.AtLandAltitude; + } + else if (mobile != null) + { + var cell = self.World.Map.Clamp(this.self.World.Map.CellContaining(destination.CenterPosition)); + QueueChild(new Move(self, cell, unloadRange)); + } + + QueueChild(new Wait(garrison.Info.BeforeUnloadDelay)); + } + + public override bool Tick(Actor self) + { + if (IsCanceling || garrison.IsEmpty(self)) + return true; + + if (garrison.CanUnload()) + { + foreach (var inu in notifiers) + inu.Unloading(self); + + var actor = garrison.Peek(self); + var spawn = self.CenterPosition; + + var exitSubCell = ChooseExitSubCell(actor); + if (exitSubCell == null) + { + self.NotifyBlocker(BlockedExitCells(actor)); + + Queue(new Wait(10)); + return false; + } + + garrison.Unload(self); + self.World.AddFrameEndTask(w => + { + if (actor.Disposed) + return; + + var move = actor.Trait(); + var pos = actor.Trait(); + + pos.SetPosition(actor, exitSubCell.Value.First, exitSubCell.Value.Second); + pos.SetVisualPosition(actor, spawn); + + actor.CancelActivity(); + w.Add(actor); + }); + } + + if (!unloadAll || !garrison.CanUnload()) + { + if (garrison.Info.AfterUnloadDelay > 0) + QueueChild(new Wait(garrison.Info.AfterUnloadDelay, false)); + + if (takeOffAfterUnload) + QueueChild(new TakeOff(self)); + + return true; + } + + return false; + } + } +} diff --git a/OpenRA.Mods.RA2/OpenRA.Mods.RA2.csproj b/OpenRA.Mods.RA2/OpenRA.Mods.RA2.csproj index e6e77986a..c64d1b085 100644 --- a/OpenRA.Mods.RA2/OpenRA.Mods.RA2.csproj +++ b/OpenRA.Mods.RA2/OpenRA.Mods.RA2.csproj @@ -23,6 +23,10 @@ + + ../engine/thirdparty/download/Eluant.dll + False + diff --git a/OpenRA.Mods.RA2/Orders/EnterGarrisonOrderTargeter.cs b/OpenRA.Mods.RA2/Orders/EnterGarrisonOrderTargeter.cs new file mode 100644 index 000000000..373e90458 --- /dev/null +++ b/OpenRA.Mods.RA2/Orders/EnterGarrisonOrderTargeter.cs @@ -0,0 +1,54 @@ +#region Copyright & License Information +/* + * Copyright 2007-2018 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System; +using OpenRA.Mods.Common.Orders; +using OpenRA.Mods.Common.Traits; +using OpenRA.Mods.RA2.Traits; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA2.Orders +{ + public class EnterGarrisonOrderTargeter : UnitOrderTargeter where GarrisonableInfo : ITraitInfo + { + readonly Func canTarget; + readonly Func useEnterCursor; + GarrisonerInfo garrisonerInfo; + + public EnterGarrisonOrderTargeter(string order, int priority, + Func canTarget, Func useEnterCursor, GarrisonerInfo garrisonerInfo) + : base(order, priority, "enter", true, true) + { + this.canTarget = canTarget; + this.useEnterCursor = useEnterCursor; + this.garrisonerInfo = garrisonerInfo; + } + + public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) + { + if (garrisonerInfo.TargetStances.HasStance(self.Owner.Stances[target.Owner]) && target.Info.HasTraitInfo() && canTarget(target, modifiers)) + { + cursor = useEnterCursor(target) ? "enter" : "enter-blocked"; + return true; + } + else + return false; + } + + public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor) + { + if (target.Info.HasTraitInfo()) + return true; + + return false; + } + } +} diff --git a/OpenRA.Mods.RA2/Traits/AttackGarrisonedRV.cs b/OpenRA.Mods.RA2/Traits/AttackGarrisonedRV.cs new file mode 100644 index 000000000..e530e0022 --- /dev/null +++ b/OpenRA.Mods.RA2/Traits/AttackGarrisonedRV.cs @@ -0,0 +1,221 @@ +#region Copyright & License Information +/* + * Copyright 2007-2018 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using OpenRA.Graphics; +using OpenRA.Mods.Common; +using OpenRA.Mods.Common.Traits; +using OpenRA.Mods.Common.Traits.Render; +using OpenRA.Primitives; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA2.Traits +{ + public class FirePort + { + public WVec Offset; + public WAngle Yaw; + public WAngle Cone; + } + + [Desc("Garrisoners can fire their weapons out of fire ports.")] + public class AttackGarrisonedRVInfo : AttackFollowInfo, IRulesetLoaded, Requires + { + [FieldLoader.Require] + [Desc("Fire port offsets in local coordinates.")] + public readonly WVec[] PortOffsets = null; + + [FieldLoader.Require] + [Desc("Fire port yaw angles.")] + public readonly WAngle[] PortYaws = null; + + [FieldLoader.Require] + [Desc("Fire port yaw cone angle.")] + public readonly WAngle[] PortCones = null; + + public FirePort[] Ports { get; private set; } + + [PaletteReference] + public readonly string MuzzlePalette = "effect"; + + public override object Create(ActorInitializer init) { return new AttackGarrisonedRV(init.Self, this); } + public override void RulesetLoaded(Ruleset rules, ActorInfo ai) + { + if (PortOffsets.Length == 0) + throw new YamlException("PortOffsets must have at least one entry."); + + if (PortYaws.Length != PortOffsets.Length) + throw new YamlException("PortYaws must define an angle for each port."); + + if (PortCones.Length != PortOffsets.Length) + throw new YamlException("PortCones must define an angle for each port."); + + Ports = new FirePort[PortOffsets.Length]; + + for (var i = 0; i < PortOffsets.Length; i++) + { + Ports[i] = new FirePort + { + Offset = PortOffsets[i], + Yaw = PortYaws[i], + Cone = PortCones[i], + }; + } + + base.RulesetLoaded(rules, ai); + } + } + + public class AttackGarrisonedRV : AttackFollow, INotifyGarrisonerEntered, INotifyGarrisonerExited, IRender + { + public readonly new AttackGarrisonedRVInfo Info; + Lazy coords; + List armaments; + List muzzles; + Dictionary paxFacing; + Dictionary paxPos; + Dictionary paxRender; + + public AttackGarrisonedRV(Actor self, AttackGarrisonedRVInfo info) + : base(self, info) + { + Info = info; + coords = Exts.Lazy(() => self.Trait()); + armaments = new List(); + muzzles = new List(); + paxFacing = new Dictionary(); + paxPos = new Dictionary(); + paxRender = new Dictionary(); + } + + protected override Func> InitializeGetArmaments(Actor self) + { + return () => armaments; + } + + void INotifyGarrisonerEntered.OnGarrisonerEntered(Actor self, Actor garrisoner) + { + paxFacing.Add(garrisoner, garrisoner.Trait()); + paxPos.Add(garrisoner, garrisoner.Trait()); + paxRender.Add(garrisoner, garrisoner.Trait()); + armaments.AddRange( + garrisoner.TraitsImplementing() + .Where(a => Info.Armaments.Contains(a.Info.Name))); + } + + void INotifyGarrisonerExited.OnGarrisonerExited(Actor self, Actor garrisoner) + { + paxFacing.Remove(garrisoner); + paxPos.Remove(garrisoner); + paxRender.Remove(garrisoner); + armaments.RemoveAll(a => a.Actor == garrisoner); + } + + FirePort SelectFirePort(Actor self, WAngle targetYaw) + { + // Pick a random port that faces the target + var bodyYaw = facing != null ? WAngle.FromFacing(facing.Facing) : WAngle.Zero; + var indices = Enumerable.Range(0, Info.Ports.Length).Shuffle(self.World.SharedRandom); + foreach (var i in indices) + { + var yaw = bodyYaw + Info.Ports[i].Yaw; + var leftTurn = (yaw - targetYaw).Angle; + var rightTurn = (targetYaw - yaw).Angle; + if (Math.Min(leftTurn, rightTurn) <= Info.Ports[i].Cone.Angle) + return Info.Ports[i]; + } + + return null; + } + + WVec PortOffset(Actor self, FirePort p) + { + var bodyOrientation = coords.Value.QuantizeOrientation(self, self.Orientation); + return coords.Value.LocalToWorld(p.Offset.Rotate(bodyOrientation)); + } + + public override void DoAttack(Actor self, Target target) + { + if (!CanAttack(self, target)) + return; + + var pos = self.CenterPosition; + var targetedPosition = GetTargetPosition(pos, target); + var targetYaw = (targetedPosition - pos).Yaw; + + foreach (var a in Armaments) + { + if (a.IsTraitDisabled) + continue; + + var port = SelectFirePort(self, targetYaw); + if (port == null) + return; + + var muzzleFacing = targetYaw.Angle / 4; + paxFacing[a.Actor].Facing = muzzleFacing; + paxPos[a.Actor].SetVisualPosition(a.Actor, pos + PortOffset(self, port)); + + var barrel = a.CheckFire(a.Actor, facing, target); + if (barrel == null) + continue; + + if (a.Info.MuzzleSequence != null) + { + // Muzzle facing is fixed once the firing starts + var muzzleAnim = new Animation(self.World, paxRender[a.Actor].GetImage(a.Actor), () => muzzleFacing); + var sequence = a.Info.MuzzleSequence; + + if (a.Info.MuzzleSplitFacings > 0) + sequence += OpenRA.Mods.Common.Util.QuantizeFacing(muzzleFacing, a.Info.MuzzleSplitFacings).ToString(); + + var muzzleFlash = new AnimationWithOffset(muzzleAnim, + () => PortOffset(self, port), + () => false, + p => RenderUtils.ZOffsetFromCenter(self, p, 1024)); + + muzzles.Add(muzzleFlash); + muzzleAnim.PlayThen(sequence, () => muzzles.Remove(muzzleFlash)); + } + + foreach (var npa in self.TraitsImplementing()) + npa.Attacking(self, target, a, barrel); + } + } + + IEnumerable IRender.Render(Actor self, WorldRenderer wr) + { + var pal = wr.Palette(Info.MuzzlePalette); + + // Display muzzle flashes + foreach (var m in muzzles) + foreach (var r in m.Render(self, wr, pal, 1f)) + yield return r; + } + + IEnumerable IRender.ScreenBounds(Actor self, WorldRenderer wr) + { + // Muzzle flashes don't contribute to actor bounds + yield break; + } + + protected override void Tick(Actor self) + { + base.Tick(self); + + // Take a copy so that Tick() can remove animations + foreach (var m in muzzles.ToArray()) + m.Animation.Tick(); + } + } +} diff --git a/OpenRA.Mods.RA2/Traits/ChangeOwner.cs b/OpenRA.Mods.RA2/Traits/ChangeOwner.cs new file mode 100644 index 000000000..5d3873cbc --- /dev/null +++ b/OpenRA.Mods.RA2/Traits/ChangeOwner.cs @@ -0,0 +1,29 @@ +#region Copyright & License Information +/* + * Copyright 2007-2019 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using OpenRA.Traits; + +namespace OpenRA.Mods.RA2.Traits +{ + public abstract class ChangeOwnerInfo : ITraitInfo + { + public abstract object Create(ActorInitializer init); + } + + public abstract class ChangeOwner + { + protected void NeedChangeOwner(Actor self, Actor actor, Player newOwner) + { + var oldOwner = self.Owner; + self.ChangeOwner(newOwner); + } + } +} diff --git a/OpenRA.Mods.RA2/Traits/ChangeOwnerOnGarrisoner.cs b/OpenRA.Mods.RA2/Traits/ChangeOwnerOnGarrisoner.cs new file mode 100644 index 000000000..a44cf381f --- /dev/null +++ b/OpenRA.Mods.RA2/Traits/ChangeOwnerOnGarrisoner.cs @@ -0,0 +1,67 @@ +#region Copyright & License Information +/* + * Copyright 2007-2019 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using OpenRA.Traits; + +namespace OpenRA.Mods.RA2.Traits +{ + public class ChangeOwnerOnGarrisonerInfo : ChangeOwnerInfo, ITraitInfo, Requires + { + [Desc("Speech notification played when the first actor enters this garrison.")] + public readonly string EnterNotification = null; + + [Desc("Speech notification played when the last actor leaves this garrison.")] + public readonly string ExitNotification = null; + + [Desc("Sound played when the first actor enters this garrison.")] + public readonly string EnterSound = null; + + [Desc("Sound played when the last actor exits this garrison.")] + public readonly string ExitSound = null; + + public override object Create(ActorInitializer init) { return new ChangeOwnerOnGarrisoner(init.Self, this); } + } + + public class ChangeOwnerOnGarrisoner : ChangeOwner, INotifyGarrisonerEntered, INotifyGarrisonerExited + { + readonly ChangeOwnerOnGarrisonerInfo info; + readonly Garrisonable garrison; + private readonly Player originalOwner; + + public ChangeOwnerOnGarrisoner(Actor self, ChangeOwnerOnGarrisonerInfo info) + { + this.info = info; + garrison = self.Trait(); + originalOwner = self.Owner; + } + + void INotifyGarrisonerEntered.OnGarrisonerEntered(Actor self, Actor garrisoner) + { + var newOwner = garrisoner.Owner; + if (self.Owner != originalOwner || self.Owner == newOwner || self.Owner.IsAlliedWith(garrisoner.Owner)) + return; + + NeedChangeOwner(self, garrisoner, newOwner); + Game.Sound.Play(SoundType.World, info.EnterSound, self.CenterPosition); + Game.Sound.PlayNotification(self.World.Map.Rules, garrisoner.Owner, "Speech", info.EnterNotification, newOwner.Faction.InternalName); + } + + void INotifyGarrisonerExited.OnGarrisonerExited(Actor self, Actor garrisoner) + { + if (garrison.GarrisonerCount > 0) + return; + + Game.Sound.Play(SoundType.World, info.ExitSound, self.CenterPosition); + Game.Sound.PlayNotification(self.World.Map.Rules, garrisoner.Owner, "Speech", info.ExitNotification, garrisoner.Owner.Faction.InternalName); + NeedChangeOwner(self, garrisoner, originalOwner); + } + } +} diff --git a/OpenRA.Mods.RA2/Traits/Garrisonable.cs b/OpenRA.Mods.RA2/Traits/Garrisonable.cs new file mode 100644 index 000000000..459a19d34 --- /dev/null +++ b/OpenRA.Mods.RA2/Traits/Garrisonable.cs @@ -0,0 +1,563 @@ +#region Copyright & License Information +/* + * Copyright 2007-2018 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using OpenRA.Mods.Common; +using OpenRA.Mods.Common.Activities; +using OpenRA.Mods.Common.Orders; +using OpenRA.Mods.Common.Traits; +using OpenRA.Mods.Common.Widgets; +using OpenRA.Mods.RA2.Activities; +using OpenRA.Primitives; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA2.Traits +{ + [Desc("This actor can store Garrisoner actors.")] + public class GarrisonableInfo : PausableConditionalTraitInfo, ITraitInfo, Requires + { + [Desc("The maximum sum of Garrisoner.Weight that this actor can support.")] + public readonly int MaxWeight = 0; + + [Desc("Number of pips to display when this actor is selected.")] + public readonly int PipCount = 0; + + [Desc("`Garrisoner.GarrisonType`s that can be loaded into this actor.")] + public readonly HashSet Types = new HashSet(); + + [Desc("A list of actor types that are initially spawned into this actor.")] + public readonly string[] InitialUnits = { }; + + [Desc("When this actor is sold should all of its garrisoners be unloaded?")] + public readonly bool EjectOnSell = true; + + [Desc("When this actor dies should all of its garrisoners be unloaded?")] + public readonly bool EjectOnDeath = false; + + [Desc("Terrain types that this actor is allowed to eject actors onto. Leave empty for all terrain types.")] + public readonly HashSet UnloadTerrainTypes = new HashSet(); + + [VoiceReference] + [Desc("Voice to play when ordered to unload the garrisoners.")] + public readonly string UnloadVoice = "Action"; + + [Desc("Radius to search for a load/unload location if the ordered cell is blocked.")] + public readonly WDist LoadRange = WDist.FromCells(5); + + [Desc("Which direction the garrisoner will face (relative to the transport) when unloading.")] + public readonly int GarrisonerFacing = 128; + + [Desc("Delay (in ticks) before continuing after loading a passenger.")] + public readonly int AfterLoadDelay = 8; + + [Desc("Delay (in ticks) before unloading the first passenger.")] + public readonly int BeforeUnloadDelay = 8; + + [Desc("Delay (in ticks) before continuing after unloading a passenger.")] + public readonly int AfterUnloadDelay = 25; + + [Desc("Cursor to display when able to unload the garrisoners.")] + public readonly string UnloadCursor = "deploy"; + + [Desc("Cursor to display when unable to unload the garrisoners.")] + public readonly string UnloadBlockedCursor = "deploy-blocked"; + + [GrantedConditionReference] + [Desc("The condition to grant to self while waiting for garrisonable to load.")] + public readonly string LoadingCondition = null; + + [GrantedConditionReference] + [Desc("The condition to grant to self while garrisoners are loaded.", + "Condition can stack with multiple garrisoners.")] + public readonly string LoadedCondition = null; + + [Desc("Conditions to grant when specified actors are loaded inside the transport.", + "A dictionary of [actor id]: [condition].")] + public readonly Dictionary GarrisonerConditions = new Dictionary(); + + [GrantedConditionReference] + public IEnumerable LinterGarrisonerConditions { get { return GarrisonerConditions.Values; } } + + public override object Create(ActorInitializer init) { return new Garrisonable(init, this); } + } + + public class Garrisonable : PausableConditionalTrait, IPips, IIssueOrder, IResolveOrder, IOrderVoice, INotifyCreated, INotifyKilled, + INotifyOwnerChanged, INotifySold, INotifyActorDisposing, IIssueDeployOrder, + ITransformActorInitModifier + { + readonly Actor self; + readonly List garrisonable = new List(); + readonly HashSet reserves = new HashSet(); + readonly Dictionary> garrisonerTokens = new Dictionary>(); + readonly Lazy facing; + readonly bool checkTerrainType; + + int totalWeight = 0; + int reservedWeight = 0; + Aircraft aircraft; + ConditionManager conditionManager; + int loadingToken = ConditionManager.InvalidConditionToken; + Stack loadedTokens = new Stack(); + bool takeOffAfterLoad; + bool initialised; + + readonly CachedTransform> currentAdjacentCells; + public IEnumerable CurrentAdjacentCells + { + get { return currentAdjacentCells.Update(self.Location); } + } + + public IEnumerable Garrisoners { get { return garrisonable; } } + public int GarrisonerCount { get { return garrisonable.Count; } } + + enum State { Free, Locked } + State state = State.Free; + + public Garrisonable(ActorInitializer init, GarrisonableInfo info) + : base(info) + { + self = init.Self; + checkTerrainType = info.UnloadTerrainTypes.Count > 0; + + currentAdjacentCells = new CachedTransform>(loc => + { + return Util.AdjacentCells(self.World, Target.FromActor(self)).Where(c => loc != c); + }); + + if (init.Contains()) + { + garrisonable = new List(init.Get()); + totalWeight = garrisonable.Sum(c => GetWeight(c)); + } + else if (init.Contains()) + { + foreach (var u in init.Get()) + { + var unit = self.World.CreateActor(false, u.ToLowerInvariant(), + new TypeDictionary { new OwnerInit(self.Owner) }); + + garrisonable.Add(unit); + } + + totalWeight = garrisonable.Sum(c => GetWeight(c)); + } + else + { + foreach (var u in info.InitialUnits) + { + var unit = self.World.CreateActor(false, u.ToLowerInvariant(), + new TypeDictionary { new OwnerInit(self.Owner) }); + + garrisonable.Add(unit); + } + + totalWeight = garrisonable.Sum(c => GetWeight(c)); + } + + facing = Exts.Lazy(self.TraitOrDefault); + } + + void INotifyCreated.Created(Actor self) + { + aircraft = self.TraitOrDefault(); + conditionManager = self.TraitOrDefault(); + + if (conditionManager != null && garrisonable.Any()) + { + foreach (var c in garrisonable) + { + string garrisonerCondition; + if (Info.GarrisonerConditions.TryGetValue(c.Info.Name, out garrisonerCondition)) + garrisonerTokens.GetOrAdd(c.Info.Name).Push(conditionManager.GrantCondition(self, garrisonerCondition)); + } + + if (!string.IsNullOrEmpty(Info.LoadedCondition)) + loadedTokens.Push(conditionManager.GrantCondition(self, Info.LoadedCondition)); + } + + // Defer notifications until we are certain all traits on the transport are initialised + self.World.AddFrameEndTask(w => + { + foreach (var c in garrisonable) + { + c.Trait().Transport = self; + + foreach (var nec in c.TraitsImplementing()) + nec.OnEnteredGarrison(c, self); + + foreach (var npe in self.TraitsImplementing()) + npe.OnGarrisonerEntered(self, c); + } + + initialised = true; + }); + } + + static int GetWeight(Actor a) { return a.Info.TraitInfo().Weight; } + + public IEnumerable Orders + { + get + { + yield return new DeployOrderTargeter("Unload", 10, + () => CanUnload() ? Info.UnloadCursor : Info.UnloadBlockedCursor); + } + } + + public Order IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued) + { + if (order.OrderID == "Unload") + return new Order(order.OrderID, self, queued); + + return null; + } + + Order IIssueDeployOrder.IssueDeployOrder(Actor self, bool queued) + { + return new Order("Unload", self, queued); + } + + bool IIssueDeployOrder.CanIssueDeployOrder(Actor self) { return true; } + + public void ResolveOrder(Actor self, Order order) + { + if (order.OrderString == "Unload") + { + if (!order.Queued && !CanUnload()) + return; + + self.QueueActivity(new UnloadGarrison(self, Info.LoadRange)); + } + } + + public bool CanUnload(bool check = false) + { + if (checkTerrainType) + { + var terrainType = self.World.Map.GetTerrainInfo(self.Location).Type; + + if (!Info.UnloadTerrainTypes.Contains(terrainType)) + return false; + } + + return !IsEmpty(self) && (aircraft == null || aircraft.CanLand(self.Location, blockedByMobile: false)) + && CurrentAdjacentCells != null && CurrentAdjacentCells.Any(c => Garrisoners.Any(p => !p.IsDead && p.Trait().CanEnterCell(c, null, check))); + } + + public bool CanLoad(Actor self, Actor a) + { + return reserves.Contains(a) || HasSpace(GetWeight(a)); + } + + internal bool ReserveSpace(Actor a) + { + if (reserves.Contains(a)) + return true; + + var w = GetWeight(a); + if (!HasSpace(w)) + return false; + + if (conditionManager != null && loadingToken == ConditionManager.InvalidConditionToken && !string.IsNullOrEmpty(Info.LoadingCondition)) + loadingToken = conditionManager.GrantCondition(self, Info.LoadingCondition); + + reserves.Add(a); + reservedWeight += w; + LockForPickup(self); + + return true; + } + + internal void UnreserveSpace(Actor a) + { + if (!reserves.Contains(a) || self.IsDead) + return; + + reservedWeight -= GetWeight(a); + reserves.Remove(a); + ReleaseLock(self); + + if (loadingToken != ConditionManager.InvalidConditionToken) + loadingToken = conditionManager.RevokeCondition(self, loadingToken); + } + + // Prepare for transport pickup + void LockForPickup(Actor self) + { + if (state == State.Locked) + return; + + state = State.Locked; + + self.CancelActivity(); + + var air = self.TraitOrDefault(); + if (air != null && !air.AtLandAltitude) + { + takeOffAfterLoad = true; + self.QueueActivity(new Land(self)); + } + + self.QueueActivity(new WaitFor(() => state != State.Locked, false)); + } + + void ReleaseLock(Actor self) + { + if (reservedWeight != 0) + return; + + state = State.Free; + + self.QueueActivity(new Wait(Info.AfterLoadDelay, false)); + if (takeOffAfterLoad) + self.QueueActivity(new TakeOff(self)); + + takeOffAfterLoad = false; + } + + public string VoicePhraseForOrder(Actor self, Order order) + { + if (order.OrderString != "Unload" || IsEmpty(self) || !self.HasVoice(Info.UnloadVoice)) + return null; + + return Info.UnloadVoice; + } + + public bool HasSpace(int weight) { return totalWeight + reservedWeight + weight <= Info.MaxWeight; } + public bool IsEmpty(Actor self) { return garrisonable.Count == 0; } + + public Actor Peek(Actor self) { return garrisonable.Last(); } + + public Actor Unload(Actor self, Actor passenger = null) + { + passenger = passenger ?? garrisonable.Last(); + if (!garrisonable.Remove(passenger)) + throw new ArgumentException("Attempted to ungarrison an actor that is not a garrisoner."); + + totalWeight -= GetWeight(passenger); + + SetGarrisonerFacing(passenger); + + foreach (var npe in self.TraitsImplementing()) + npe.OnGarrisonerExited(self, passenger); + + foreach (var nec in passenger.TraitsImplementing()) + nec.OnExitedGarrison(passenger, self); + + var p = passenger.Trait(); + p.Transport = null; + + Stack garrisonerToken; + if (garrisonerTokens.TryGetValue(passenger.Info.Name, out garrisonerToken) && garrisonerToken.Any()) + conditionManager.RevokeCondition(self, garrisonerToken.Pop()); + + if (loadedTokens.Any()) + conditionManager.RevokeCondition(self, loadedTokens.Pop()); + + return passenger; + } + + void SetGarrisonerFacing(Actor garrisoner) + { + if (facing.Value == null) + return; + + var garrisonerFacing = garrisoner.TraitOrDefault(); + if (garrisonerFacing != null) + garrisonerFacing.Facing = facing.Value.Facing + Info.GarrisonerFacing; + + foreach (var t in garrisoner.TraitsImplementing()) + t.TurretFacing = facing.Value.Facing + Info.GarrisonerFacing; + } + + public int DamageVersus(Actor victim, Dictionary versus) + { + // If no Versus values are defined, DamageVersus would return 100 anyway, so we might as well do that early. + if (versus.Count == 0) + return 100; + + var armor = victim.TraitsImplementing() + .Where(a => !a.IsTraitDisabled && a.Info.Type != null && versus.ContainsKey(a.Info.Type)) + .Select(a => versus[a.Info.Type]); + + return Util.ApplyPercentageModifiers(100, armor); + } + + public void DamagePassengers(int damage, Actor attacker, int amount, Dictionary versus, BitSet damageTypes, IEnumerable damageModifiers) + { + var passengersToDamage = amount > 0 && amount < garrisonable.Count() ? garrisonable.Shuffle(self.World.SharedRandom).Take(amount) : garrisonable; + foreach (var passenger in passengersToDamage) + { + var d = Util.ApplyPercentageModifiers(damage, damageModifiers.Append(DamageVersus(passenger, versus))); + passenger.InflictDamage(attacker, new Damage(d, damageTypes)); + } + } + + public IEnumerable GetPips(Actor self) + { + var numPips = Info.PipCount; + + for (var i = 0; i < numPips; i++) + yield return GetPipAt(i); + } + + PipType GetPipAt(int i) + { + var n = i * Info.MaxWeight / Info.PipCount; + + foreach (var c in garrisonable) + { + var pi = c.Info.TraitInfo(); + if (n < pi.Weight) + return pi.PipType; + else + n -= pi.Weight; + } + + return PipType.Transparent; + } + + public void Load(Actor self, Actor a) + { + garrisonable.Add(a); + var w = GetWeight(a); + totalWeight += w; + if (reserves.Contains(a)) + { + reservedWeight -= w; + reserves.Remove(a); + ReleaseLock(self); + + if (loadingToken != ConditionManager.InvalidConditionToken) + loadingToken = conditionManager.RevokeCondition(self, loadingToken); + } + + // Don't initialise (effectively twice) if this runs before the FrameEndTask from Created + if (initialised) + { + a.Trait().Transport = self; + + foreach (var nec in a.TraitsImplementing()) + nec.OnEnteredGarrison(a, self); + + foreach (var npe in self.TraitsImplementing()) + npe.OnGarrisonerEntered(self, a); + } + + string garrisonerCondition; + if (conditionManager != null && Info.GarrisonerConditions.TryGetValue(a.Info.Name, out garrisonerCondition)) + garrisonerTokens.GetOrAdd(a.Info.Name).Push(conditionManager.GrantCondition(self, garrisonerCondition)); + + if (conditionManager != null && !string.IsNullOrEmpty(Info.LoadedCondition)) + loadedTokens.Push(conditionManager.GrantCondition(self, Info.LoadedCondition)); + } + + void INotifyKilled.Killed(Actor self, AttackInfo e) + { + if (Info.EjectOnDeath) + while (!IsEmpty(self) && CanUnload(true)) + { + var garrisoner = Unload(self); + var cp = self.CenterPosition; + var inAir = self.World.Map.DistanceAboveTerrain(cp).Length != 0; + var positionable = garrisoner.Trait(); + positionable.SetPosition(garrisoner, self.Location); + + if (!inAir && positionable.CanEnterCell(self.Location, self, false)) + { + self.World.AddFrameEndTask(w => w.Add(garrisoner)); + var nbms = garrisoner.TraitsImplementing(); + foreach (var nbm in nbms) + nbm.OnNotifyBlockingMove(garrisoner, garrisoner); + } + else + garrisoner.Kill(e.Attacker); + } + + foreach (var c in garrisonable) + c.Kill(e.Attacker); + + garrisonable.Clear(); + } + + void INotifyActorDisposing.Disposing(Actor self) + { + foreach (var c in garrisonable) + c.Dispose(); + + garrisonable.Clear(); + } + + void INotifySold.Selling(Actor self) { } + void INotifySold.Sold(Actor self) + { + if (!Info.EjectOnSell || garrisonable == null) + return; + + while (!IsEmpty(self)) + SpawnGarrisoner(Unload(self)); + } + + void SpawnGarrisoner(Actor garrisoner) + { + self.World.AddFrameEndTask(w => + { + w.Add(garrisoner); + garrisoner.Trait().SetPosition(garrisoner, self.Location); + + // TODO: this won't work well for >1 actor as they should move towards the next enterable (sub) cell instead + }); + } + + void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner) + { + if (garrisonable == null) + return; + + foreach (var p in Garrisoners) + p.ChangeOwner(newOwner); + } + + void ITransformActorInitModifier.ModifyTransformActorInit(Actor self, TypeDictionary init) + { + init.Add(new RuntimeGarrisonInit(Garrisoners.ToArray())); + } + + protected override void TraitDisabled(Actor self) + { + if (!CanUnload()) + return; + + self.CancelActivity(); + self.QueueActivity(new UnloadGarrison(self, Info.LoadRange)); + } + } + + public class RuntimeGarrisonInit : IActorInit, ISuppressInitExport + { + [FieldFromYamlKey] + readonly Actor[] value = { }; + public RuntimeGarrisonInit() { } + public RuntimeGarrisonInit(Actor[] init) { value = init; } + public Actor[] Value(World world) { return value; } + } + + public class GarrisonInit : IActorInit + { + [FieldFromYamlKey] + readonly string[] value = { }; + public GarrisonInit() { } + public GarrisonInit(string[] init) { value = init; } + public string[] Value(World world) { return value; } + } +} diff --git a/OpenRA.Mods.RA2/Traits/Garrisoner.cs b/OpenRA.Mods.RA2/Traits/Garrisoner.cs new file mode 100644 index 000000000..980ba5f1f --- /dev/null +++ b/OpenRA.Mods.RA2/Traits/Garrisoner.cs @@ -0,0 +1,227 @@ +#region Copyright & License Information +/* + * Copyright 2007-2019 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System; +using System.Collections.Generic; +using OpenRA.Mods.Common.Traits; +using OpenRA.Mods.RA2.Activities; +using OpenRA.Mods.RA2.Orders; +using OpenRA.Primitives; +using OpenRA.Support; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA2.Traits +{ + [Desc("This actor can enter Garrisonable actors.")] + public class GarrisonerInfo : ITraitInfo + { + public readonly string GarrisonType = null; + public readonly PipType PipType = PipType.Green; + public readonly int Weight = 1; + + [Desc("What diplomatic stances can be Garrisoned by this actor.")] + public readonly Stance TargetStances = Stance.Ally | Stance.Neutral; + + [GrantedConditionReference] + [Desc("The condition to grant to when this actor is loaded inside any transport.")] + public readonly string GarrisonCondition = null; + + [Desc("Conditions to grant when this actor is loaded inside specified transport.", + "A dictionary of [actor id]: [condition].")] + public readonly Dictionary GarrisonConditions = new Dictionary(); + + [GrantedConditionReference] + public IEnumerable LinterGarrisonConditions { get { return GarrisonConditions.Values; } } + + [VoiceReference] + public readonly string Voice = "Action"; + + [ConsumedConditionReference] + [Desc("Boolean expression defining the condition under which the regular (non-force) enter cursor is disabled.")] + public readonly BooleanExpression RequireForceMoveCondition = null; + + public object Create(ActorInitializer init) { return new Garrisoner(this); } + } + + public class Garrisoner : INotifyCreated, IIssueOrder, IResolveOrder, IOrderVoice, INotifyRemovedFromWorld, INotifyEnteredGarrison, INotifyExitedGarrison, INotifyKilled, IObservesVariables + { + public readonly GarrisonerInfo Info; + public Actor Transport; + bool requireForceMove; + + ConditionManager conditionManager; + int anyGarrisonToken = ConditionManager.InvalidConditionToken; + int specificGarrisonToken = ConditionManager.InvalidConditionToken; + + public Garrisoner(GarrisonerInfo info) + { + Info = info; + } + + public Garrisonable ReservedGarrison { get; private set; } + + IEnumerable IIssueOrder.Orders + { + get + { + yield return new EnterGarrisonOrderTargeter("EnterGarrison", 5, IsCorrectGarrisonType, CanEnter, Info); + } + } + + void INotifyCreated.Created(Actor self) + { + conditionManager = self.TraitOrDefault(); + } + + public Order IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued) + { + if (order.OrderID == "EnterGarrison") + return new Order(order.OrderID, self, target, queued); + + return null; + } + + bool IsCorrectGarrisonType(Actor target, TargetModifiers modifiers) + { + if (requireForceMove && !modifiers.HasModifier(TargetModifiers.ForceMove)) + return false; + + return IsCorrectGarrisonType(target); + } + + bool IsCorrectGarrisonType(Actor target) + { + var ci = target.Info.TraitInfo(); + return ci.Types.Contains(Info.GarrisonType); + } + + bool CanEnter(Garrisonable garrison) + { + return garrison != null && garrison.HasSpace(Info.Weight) && !garrison.IsTraitPaused && !garrison.IsTraitDisabled; + } + + bool CanEnter(Actor target) + { + return CanEnter(target.TraitOrDefault()); + } + + public string VoicePhraseForOrder(Actor self, Order order) + { + if (order.OrderString != "EnterGarrison") + return null; + + if (order.Target.Type != TargetType.Actor || !CanEnter(order.Target.Actor)) + return null; + + return Info.Voice; + } + + void INotifyEnteredGarrison.OnEnteredGarrison(Actor self, Actor garrison) + { + string specificGarrisonCondition; + if (conditionManager != null) + { + if (anyGarrisonToken == ConditionManager.InvalidConditionToken && !string.IsNullOrEmpty(Info.GarrisonCondition)) + anyGarrisonToken = conditionManager.GrantCondition(self, Info.GarrisonCondition); + + if (specificGarrisonToken == ConditionManager.InvalidConditionToken && Info.GarrisonConditions.TryGetValue(garrison.Info.Name, out specificGarrisonCondition)) + specificGarrisonToken = conditionManager.GrantCondition(self, specificGarrisonCondition); + } + + // Allow scripted / initial actors to move from the unload point back into the cell grid on unload + // This is handled by the RideTransport activity for player-loaded cargo + if (self.IsIdle) + { + // IMove is not used anywhere else in this trait, there is no benefit to caching it from Created. + var move = self.TraitOrDefault(); + if (move != null) + self.QueueActivity(move.ReturnToCell(self)); + } + } + + void INotifyExitedGarrison.OnExitedGarrison(Actor self, Actor garrison) + { + if (anyGarrisonToken != ConditionManager.InvalidConditionToken) + anyGarrisonToken = conditionManager.RevokeCondition(self, anyGarrisonToken); + + if (specificGarrisonToken != ConditionManager.InvalidConditionToken) + specificGarrisonToken = conditionManager.RevokeCondition(self, specificGarrisonToken); + } + + void IResolveOrder.ResolveOrder(Actor self, Order order) + { + if (order.OrderString != "EnterGarrison") + return; + + if (order.Target.Type == TargetType.Actor) + { + var targetActor = order.Target.Actor; + if (!CanEnter(targetActor)) + return; + + if (!IsCorrectGarrisonType(targetActor)) + return; + } + else + { + var targetActor = order.Target.FrozenActor; + } + + self.QueueActivity(order.Queued, new EnterGarrison(self, order.Target)); + self.ShowTargetLines(); + } + + public bool Reserve(Actor self, Garrisonable garrison) + { + if (garrison == ReservedGarrison) + return true; + + Unreserve(self); + if (!garrison.ReserveSpace(self)) + return false; + + ReservedGarrison = garrison; + return true; + } + + void INotifyRemovedFromWorld.RemovedFromWorld(Actor self) { Unreserve(self); } + + public void Unreserve(Actor self) + { + if (ReservedGarrison == null) + return; + + ReservedGarrison.UnreserveSpace(self); + ReservedGarrison = null; + } + + void INotifyKilled.Killed(Actor self, AttackInfo e) + { + if (Transport == null) + return; + + // Something killed us, but it wasn't our transport blowing up. Remove us from the cargo. + if (!Transport.IsDead) + self.World.AddFrameEndTask(w => Transport.Trait().Unload(Transport, self)); + } + + IEnumerable IObservesVariables.GetVariableObservers() + { + if (Info.RequireForceMoveCondition != null) + yield return new VariableObserver(RequireForceMoveConditionChanged, Info.RequireForceMoveCondition.Variables); + } + + void RequireForceMoveConditionChanged(Actor self, IReadOnlyDictionary conditions) + { + requireForceMove = Info.RequireForceMoveCondition.Evaluate(conditions); + } + } +} diff --git a/OpenRA.Mods.RA2/Traits/TraitsInterfaces.cs b/OpenRA.Mods.RA2/Traits/TraitsInterfaces.cs new file mode 100644 index 000000000..1e5db8a35 --- /dev/null +++ b/OpenRA.Mods.RA2/Traits/TraitsInterfaces.cs @@ -0,0 +1,28 @@ +#region Copyright & License Information +/* + * Copyright 2007-2019 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using OpenRA.GameRules; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA2.Traits +{ + [RequireExplicitImplementation] + public interface INotifyEnteredGarrison { void OnEnteredGarrison(Actor self, Actor garrison); } + + [RequireExplicitImplementation] + public interface INotifyExitedGarrison { void OnExitedGarrison(Actor self, Actor garrison); } + + [RequireExplicitImplementation] + public interface INotifyGarrisonerEntered { void OnGarrisonerEntered(Actor self, Actor garrisoner); } + + [RequireExplicitImplementation] + public interface INotifyGarrisonerExited { void OnGarrisonerExited(Actor self, Actor garrisoner); } +} diff --git a/mods/ra2/rules/allied-infantry.yaml b/mods/ra2/rules/allied-infantry.yaml index 9489cf950..3051a96e7 100644 --- a/mods/ra2/rules/allied-infantry.yaml +++ b/mods/ra2/rules/allied-infantry.yaml @@ -137,6 +137,8 @@ e1: HP: 125 Mobile: PauseOnCondition: chronodisable || !undeployed + Garrisoner: + PipType: Green Passenger: PipType: Green RevealsShroud: diff --git a/mods/ra2/rules/civilian-structures.yaml b/mods/ra2/rules/civilian-structures.yaml index 21103dfed..c997d6fcc 100644 --- a/mods/ra2/rules/civilian-structures.yaml +++ b/mods/ra2/rules/civilian-structures.yaml @@ -3691,7 +3691,7 @@ camsc10.rubble: Image: camsc10 cabunk01: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x2Shape Tooltip: Name: Concrete Bunker @@ -3717,7 +3717,7 @@ cabunk01.rubble: Image: cabunk01 cabunk02: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x2Shape Tooltip: Name: Concrete Bunker diff --git a/mods/ra2/rules/defaults.yaml b/mods/ra2/rules/defaults.yaml index d99377fbd..620c57173 100644 --- a/mods/ra2/rules/defaults.yaml +++ b/mods/ra2/rules/defaults.yaml @@ -421,6 +421,24 @@ MapEditorData: Categories: Civilian building +^GarrisonableBuilding: + Inherits: ^CivBuilding + Inherits@AUTOTARGET: ^AutoTargetGround + ChangeOwnerOnGarrisoner: + Garrisonable: + Types: Garrisoner + MaxWeight: 6 + PipCount: 6 + EjectOnDeath: true + LoadedCondition: loaded + AttackGarrisonedRV: + Armaments: garrisoned + PortOffsets: 768,0,1024, 448,-682,1024, -448,-682,1024, -768,0,1024, -448,682,1024, 448,682,1024 + PortYaws: 0, 176, 341, 512, 682, 853 + PortCones: 88, 88, 88, 88, 88, 88 + PauseOnCondition: chronodisable + RequiresCondition: !build-incomplete + ^Rubble: Inherits@1: ^SpriteActor Inherits@shape: ^1x1Shape diff --git a/mods/ra2/rules/soviet-infantry.yaml b/mods/ra2/rules/soviet-infantry.yaml index 64b2c0283..a53324637 100644 --- a/mods/ra2/rules/soviet-infantry.yaml +++ b/mods/ra2/rules/soviet-infantry.yaml @@ -20,6 +20,8 @@ e2: Bounds: 20, 30, 0, -11 Health: HP: 125 + Garrisoner: + PipType: Green Passenger: PipType: Green RevealsShroud: @@ -63,6 +65,8 @@ flakt: Bounds: 20, 30, 0, -11 Health: HP: 100 + Garrisoner: + PipType: Green Passenger: PipType: Green RevealsShroud: @@ -127,6 +131,8 @@ shk: Armor: Type: Plate -Crushable: + Garrisoner: + PipType: Green Passenger: PipType: Red AttackFrontal: From 9a1a89898deb8309aca46b84df17358c4fd5c850 Mon Sep 17 00:00:00 2001 From: Lesueur Benjamin Date: Thu, 19 Mar 2020 11:27:21 +0100 Subject: [PATCH 02/11] Some changes to garrison Adds garrison art. Make some more buildings garrisonable. Adjusts garrison amount to match original. (McBurger Kong and McRoo don' match in original for some reason, i made Kong have 10 too.) Add proper structure garrisoned/abandoned notification. --- mods/ra2/rules/civilian-structures.yaml | 31 ++++-- mods/ra2/rules/defaults.yaml | 15 ++- mods/ra2/sequences/civilian-structures.yaml | 117 +++++++++++++++++--- mods/ra2/sequences/defaults.yaml | 5 + mods/ra2/sequences/misc.yaml | 12 ++ 5 files changed, 156 insertions(+), 24 deletions(-) diff --git a/mods/ra2/rules/civilian-structures.yaml b/mods/ra2/rules/civilian-structures.yaml index c997d6fcc..d35fa70a0 100644 --- a/mods/ra2/rules/civilian-structures.yaml +++ b/mods/ra2/rules/civilian-structures.yaml @@ -1089,7 +1089,7 @@ canewy18.rubble: Image: canewy18 canewy20: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x5Shape Tooltip: Name: Warehouse @@ -1115,7 +1115,7 @@ canewy20.rubble: Image: canewy20 canewy21: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^5x3Shape Tooltip: Name: Warehouse @@ -1453,7 +1453,7 @@ cacolo01.rubble: Image: cacolo01 caind01: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Building: Footprint: xxxx xxxx xxxx xxxx @@ -1697,7 +1697,7 @@ catexs01.rubble: Image: catexs01 catexs02: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Tooltip: Name: Alamo @@ -3626,7 +3626,7 @@ castl05h.rubble: Image: castl05h camsc07: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x2Shape Tooltip: Name: Hut @@ -3639,11 +3639,14 @@ camsc07: Building: Dimensions: 2,2 Footprint: xx xx + Garrisonable: + MaxWeight: 6 + PipCount: 6 MapEditorData: ExcludeTilesets: SNOW camsc08: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x2Shape Tooltip: Name: Hut @@ -3651,11 +3654,14 @@ camsc08: Range: 6c0 Health: HP: 200 + Garrisonable: + MaxWeight: 6 + PipCount: 6 MapEditorData: ExcludeTilesets: SNOW camsc09: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x2Shape Tooltip: Name: Hut @@ -3663,11 +3669,14 @@ camsc09: Range: 6c0 Health: HP: 200 + Garrisonable: + MaxWeight: 6 + PipCount: 6 MapEditorData: ExcludeTilesets: SNOW camsc10: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Tooltip: Name: McBurger Kong @@ -3704,6 +3713,9 @@ cabunk01: Building: Dimensions: 2,2 Footprint: xx xx + Garrisonable: + MaxWeight: 8 + PipCount: 8 SpawnActorOnDeath: Actor: cabunk01.rubble @@ -3730,6 +3742,9 @@ cabunk02: Building: Dimensions: 2,2 Footprint: xx xx + Garrisonable: + MaxWeight: 8 + PipCount: 8 SpawnActorOnDeath: Actor: cabunk02.rubble diff --git a/mods/ra2/rules/defaults.yaml b/mods/ra2/rules/defaults.yaml index 620c57173..4b11c2c53 100644 --- a/mods/ra2/rules/defaults.yaml +++ b/mods/ra2/rules/defaults.yaml @@ -423,12 +423,16 @@ ^GarrisonableBuilding: Inherits: ^CivBuilding - Inherits@AUTOTARGET: ^AutoTargetGround + Inherits@AUTOTARGET: ^AutoTargetAll ChangeOwnerOnGarrisoner: + EnterSound: ugarris.wav + ExitSound: ugarris.wav + EnterNotification: StructureGarrisoned + ExitNotification: StructureAbandoned Garrisonable: Types: Garrisoner - MaxWeight: 6 - PipCount: 6 + MaxWeight: 10 + PipCount: 10 EjectOnDeath: true LoadedCondition: loaded AttackGarrisonedRV: @@ -438,6 +442,11 @@ PortCones: 88, 88, 88, 88, 88, 88 PauseOnCondition: chronodisable RequiresCondition: !build-incomplete + WithSpriteBody: + RequiresCondition: !loaded + WithSpriteBody@GARRISONED: + Sequence: garrisoned + RequiresCondition: loaded ^Rubble: Inherits@1: ^SpriteActor diff --git a/mods/ra2/sequences/civilian-structures.yaml b/mods/ra2/sequences/civilian-structures.yaml index 22cfcb2de..c0d7f46fb 100644 --- a/mods/ra2/sequences/civilian-structures.yaml +++ b/mods/ra2/sequences/civilian-structures.yaml @@ -217,14 +217,34 @@ canewy18: Offset: 0,-30 canewy20: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 30,-60 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canewy21: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-60 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 caarmy01: Inherits: ^CivStructure @@ -435,27 +455,58 @@ camisc06: -rubble: camsc07: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: + UseTilesetCode: true Offset: 0,-30 - -rubble: + idle: + ShadowStart: 3 + damaged-idle: + Start: 1 + ShadowStart: 4 + garrisoned: + ShadowStart: 5 camsc08: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: + UseTilesetCode: true Offset: 0,-15 - -rubble: + idle: + ShadowStart: 3 + damaged-idle: + Start: 1 + ShadowStart: 4 + garrisoned: + ShadowStart: 5 camsc09: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: + UseTilesetCode: true Offset: 0,-15 - -rubble: + idle: + ShadowStart: 3 + damaged-idle: + Start: 1 + ShadowStart: 4 + garrisoned: + ShadowStart: 5 camsc10: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: + UseTilesetCode: true Offset: 0,-60 + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 camsc11: Inherits: ^CivStructure @@ -642,9 +693,19 @@ cacolo01: Offset: -30,-60 caind01: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: + UseTilesetCode: true Offset: 0,-60 + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 calab: Inherits: ^CivStructure @@ -705,14 +766,34 @@ cawt01: ShadowStart: 3 cabunk01: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-30 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cabunk02: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-30 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 carus01: Inherits: ^CivStructure @@ -851,9 +932,19 @@ catexs01: Offset: 0,-30 catexs02: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 catexs03: Inherits: ^CivStructure diff --git a/mods/ra2/sequences/defaults.yaml b/mods/ra2/sequences/defaults.yaml index aea112d4e..d81e2db32 100644 --- a/mods/ra2/sequences/defaults.yaml +++ b/mods/ra2/sequences/defaults.yaml @@ -284,3 +284,8 @@ Length: * Offset: 0,0 UseTilesetCode: false + +^GarrisonableBuilding: + garrisoned: + Start: 2 + ShadowStart: 6 diff --git a/mods/ra2/sequences/misc.yaml b/mods/ra2/sequences/misc.yaml index 88a02dcaa..ad52dcfce 100644 --- a/mods/ra2/sequences/misc.yaml +++ b/mods/ra2/sequences/misc.yaml @@ -136,6 +136,18 @@ pips: pip-ammo: ammopips pip-ammoempty: ammopips Start: 1 + pip-garrison-empty: pips2 + Start: 6 + pip-garrison-yellow: pips2 + Start: 7 + pip-garrison-white: pips2 + Start: 8 + pip-garrison-red: pips2 + Start: 9 + pip-garrison-blue: pips2 + Start: 10 + pip-garrison-purple: pips2 + Start: 11 # TODO: pip-empty-building: pip-green-building: From 0700353510d7035b89b5b3e1621f78630e8f6443 Mon Sep 17 00:00:00 2001 From: Lesueur Benjamin Date: Thu, 19 Mar 2020 11:59:46 +0100 Subject: [PATCH 03/11] Complete garrisoning. --- mods/ra2/rules/civilian-props.yaml | 5 +- mods/ra2/rules/civilian-structures.yaml | 281 +++++++++++++------- mods/ra2/sequences/civilian-structures.yaml | 278 +++++++++++-------- 3 files changed, 351 insertions(+), 213 deletions(-) diff --git a/mods/ra2/rules/civilian-props.yaml b/mods/ra2/rules/civilian-props.yaml index f48a0175d..0c237597c 100644 --- a/mods/ra2/rules/civilian-props.yaml +++ b/mods/ra2/rules/civilian-props.yaml @@ -356,7 +356,7 @@ camov01: WithIdleOverlay: camov02: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x2Shape Tooltip: Name: Drive In Movie Concession Stand @@ -370,6 +370,9 @@ camov02: Dimensions: 2,2 Footprint: xx xx WithIdleOverlay: + Garrisonable: + MaxWeight: 5 + PipCount: 5 pole01: Inherits: ^TelephonePole diff --git a/mods/ra2/rules/civilian-structures.yaml b/mods/ra2/rules/civilian-structures.yaml index d35fa70a0..242fc3c60 100644 --- a/mods/ra2/rules/civilian-structures.yaml +++ b/mods/ra2/rules/civilian-structures.yaml @@ -22,7 +22,7 @@ cafncp: Name: Prison Camp Fence cahse01: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x2Shape RevealsShroud: Range: 6c0 @@ -31,6 +31,9 @@ cahse01: Building: Dimensions: 3,2 Footprint: xxx xxx + Garrisonable: + MaxWeight: 5 + PipCount: 5 SpawnActorOnDeath: Actor: cahse01.rubble @@ -44,7 +47,7 @@ cahse01.rubble: Image: cahse01 cahse02: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x2Shape RevealsShroud: Range: 6c0 @@ -53,6 +56,9 @@ cahse02: Building: Dimensions: 3,2 Footprint: xxx xxx + Garrisonable: + MaxWeight: 5 + PipCount: 5 SpawnActorOnDeath: Actor: cahse02.rubble @@ -66,7 +72,7 @@ cahse02.rubble: Image: cahse02 cahse03: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x4Shape RevealsShroud: Range: 6c0 @@ -75,6 +81,9 @@ cahse03: Building: Dimensions: 3,4 Footprint: xxx xxx xxx xxx + Garrisonable: + MaxWeight: 5 + PipCount: 5 SpawnActorOnDeath: Actor: cahse03.rubble @@ -88,7 +97,7 @@ cahse03.rubble: Image: cahse03 cahse04: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x2Shape RevealsShroud: Range: 6c0 @@ -97,6 +106,9 @@ cahse04: Building: Dimensions: 3,2 Footprint: xxx xxx + Garrisonable: + MaxWeight: 5 + PipCount: 5 SpawnActorOnDeath: Actor: cahse04.rubble @@ -110,7 +122,7 @@ cahse04.rubble: Image: cahse04 cahse05: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^1x2Shape RevealsShroud: Range: 6c0 @@ -119,6 +131,9 @@ cahse05: Building: Dimensions: 1,2 Footprint: x x + Garrisonable: + MaxWeight: 5 + PipCount: 5 SpawnActorOnDeath: Actor: cahse05.rubble MapEditorData: @@ -134,7 +149,7 @@ cahse05.rubble: Image: cahse05 cahse06: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x1Shape RevealsShroud: Range: 6c0 @@ -143,6 +158,9 @@ cahse06: Building: Dimensions: 2,1 Footprint: xx + Garrisonable: + MaxWeight: 5 + PipCount: 5 SpawnActorOnDeath: Actor: cahse06.rubble MapEditorData: @@ -158,7 +176,7 @@ cahse06.rubble: Image: cahse06 cahse07: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x3Shape RevealsShroud: Range: 6c0 @@ -167,6 +185,9 @@ cahse07: Building: Dimensions: 2,3 Footprint: xx xx xx + Garrisonable: + MaxWeight: 5 + PipCount: 5 SpawnActorOnDeath: Actor: cahse07.rubble MapEditorData: @@ -208,7 +229,7 @@ cats01: Footprint: xx xx cabarn02: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x2Shape Tooltip: Name: Barn @@ -219,6 +240,9 @@ cabarn02: Building: Dimensions: 2,2 Footprint: xx xx + Garrisonable: + MaxWeight: 5 + PipCount: 5 cawash01: Inherits: ^CivBuilding @@ -249,7 +273,7 @@ cawash01.rubble: Image: cawash01 cawash03: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x3Shape Building: Footprint: xxxx xxxx xxxx @@ -275,7 +299,7 @@ cawash03.rubble: Image: cawash03 cawash04: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Building: Footprint: xxxx xxxx xxxx xxxx @@ -301,7 +325,7 @@ cawash04.rubble: Image: cawash04 cawash05: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x2Shape Building: Footprint: xxxx xxxx @@ -327,7 +351,7 @@ cawash05.rubble: Image: cawash05 cawash06: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Armor: Type: Steel @@ -353,7 +377,7 @@ cawash06.rubble: Image: cawash06 cawash07: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Building: Footprint: xxx xxx xxx @@ -377,7 +401,7 @@ cawash07.rubble: Image: cawash07 cawash08: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x4Shape Armor: Type: Steel @@ -401,7 +425,7 @@ cawash08.rubble: Image: cawash08 cawash09: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Building: Footprint: xxx xxx xxx @@ -427,7 +451,7 @@ cawash09.rubble: Image: cawash09 cawash10: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Building: Footprint: xxxx xxxx xxxx xxxx @@ -453,7 +477,7 @@ cawash10.rubble: Image: cawash10 cawash11: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Building: Footprint: xxxx xxxx xxxx xxxx @@ -521,7 +545,7 @@ cawsh12.rubble: Image: cawsh12 cawash13: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x4Shape Armor: Type: Steel @@ -627,7 +651,7 @@ cawash16.rubble: Image: cawash16 cawash17: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^6x4Shape Tooltip: Name: Smithsonian Natural History Museum @@ -704,7 +728,7 @@ cawash19.rubble: Image: cawash19 canewy01: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Building: Footprint: xxxx xxxx xxxx xxxx @@ -777,7 +801,7 @@ canewy05: ExcludeTilesets: SNOW canewy06: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Armor: Type: Steel @@ -803,7 +827,7 @@ canewy06.rubble: Image: canewy06 canewy07: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Armor: Type: Steel @@ -829,7 +853,7 @@ canewy07.rubble: Image: canewy07 canewy08: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Armor: Type: Steel @@ -855,7 +879,7 @@ canewy08.rubble: Image: canewy08 canewy10: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x2Shape Armor: Type: Steel @@ -881,7 +905,7 @@ canewy10.rubble: Image: canewy10 canewy11: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x2Shape Armor: Type: Steel @@ -907,7 +931,7 @@ canewy11.rubble: Image: canewy11 canewy12: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x3Shape Armor: Type: Steel @@ -933,7 +957,7 @@ canewy12.rubble: Image: canewy12 canewy13: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Armor: Type: Steel @@ -959,7 +983,7 @@ canewy13.rubble: Image: canewy13 canewy14: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Armor: Type: Steel @@ -985,7 +1009,7 @@ canewy14.rubble: Image: canewy14 canewy15: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Armor: Type: Steel @@ -1011,7 +1035,7 @@ canewy15.rubble: Image: canewy15 canewy16: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x2Shape Armor: Type: Steel @@ -1037,7 +1061,7 @@ canewy16.rubble: Image: canewy16 canewy17: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x2Shape Armor: Type: Steel @@ -1063,7 +1087,7 @@ canewy17.rubble: Image: canewy17 canewy18: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x2Shape Armor: Type: Steel @@ -1141,7 +1165,7 @@ canewy21.rubble: Image: canewy21 caswst01: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x3Shape Tooltip: Name: Southwest Building @@ -1169,7 +1193,7 @@ caswst01.rubble: Image: caswst01 caarmy01: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x2Shape Building: Footprint: xxx xxx @@ -1182,22 +1206,28 @@ caarmy01: Range: 6c0 caarmy02: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Tooltip: Name: Army Tent RevealsShroud: Range: 6c0 Health: HP: 200 + Garrisonable: + MaxWeight: 4 + PipCount: 4 caarmy03: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Tooltip: Name: Army Tent RevealsShroud: Range: 6c0 Health: HP: 200 + Garrisonable: + MaxWeight: 4 + PipCount: 4 caarmy04: Inherits: ^CivBuilding @@ -1209,7 +1239,7 @@ caarmy04: HP: 200 cawa2a: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Valued: Cost: 2000 @@ -1237,7 +1267,7 @@ cawa2a.rubble: Image: cawa2a cawa2b: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Valued: Cost: 2000 @@ -1265,7 +1295,7 @@ cawa2b.rubble: Image: cawa2b cawa2c: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Valued: Cost: 2000 @@ -1321,7 +1351,7 @@ cawa2d.rubble: Image: cawa2d cafarm01: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x2Shape Building: Footprint: xx xx @@ -1332,6 +1362,9 @@ cafarm01: HP: 400 RevealsShroud: Range: 4c0 + Garrisonable: + MaxWeight: 6 + PipCount: 6 cafarm02: Inherits: ^CivBuilding @@ -1351,7 +1384,7 @@ cafarm02.rubble: Image: cafarm02 cafarm06: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x2Shape Tooltip: Name: Lighthouse @@ -1364,6 +1397,9 @@ cafarm06: Building: Dimensions: 2,2 Footprint: xx xx + Garrisonable: + MaxWeight: 5 + PipCount: 5 SpawnActorOnDeath: Actor: cafarm06.rubble @@ -1479,7 +1515,7 @@ caind01.rubble: Image: caind01 calab: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x4Shape Building: Footprint: xxx xxx xxx xxx @@ -1505,7 +1541,7 @@ calab.rubble: Image: calab cagas01: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Building: Footprint: xxx xxx xxx @@ -1643,7 +1679,7 @@ city05: ExcludeTilesets: SNOW catech01: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Tooltip: Name: Communications Center @@ -1671,7 +1707,7 @@ catech01.rubble: Image: catech01 catexs01: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x2Shape Armor: Type: Steel @@ -1725,7 +1761,7 @@ catexs02.rubble: Image: catexs02 catexs03: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Armor: Type: Steel @@ -1751,7 +1787,7 @@ catexs03.rubble: Image: catexs03 catexs04: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Armor: Type: Steel @@ -1777,7 +1813,7 @@ catexs04.rubble: Image: catexs04 catexs05: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Armor: Type: Steel @@ -1803,7 +1839,7 @@ catexs05.rubble: Image: catexs05 catexs06: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Armor: Type: Steel @@ -1829,7 +1865,7 @@ catexs06.rubble: Image: catexs06 catexs07: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Armor: Type: Steel @@ -1855,7 +1891,7 @@ catexs07.rubble: Image: catexs07 catexs08: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x3Shape Armor: Type: Steel @@ -1907,7 +1943,7 @@ capars01.rubble: Image: capars01 capars02: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^6x4Shape Armor: Type: Steel @@ -1933,7 +1969,7 @@ capars02.rubble: Image: capars02 capars04: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Armor: Type: Steel @@ -1944,6 +1980,9 @@ capars04: Building: Dimensions: 3,3 Footprint: xxx xxx xxx + Garrisonable: + MaxWeight: 6 + PipCount: 6 SpawnActorOnDeath: Actor: capars04.rubble MapEditorData: @@ -1959,7 +1998,7 @@ capars04.rubble: Image: capars04 capars05: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Armor: Type: Steel @@ -1970,6 +2009,9 @@ capars05: Building: Dimensions: 3,3 Footprint: xxx xxx xxx + Garrisonable: + MaxWeight: 6 + PipCount: 6 SpawnActorOnDeath: Actor: capars05.rubble MapEditorData: @@ -1985,7 +2027,7 @@ capars05.rubble: Image: capars05 capars06: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Armor: Type: Steel @@ -1996,6 +2038,9 @@ capars06: Building: Dimensions: 3,3 Footprint: xxx xxx xxx + Garrisonable: + MaxWeight: 6 + PipCount: 6 SpawnActorOnDeath: Actor: capars06.rubble MapEditorData: @@ -2022,7 +2067,7 @@ capars07: Categories: Decoration capars08: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^6x4Shape Armor: Type: Steel @@ -2048,7 +2093,7 @@ capars08.rubble: Image: capars08 capars09: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^6x4Shape Armor: Type: Steel @@ -2074,7 +2119,7 @@ capars09.rubble: Image: capars09 capars10: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x3Shape Tooltip: Name: Bistro @@ -2128,7 +2173,7 @@ capars11.rubble: Image: capars11 capars12: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x5Shape Tooltip: Name: Notre Dame @@ -2156,7 +2201,7 @@ capars12.rubble: Image: capars12 capars13: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x4Shape Tooltip: Name: Bistro @@ -2184,7 +2229,7 @@ capars13.rubble: Image: capars13 capars14: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x3Shape Tooltip: Name: Bistro @@ -2212,7 +2257,7 @@ capars14.rubble: Image: capars14 cafrma: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x2Shape Tooltip: Name: Farmhouse @@ -2225,7 +2270,7 @@ cafrma: Footprint: xx xx cafrmb: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Tooltip: Name: Outhouse RevealsShroud: @@ -2234,9 +2279,12 @@ cafrmb: HP: 50 MapEditorData: Categories: Decoration + Garrisonable: + MaxWeight: 1 + PipCount: 1 caprs03: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^6x4Shape Tooltip: Name: Louvre @@ -2279,7 +2327,7 @@ cagard01: Categories: Decoration carus01: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Tooltip: Name: St. Basil's Cathedral @@ -2343,7 +2391,7 @@ carus02b.rubble: Image: carus02b carus02g: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Tooltip: Name: Kremlin Wall Clock Tower Armor: @@ -2363,7 +2411,7 @@ carus02g.rubble: Image: carus02g carus03: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x5Shape Tooltip: Name: Kremlin Palace @@ -2389,7 +2437,7 @@ carus03.rubble: Image: carus03 carus04: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Armor: Type: Steel @@ -2400,6 +2448,9 @@ carus04: Building: Dimensions: 4,4 Footprint: xxxx xxxx xxxx xxxx + Garrisonable: + MaxWeight: 8 + PipCount: 8 SpawnActorOnDeath: Actor: carus04.rubble @@ -2413,7 +2464,7 @@ carus04.rubble: Image: carus04 carus05: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Armor: Type: Steel @@ -2424,6 +2475,9 @@ carus05: Building: Dimensions: 4,4 Footprint: xxxx xxxx xxxx xxxx + Garrisonable: + MaxWeight: 8 + PipCount: 8 SpawnActorOnDeath: Actor: carus05.rubble @@ -2437,7 +2491,7 @@ carus05.rubble: Image: carus05 carus06: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Armor: Type: Steel @@ -2448,6 +2502,9 @@ carus06: Building: Dimensions: 4,4 Footprint: xxxx xxxx xxxx xxxx + Garrisonable: + MaxWeight: 8 + PipCount: 8 SpawnActorOnDeath: Actor: carus06.rubble @@ -2461,13 +2518,16 @@ carus06.rubble: Image: carus06 carus08: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Armor: Type: Steel RevealsShroud: Range: 6c0 Health: HP: 1000 + Garrisonable: + MaxWeight: 5 + PipCount: 5 SpawnActorOnDeath: Actor: carus08.rubble @@ -2477,7 +2537,7 @@ carus08.rubble: Image: carus08 carus09: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x1Shape Armor: Type: Steel @@ -2488,6 +2548,9 @@ carus09: Building: Dimensions: 2,1 Footprint: xx + Garrisonable: + MaxWeight: 5 + PipCount: 5 SpawnActorOnDeath: Actor: carus09.rubble @@ -2501,7 +2564,7 @@ carus09.rubble: Image: carus09 carus10: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^1x2Shape Armor: Type: Steel @@ -2512,6 +2575,9 @@ carus10: Building: Dimensions: 1,2 Footprint: x x + Garrisonable: + MaxWeight: 5 + PipCount: 5 SpawnActorOnDeath: Actor: carus10.rubble @@ -2525,7 +2591,7 @@ carus10.rubble: Image: carus10 carus11: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x1Shape Armor: Type: Steel @@ -2536,6 +2602,9 @@ carus11: Building: Dimensions: 2,1 Footprint: xx + Garrisonable: + MaxWeight: 5 + PipCount: 5 SpawnActorOnDeath: Actor: carus11.rubble @@ -2549,7 +2618,7 @@ carus11.rubble: Image: carus11 camiam01: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x2Shape Armor: Type: Steel @@ -2575,7 +2644,7 @@ camiam01.rubble: Image: camiam01 camiam02: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x2Shape Armor: Type: Steel @@ -2601,7 +2670,7 @@ camiam02.rubble: Image: camiam02 camiam03: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x3Shape Armor: Type: Steel @@ -2627,7 +2696,7 @@ camiam03.rubble: Image: camiam03 camiam04: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Tooltip: Name: Lifeguard Hut RevealsShroud: @@ -2636,11 +2705,14 @@ camiam04: HP: 200 MapEditorData: Categories: Decoration + Garrisonable: + MaxWeight: 3 + PipCount: 3 MapEditorData: ExcludeTilesets: SNOW camiam05: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x4Shape Armor: Type: Steel @@ -2666,7 +2738,7 @@ camiam05.rubble: Image: camiam05 camiam06: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Armor: Type: Steel @@ -2692,7 +2764,8 @@ camiam06.rubble: Image: camiam06 camiam07: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding + Inherits@shape: ^4x4Shape Armor: Type: Steel RevealsShroud: @@ -2744,7 +2817,7 @@ camiam08.rubble: Image: camiam08 canwy05: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Armor: Type: Steel @@ -2770,7 +2843,7 @@ canwy05.rubble: Image: canwy05 canwy09: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x3Shape Armor: Type: Steel @@ -2796,7 +2869,7 @@ canwy09.rubble: Image: canwy09 canwy22: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Armor: Type: Steel @@ -2822,7 +2895,7 @@ canwy22.rubble: Image: canwy22 canwy23: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x2Shape Armor: Type: Steel @@ -2848,7 +2921,7 @@ canwy23.rubble: Image: canwy23 canwy24: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Armor: Type: Steel @@ -2874,7 +2947,7 @@ canwy24.rubble: Image: canwy24 canwy25: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x3Shape Armor: Type: Steel @@ -2900,7 +2973,7 @@ canwy25.rubble: Image: canwy25 canwy26: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^5x3Shape Armor: Type: Steel @@ -2954,7 +3027,7 @@ camex01.rubble: Image: camex01 camex02: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^6x4Shape Tooltip: Name: Mayan Castillo @@ -3066,7 +3139,7 @@ camex05.rubble: Image: camex05 caeur1: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x2Shape Tooltip: Name: Cottage @@ -3077,6 +3150,9 @@ caeur1: Building: Dimensions: 2,2 Footprint: xx xx + Garrisonable: + MaxWeight: 3 + PipCount: 3 SpawnActorOnDeath: Actor: caeur1.rubble @@ -3090,7 +3166,7 @@ caeur1.rubble: Image: caeur1 caeur2: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x2Shape Tooltip: Name: Cottage @@ -3101,6 +3177,9 @@ caeur2: Building: Dimensions: 2,2 Footprint: xx xx + Garrisonable: + MaxWeight: 3 + PipCount: 3 SpawnActorOnDeath: Actor: caeur2.rubble @@ -3114,7 +3193,7 @@ caeur2.rubble: Image: caeur2 caeur04: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x3Shape Armor: Type: Steel @@ -3138,7 +3217,7 @@ caeur04.rubble: Image: caeur04 cachig01: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x2Shape Armor: Type: Steel @@ -3164,7 +3243,7 @@ cachig01.rubble: Image: cachig01 cachig02: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x3Shape Armor: Type: Steel @@ -3190,7 +3269,7 @@ cachig02.rubble: Image: cachig02 cachig03: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^3x2Shape Armor: Type: Steel @@ -3216,7 +3295,7 @@ cachig03.rubble: Image: cachig03 cachig04: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x2Shape Tooltip: Name: Associates Center @@ -3244,7 +3323,7 @@ cachig04.rubble: Image: cachig04 cachig05: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Tooltip: Name: Sears Tower @@ -3298,7 +3377,7 @@ cachig06.rubble: Image: cachig06 castl01: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Armor: Type: Steel @@ -3324,7 +3403,7 @@ castl01.rubble: Image: castl01 castl02: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Armor: Type: Steel @@ -3350,7 +3429,7 @@ castl02.rubble: Image: castl02 castl03: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^4x4Shape Armor: Type: Steel @@ -3376,7 +3455,7 @@ castl03.rubble: Image: castl03 castl04: - Inherits: ^CivBuilding + Inherits: ^GarrisonableBuilding Inherits@shape: ^2x6Shape Armor: Type: Steel diff --git a/mods/ra2/sequences/civilian-structures.yaml b/mods/ra2/sequences/civilian-structures.yaml index c0d7f46fb..67c8e68ad 100644 --- a/mods/ra2/sequences/civilian-structures.yaml +++ b/mods/ra2/sequences/civilian-structures.yaml @@ -30,22 +30,22 @@ cawash01: UseTilesetCode: false cawash03: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-52 cawash04: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 cawash05: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-45 cawash06: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 UseTilesetCode: false @@ -55,27 +55,27 @@ cawash06: rubble: cuwash06 cawash07: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 cawash08: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-52 cawash09: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 cawash10: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 cawash11: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 @@ -86,7 +86,7 @@ cawsh12: UseTilesetCode: false cawash13: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-52 @@ -108,7 +108,7 @@ cawash16: Offset: -30,-60 cawash17: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-75 @@ -134,7 +134,7 @@ cawash19: Length: 16 canewy01: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 @@ -157,62 +157,62 @@ canewy05: ShadowStart: 3 canewy06: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 canewy07: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 canewy08: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 canewy10: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-37 canewy11: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-37 canewy12: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-37 canewy13: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 canewy14: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 canewy15: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 canewy16: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-30 canewy17: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-30 canewy18: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-30 @@ -247,54 +247,89 @@ canewy21: ZOffset: -3c0 caarmy01: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-37 - -rubble: + UseTilesetCode: true + idle: + ShadowStart: 3 + damaged-idle: + Start: 1 + ShadowStart: 4 + garrisoned: + ShadowStart: 5 caarmy02: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-15 - -rubble: + UseTilesetCode: true + idle: + ShadowStart: 3 + damaged-idle: + Start: 1 + ShadowStart: 4 + garrisoned: + ShadowStart: 5 caarmy03: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-15 - -rubble: + UseTilesetCode: true + idle: + ShadowStart: 3 + damaged-idle: + Start: 1 + ShadowStart: 4 + garrisoned: + ShadowStart: 5 caarmy04: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-15 - -rubble: + UseTilesetCode: true + idle: + ShadowStart: 3 + damaged-idle: + Start: 1 + ShadowStart: 4 + garrisoned: + ShadowStart: 5 cawa2a: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 cawa2b: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 cawa2c: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 cawa2d: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 cafarm01: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: + UseTilesetCode: true Offset: 0,-30 - -rubble: + idle: + ShadowStart: 3 + damaged-idle: + Start: 1 + ShadowStart: 4 + garrisoned: + ShadowStart: 5 cafarm02: Inherits: ^CivStructure @@ -302,24 +337,38 @@ cafarm02: Offset: 0,-15 cafarm06: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-30 cafrma: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-30 - -rubble: + UseTilesetCode: true + idle: + ShadowStart: 3 + damaged-idle: + Start: 2 + ShadowStart: 4 + garrisoned: + ShadowStart: 5 cafrmb: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-15 - -rubble: + UseTilesetCode: true + idle: + ShadowStart: 3 + damaged-idle: + Start: 2 + ShadowStart: 4 + garrisoned: + ShadowStart: 5 cabarn02: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-30 @@ -527,38 +576,45 @@ camsc13: -rubble: camiam01: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-45 camiam02: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-45 camiam03: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-37 camiam04: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-15 - -rubble: + UseTilesetCode: true + idle: + ShadowStart: 3 + damaged-idle: + Start: 1 + ShadowStart: 4 + garrisoned: + ShadowStart: 5 camiam05: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-52 camiam06: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 camiam07: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 @@ -605,7 +661,7 @@ camex01: Offset: -15,-37 camex02: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-75 @@ -625,24 +681,24 @@ camex05: Offset: 0,-30 castl01: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: custl01 Offset: 0,-60 TilesetOverrides: SNOW: URBAN castl02: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: custl02 Offset: 0,-60 castl03: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: custl03 Offset: 0,-60 castl04: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: cgstl04 Offset: 60,-60 UseTilesetCode: false @@ -708,47 +764,47 @@ caind01: ZOffset: -3c0 calab: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-52 cagas01: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 cahse01: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-37 cahse02: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-37 cahse03: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-52 cahse04: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-37 cahse05: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-22 cahse06: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-22 cahse07: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-37 @@ -838,29 +894,29 @@ carus02f: -rubble: carus02g: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-15 rubble: ShadowStart: -1 carus03: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 45,-52 carus04: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 carus05: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 carus06: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 @@ -870,48 +926,48 @@ carus07: Offset: 0,-15 carus08: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-15 carus09: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-22 carus10: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-22 carus11: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-22 cachig01: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-37 cachig02: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-37 cachig03: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-37 cachig04: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: cgchig04 Offset: 0,-30 UseTilesetCode: false cachig05: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 @@ -922,12 +978,12 @@ cachig06: UseTilesetCode: false catech01: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 catexs01: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-30 @@ -947,67 +1003,67 @@ catexs02: ZOffset: -3c0 catexs03: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 catexs04: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 catexs05: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 catexs06: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 catexs07: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 catexs08: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-37 canwy05: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 canwy09: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-37 canwy22: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 canwy23: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-37 canwy24: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 canwy25: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 canwy26: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-60 @@ -1029,7 +1085,7 @@ camov01: Tick: 200 camov02: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-30 idle-overlay: camov02_a @@ -1047,22 +1103,22 @@ capars01: UseTilesetCode: false capars02: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-75 capars04: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 capars05: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 capars06: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 @@ -1073,17 +1129,17 @@ capars07: -rubble: capars08: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-75 capars09: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-75 capars10: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-52 @@ -1094,17 +1150,17 @@ capars11: UseTilesetCode: false capars12: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 30,-60 capars13: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-52 capars14: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-52 @@ -1133,27 +1189,27 @@ cagard01: Tick: 80 caeur1: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-30 caeur2: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-30 caeur04: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-52 caprs03: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-75 caswst01: - Inherits: ^CivStructure + Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-37 From cc973c2cfd9782138026b4d7dcce27063e785c6c Mon Sep 17 00:00:00 2001 From: Lesueur Benjamin Date: Thu, 19 Mar 2020 13:06:45 +0100 Subject: [PATCH 04/11] Complete garrisoning. --- .../{Traits => }/TraitsInterfaces.cs | 0 mods/ra2/rules/allied-infantry.yaml | 12 +- mods/ra2/rules/soviet-infantry.yaml | 12 +- mods/ra2/sequences/civilian-structures.yaml | 994 +++++++++++++++++- 4 files changed, 986 insertions(+), 32 deletions(-) rename OpenRA.Mods.RA2/{Traits => }/TraitsInterfaces.cs (100%) diff --git a/OpenRA.Mods.RA2/Traits/TraitsInterfaces.cs b/OpenRA.Mods.RA2/TraitsInterfaces.cs similarity index 100% rename from OpenRA.Mods.RA2/Traits/TraitsInterfaces.cs rename to OpenRA.Mods.RA2/TraitsInterfaces.cs diff --git a/mods/ra2/rules/allied-infantry.yaml b/mods/ra2/rules/allied-infantry.yaml index 3051a96e7..7b9c9d919 100644 --- a/mods/ra2/rules/allied-infantry.yaml +++ b/mods/ra2/rules/allied-infantry.yaml @@ -137,8 +137,10 @@ e1: HP: 125 Mobile: PauseOnCondition: chronodisable || !undeployed - Garrisoner: + Garrisoner: + Voice: Move PipType: Green + GarrisonType: Garrisoner Passenger: PipType: Green RevealsShroud: @@ -164,6 +166,14 @@ e1: Name: deployed-elite Weapon: paraE RequiresCondition: deployed && rank-elite + Armament@garrisoned: + Weapon: para + Name: garrisoned + RequiresCondition: !rank-elite + Armament@elite-garrisoned: + Weapon: paraE + Name: garrisoned + RequiresCondition: rank-elite WithInfantryBody: DefaultAttackSequence: shoot RequiresCondition: undeployed diff --git a/mods/ra2/rules/soviet-infantry.yaml b/mods/ra2/rules/soviet-infantry.yaml index a53324637..ec27b7b19 100644 --- a/mods/ra2/rules/soviet-infantry.yaml +++ b/mods/ra2/rules/soviet-infantry.yaml @@ -20,8 +20,10 @@ e2: Bounds: 20, 30, 0, -11 Health: HP: 125 - Garrisoner: + Garrisoner: + Voice: Move PipType: Green + GarrisonType: Garrisoner Passenger: PipType: Green RevealsShroud: @@ -34,6 +36,14 @@ e2: Armament@elite: Weapon: M1CarbineE RequiresCondition: rank-elite + Armament@garrisoned: + Name: garrisoned + Weapon: M1Carbine + RequiresCondition: !rank-elite + Armament@elite-garrisoned: + Name: garrisoned + Weapon: M1CarbineE + RequiresCondition: rank-elite WithInfantryBody: DefaultAttackSequence: shoot Voiced: diff --git a/mods/ra2/sequences/civilian-structures.yaml b/mods/ra2/sequences/civilian-structures.yaml index 67c8e68ad..2fcf96a48 100644 --- a/mods/ra2/sequences/civilian-structures.yaml +++ b/mods/ra2/sequences/civilian-structures.yaml @@ -33,51 +33,127 @@ cawash03: Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-52 + idle: cuwash03 + ShadowStart: 4 + damaged-idle: cuwash03 + Start: 1 + ShadowStart: 5 + rubble: cuwash03 + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cawash04: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 + idle: cuwash04 + ShadowStart: 4 + damaged-idle: cuwash04 + Start: 1 + ShadowStart: 5 + rubble: cuwash04 + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cawash05: Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-45 + idle: cuwash05 + ShadowStart: 4 + damaged-idle: cuwash05 + Start: 1 + ShadowStart: 5 + rubble: cuwash05 + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cawash06: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 - UseTilesetCode: false idle: cgwash06_a # Custom artwork, original lacked shadow. ShadowStart: 1 damaged-idle: cuwash06 + Start: 1 + ShadowStart: 5 rubble: cuwash06 + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cawash07: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + idle: cuwash07 + ShadowStart: 4 + damaged-idle: cuwash07 + Start: 1 + ShadowStart: 5 + rubble: cuwash07 + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cawash08: Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-52 + idle: cuwash08 + ShadowStart: 4 + damaged-idle: cuwash08 + Start: 1 + ShadowStart: 5 + rubble: cuwash08 + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cawash09: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + idle: cuwash09 + ShadowStart: 4 + damaged-idle: cuwash09 + Start: 1 + ShadowStart: 5 + rubble: cuwash09 + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cawash10: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 + idle: cuwash10 + ShadowStart: 4 + damaged-idle: cuwash10 + Start: 1 + ShadowStart: 5 + rubble: cuwash10 + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cawash11: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 + idle: cuwash11 + ShadowStart: 4 + damaged-idle: cuwash11 + Start: 1 + ShadowStart: 5 + rubble: cuwash11 + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cawsh12: Inherits: ^CivStructure @@ -89,6 +165,15 @@ cawash13: Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-52 + idle: cuwash13 + ShadowStart: 4 + damaged-idle: cuwash13 + Start: 1 + ShadowStart: 5 + rubble: cuwash13 + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cawash14: Inherits: ^CivStructure @@ -111,6 +196,16 @@ cawash17: Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-75 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cawash18: Defaults: @@ -137,6 +232,15 @@ canewy01: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 + idle: cunewy01 + ShadowStart: 4 + damaged-idle: cunewy01 + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canewy04: Inherits: ^CivStructure @@ -160,61 +264,181 @@ canewy06: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canewy07: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canewy08: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canewy10: Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-37 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canewy11: Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-37 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canewy12: Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-37 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canewy13: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canewy14: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canewy15: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canewy16: Inherits: ^GarrisonableBuilding Defaults: + UseTilesetCode: true Offset: 0,-30 + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canewy17: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-30 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canewy18: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-30 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canewy20: Inherits: ^GarrisonableBuilding @@ -249,8 +473,8 @@ canewy21: caarmy01: Inherits: ^GarrisonableBuilding Defaults: - Offset: -15,-37 UseTilesetCode: true + Offset: -15,-37 idle: ShadowStart: 3 damaged-idle: @@ -302,21 +526,61 @@ cawa2a: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cawa2b: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cawa2c: Inherits: ^GarrisonableBuilding Defaults: + UseTilesetCode: true Offset: 0,-60 + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cawa2d: Inherits: ^GarrisonableBuilding Defaults: + UseTilesetCode: true Offset: 0,-60 + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cafarm01: Inherits: ^GarrisonableBuilding @@ -339,7 +603,17 @@ cafarm02: cafarm06: Inherits: ^GarrisonableBuilding Defaults: + UseTilesetCode: true Offset: 0,-30 + idle: + ShadowStart: 4 + damaged-idle: + Start: 2 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cafrma: Inherits: ^GarrisonableBuilding @@ -370,13 +644,22 @@ cafrmb: cabarn02: Inherits: ^GarrisonableBuilding Defaults: + UseTilesetCode: true Offset: 0,-30 - -causfgl: - Inherits: ^CivStructure - Defaults: - Offset: 0,-15 - -rubble: + idle: + ShadowStart: 4 + damaged-idle: + Start: 2 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 + +causfgl: + Inherits: ^CivStructure + Defaults: + Offset: 0,-15 + -rubble: flag: causfgl_a Length: 16 ShadowStart: 16 @@ -579,16 +862,46 @@ camiam01: Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 camiam02: Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 camiam03: Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-37 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 camiam04: Inherits: ^GarrisonableBuilding @@ -607,16 +920,46 @@ camiam05: Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-52 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 camiam06: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 camiam07: Inherits: ^GarrisonableBuilding Defaults: + UseTilesetCode: true Offset: 0,-60 + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 camiam08: Inherits: ^CivStructure @@ -664,6 +1007,16 @@ camex02: Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-75 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 2 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 camex03: Inherits: ^CivStructure @@ -682,26 +1035,63 @@ camex05: castl01: Inherits: ^GarrisonableBuilding - Defaults: custl01 + Defaults: + UseTilesetCode: true Offset: 0,-60 - TilesetOverrides: - SNOW: URBAN + idle: custl01 + ShadowStart: 4 + damaged-idle: custl01 + Start: 1 + ShadowStart: 5 + rubble: custl01 + UseTilesetCode: false + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 castl02: Inherits: ^GarrisonableBuilding - Defaults: custl02 + Defaults: Offset: 0,-60 + UseTilesetCode: true + idle: custl02 + ShadowStart: 4 + damaged-idle: custl02 + Start: 1 + ShadowStart: 5 + rubble: custl02 + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 castl03: Inherits: ^GarrisonableBuilding - Defaults: custl03 + Defaults: Offset: 0,-60 + UseTilesetCode: true + idle: custl03 + ShadowStart: 4 + damaged-idle: custl03 + Start: 1 + ShadowStart: 5 + rubble: custl03 + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 castl04: Inherits: ^GarrisonableBuilding - Defaults: cgstl04 + Defaults: Offset: 60,-60 - UseTilesetCode: false + idle: cgstl04 + ShadowStart: 3 + damaged-idle: cgstl04 + Start: 1 + ShadowStart: 4 + rubble: cgstl04 + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 castl05a: Inherits: ^CivStructure @@ -766,47 +1156,137 @@ caind01: calab: Inherits: ^GarrisonableBuilding Defaults: + UseTilesetCode: true Offset: 15,-52 + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cagas01: Inherits: ^GarrisonableBuilding Defaults: + UseTilesetCode: true Offset: 0,-45 + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cahse01: Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-37 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 4 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cahse02: Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-37 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 4 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cahse03: Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-52 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 4 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cahse04: Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-37 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 4 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cahse05: Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-22 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cahse06: Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-22 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cahse07: Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-37 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cawt01: Defaults: @@ -852,10 +1332,18 @@ cabunk02: ZOffset: -3c0 carus01: - Inherits: ^CivStructure - Defaults: cgrus01 + Inherits: ^GarrisonableBuilding + Defaults: Offset: 0,-60 - UseTilesetCode: false + idle: cgrus01 + ShadowStart: 4 + damaged-idle: cgrus01 + Start: 1 + ShadowStart: 5 + rubble: cgrus01 + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 carus02a: Inherits: ^CivStructure @@ -897,31 +1385,79 @@ carus02g: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-15 + UseTilesetCode: false + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 rubble: - ShadowStart: -1 + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 carus03: Inherits: ^GarrisonableBuilding Defaults: Offset: 45,-52 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 carus04: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 carus05: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 - -carus06: - Inherits: ^GarrisonableBuilding - Defaults: - Offset: 0,-60 - -carus07: - Inherits: ^CivStructure + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 + +carus06: + Inherits: ^GarrisonableBuilding + Defaults: + Offset: 0,-60 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 + +carus07: + Inherits: ^CivStructure Defaults: Offset: 0,-15 @@ -929,47 +1465,135 @@ carus08: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-15 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 carus09: Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-22 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 carus10: Inherits: ^GarrisonableBuilding Defaults: - Offset: -15,-22 + Offset: 15,-23 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 carus11: Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-22 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cachig01: Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-37 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cachig02: Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-37 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cachig03: Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-37 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cachig04: Inherits: ^GarrisonableBuilding - Defaults: cgchig04 + Defaults: Offset: 0,-30 - UseTilesetCode: false + idle: cgchig04 + ShadowStart: 4 + damaged-idle: cgchig04 + Start: 1 + ShadowStart: 5 + rubble: cgchig04 + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cachig05: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cachig06: Inherits: ^CivStructure @@ -981,11 +1605,31 @@ catech01: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 catexs01: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-30 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 catexs02: Inherits: ^GarrisonableBuilding @@ -1006,66 +1650,196 @@ catexs03: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 catexs04: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 catexs05: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 catexs06: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 catexs07: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 catexs08: Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-37 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canwy05: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-60 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canwy09: Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-37 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canwy22: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canwy23: Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-37 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canwy24: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canwy25: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 canwy26: Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-60 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 camov01: Defaults: @@ -1087,7 +1861,13 @@ camov01: camov02: Inherits: ^GarrisonableBuilding Defaults: + UseTilesetCode: true Offset: 0,-30 + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 idle-overlay: camov02_a Length: 2 Tick: 200 @@ -1095,6 +1875,10 @@ camov02: Start: 2 Length: 2 Tick: 200 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 capars01: Inherits: ^CivStructure @@ -1106,21 +1890,61 @@ capars02: Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-75 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 capars04: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 capars05: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 capars06: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 capars07: Inherits: ^CivStructure @@ -1132,16 +1956,46 @@ capars08: Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-75 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 capars09: Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-75 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 capars10: Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-52 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 capars11: Inherits: ^CivStructure @@ -1153,16 +2007,46 @@ capars12: Inherits: ^GarrisonableBuilding Defaults: Offset: 30,-60 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 capars13: Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-52 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 capars14: Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-52 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 cats01: Defaults: @@ -1192,26 +2076,76 @@ caeur1: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-30 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 caeur2: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-30 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 caeur04: Inherits: ^GarrisonableBuilding Defaults: Offset: -15,-52 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 caprs03: Inherits: ^GarrisonableBuilding Defaults: Offset: -30,-75 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 caswst01: Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-37 + UseTilesetCode: true + idle: + ShadowStart: 4 + damaged-idle: + Start: 1 + ShadowStart: 5 + rubble: + Start: 3 + ShadowStart: 7 + ZOffset: -3c0 galite: idle: From a397c47f23797e892bb5c56b7793a1d17397cfa3 Mon Sep 17 00:00:00 2001 From: Lesueur Benjamin Date: Thu, 19 Mar 2020 13:09:00 +0100 Subject: [PATCH 05/11] Make Garrisoned Structures auto target in defensive stance. --- mods/ra2/rules/defaults.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mods/ra2/rules/defaults.yaml b/mods/ra2/rules/defaults.yaml index 4b11c2c53..53375ffd6 100644 --- a/mods/ra2/rules/defaults.yaml +++ b/mods/ra2/rules/defaults.yaml @@ -442,6 +442,9 @@ PortCones: 88, 88, 88, 88, 88, 88 PauseOnCondition: chronodisable RequiresCondition: !build-incomplete + Targetable@GARRISONED: + TargetTypes: Defense + RequiresCondition: loaded WithSpriteBody: RequiresCondition: !loaded WithSpriteBody@GARRISONED: From 220ae25543512c015e096cc14cad57823921184d Mon Sep 17 00:00:00 2001 From: Lesueur Benjamin Date: Thu, 19 Mar 2020 13:14:18 +0100 Subject: [PATCH 06/11] Make Garrisonable Pauseable. --- mods/ra2/rules/defaults.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ra2/rules/defaults.yaml b/mods/ra2/rules/defaults.yaml index 53375ffd6..2220de1b0 100644 --- a/mods/ra2/rules/defaults.yaml +++ b/mods/ra2/rules/defaults.yaml @@ -435,6 +435,7 @@ PipCount: 10 EjectOnDeath: true LoadedCondition: loaded + PauseOnCondition: dmg_crit AttackGarrisonedRV: Armaments: garrisoned PortOffsets: 768,0,1024, 448,-682,1024, -448,-682,1024, -768,0,1024, -448,682,1024, 448,682,1024 From 79ac06b86ea7ef5b0df8c8fa820ead0f0b92f19f Mon Sep 17 00:00:00 2001 From: Lesueur Benjamin Date: Thu, 19 Mar 2020 13:16:09 +0100 Subject: [PATCH 07/11] Fix some civ buildings using snow garrisoned version. --- mods/ra2/sequences/civilian-structures.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mods/ra2/sequences/civilian-structures.yaml b/mods/ra2/sequences/civilian-structures.yaml index 2fcf96a48..efba574b7 100644 --- a/mods/ra2/sequences/civilian-structures.yaml +++ b/mods/ra2/sequences/civilian-structures.yaml @@ -89,6 +89,7 @@ cawash07: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true idle: cuwash07 ShadowStart: 4 damaged-idle: cuwash07 @@ -103,6 +104,7 @@ cawash08: Inherits: ^GarrisonableBuilding Defaults: Offset: 15,-52 + UseTilesetCode: true idle: cuwash08 ShadowStart: 4 damaged-idle: cuwash08 @@ -117,6 +119,7 @@ cawash09: Inherits: ^GarrisonableBuilding Defaults: Offset: 0,-45 + UseTilesetCode: true idle: cuwash09 ShadowStart: 4 damaged-idle: cuwash09 From 4dfcf15a20a58d7ccdd159ce61be4ed9a32683f7 Mon Sep 17 00:00:00 2001 From: Lesueur Benjamin Date: Thu, 19 Mar 2020 14:06:12 +0100 Subject: [PATCH 08/11] Update civilian-structures.yaml Removed -rubble on ^GarrisonableBuilding --- mods/ra2/sequences/civilian-structures.yaml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/mods/ra2/sequences/civilian-structures.yaml b/mods/ra2/sequences/civilian-structures.yaml index d1f84c0ff..684962f69 100644 --- a/mods/ra2/sequences/civilian-structures.yaml +++ b/mods/ra2/sequences/civilian-structures.yaml @@ -499,7 +499,6 @@ caarmy02: ShadowStart: 4 garrisoned: ShadowStart: 5 - -rubble: caarmy03: Inherits: ^GarrisonableBuilding @@ -513,7 +512,6 @@ caarmy03: ShadowStart: 4 garrisoned: ShadowStart: 5 - -rubble: caarmy04: Inherits: ^GarrisonableBuilding @@ -527,7 +525,6 @@ caarmy04: ShadowStart: 4 garrisoned: ShadowStart: 5 - -rubble: cawa2a: Inherits: ^GarrisonableBuilding @@ -601,7 +598,6 @@ cafarm01: ShadowStart: 4 garrisoned: ShadowStart: 5 - -rubble: cafarm02: Inherits: ^CivStructure @@ -635,7 +631,6 @@ cafrma: ShadowStart: 4 garrisoned: ShadowStart: 5 - -rubble: cafrmb: Inherits: ^GarrisonableBuilding @@ -649,7 +644,6 @@ cafrmb: ShadowStart: 4 garrisoned: ShadowStart: 5 - -rubble: cabarn02: Inherits: ^GarrisonableBuilding @@ -808,7 +802,6 @@ camsc07: ShadowStart: 4 garrisoned: ShadowStart: 5 - -rubble: camsc08: Inherits: ^GarrisonableBuilding @@ -822,7 +815,6 @@ camsc08: ShadowStart: 4 garrisoned: ShadowStart: 5 - -rubble: camsc09: Inherits: ^GarrisonableBuilding @@ -836,7 +828,6 @@ camsc09: ShadowStart: 4 garrisoned: ShadowStart: 5 - -rubble: camsc10: Inherits: ^GarrisonableBuilding @@ -928,7 +919,6 @@ camiam04: ShadowStart: 4 garrisoned: ShadowStart: 5 - -rubble: camiam05: Inherits: ^GarrisonableBuilding From ba8763af1652b2bdc8e8f1f29d8c020570b02dd9 Mon Sep 17 00:00:00 2001 From: Lesueur Benjamin Date: Thu, 19 Mar 2020 14:21:26 +0100 Subject: [PATCH 09/11] Update soviet-infantry.yaml flakt and shk shouldn't be Garrisonable. --- mods/ra2/rules/soviet-infantry.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mods/ra2/rules/soviet-infantry.yaml b/mods/ra2/rules/soviet-infantry.yaml index 4cefe636d..6c46a45ed 100644 --- a/mods/ra2/rules/soviet-infantry.yaml +++ b/mods/ra2/rules/soviet-infantry.yaml @@ -75,8 +75,6 @@ flakt: Bounds: 20, 30, 0, -11 Health: HP: 100 - Garrisoner: - PipType: Green Passenger: PipType: Green RevealsShroud: @@ -141,8 +139,6 @@ shk: Armor: Type: Plate -Crushable: - Garrisoner: - PipType: Green Passenger: PipType: Red AttackFrontal: From 49f7336144f1170917618f4554557cb0f6fc793b Mon Sep 17 00:00:00 2001 From: Lesueur Benjamin Date: Thu, 19 Mar 2020 14:57:17 +0100 Subject: [PATCH 10/11] Fixed bad indentions --- mods/ra2/rules/allied-infantry.yaml | 2 +- mods/ra2/rules/defaults.yaml | 2 +- mods/ra2/sequences/civilian-structures.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mods/ra2/rules/allied-infantry.yaml b/mods/ra2/rules/allied-infantry.yaml index 48bfdcb71..bc8e55b53 100644 --- a/mods/ra2/rules/allied-infantry.yaml +++ b/mods/ra2/rules/allied-infantry.yaml @@ -166,7 +166,7 @@ e1: Name: deployed-elite Weapon: paraE RequiresCondition: deployed && rank-elite - Armament@garrisoned: + Armament@garrisoned: Weapon: para Name: garrisoned RequiresCondition: !rank-elite diff --git a/mods/ra2/rules/defaults.yaml b/mods/ra2/rules/defaults.yaml index 2220de1b0..69e89c03f 100644 --- a/mods/ra2/rules/defaults.yaml +++ b/mods/ra2/rules/defaults.yaml @@ -435,7 +435,7 @@ PipCount: 10 EjectOnDeath: true LoadedCondition: loaded - PauseOnCondition: dmg_crit + PauseOnCondition: dmg_crit AttackGarrisonedRV: Armaments: garrisoned PortOffsets: 768,0,1024, 448,-682,1024, -448,-682,1024, -768,0,1024, -448,682,1024, 448,682,1024 diff --git a/mods/ra2/sequences/civilian-structures.yaml b/mods/ra2/sequences/civilian-structures.yaml index 684962f69..b4168910c 100644 --- a/mods/ra2/sequences/civilian-structures.yaml +++ b/mods/ra2/sequences/civilian-structures.yaml @@ -105,7 +105,7 @@ cawash08: Inherits: ^GarrisonableBuilding Defaults: Offset: 15, -52, 52 - UseTilesetCode: true + UseTilesetCode: true idle: cuwash08 ShadowStart: 4 damaged-idle: cuwash08 @@ -120,7 +120,7 @@ cawash09: Inherits: ^GarrisonableBuilding Defaults: Offset: 0, -45, 45 - UseTilesetCode: true + UseTilesetCode: true idle: cuwash09 ShadowStart: 4 damaged-idle: cuwash09 From c69847b44b00b0f73b5257aaab06f4ddb27b4d6a Mon Sep 17 00:00:00 2001 From: Lesueur Benjamin Date: Thu, 19 Mar 2020 14:57:25 +0100 Subject: [PATCH 11/11] Update Garrisoner.cs Removed useless else condition. --- OpenRA.Mods.RA2/Traits/Garrisoner.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/OpenRA.Mods.RA2/Traits/Garrisoner.cs b/OpenRA.Mods.RA2/Traits/Garrisoner.cs index 980ba5f1f..5322abdf8 100644 --- a/OpenRA.Mods.RA2/Traits/Garrisoner.cs +++ b/OpenRA.Mods.RA2/Traits/Garrisoner.cs @@ -170,10 +170,6 @@ void IResolveOrder.ResolveOrder(Actor self, Order order) if (!IsCorrectGarrisonType(targetActor)) return; } - else - { - var targetActor = order.Target.FrozenActor; - } self.QueueActivity(order.Queued, new EnterGarrison(self, order.Target)); self.ShowTargetLines();