Polish cnc pyle & hand inf production; lays groundwork for future polish. Likely breaks every other production structure (untested).
This commit is contained in:
@@ -220,6 +220,7 @@
|
||||
<Compile Include="Traits\Targetable.cs" />
|
||||
<Compile Include="Traits\Health.cs" />
|
||||
<Compile Include="Traits\RepairableBuilding.cs" />
|
||||
<Compile Include="Traits\Activities\Drag.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA.Activities
|
||||
namespace OpenRA.Traits.Activities
|
||||
{
|
||||
public class Drag : IActivity
|
||||
{
|
||||
@@ -16,86 +16,98 @@ using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Traits
|
||||
{
|
||||
public class ProductionInfo : TraitInfo<Production>
|
||||
public class ProductionInfo : ITraitInfo
|
||||
{
|
||||
public readonly int[] SpawnOffset = null;
|
||||
public readonly int[] ProductionOffset = null;
|
||||
public readonly int[] ExitOffset = null;
|
||||
public readonly float[] SpawnOffsets; // in px relative to CenterLocation
|
||||
public readonly int[] ExitCells; // in cells relative to TopLeft, supports a list for multiple exits
|
||||
public readonly bool EnablePrimary = true;
|
||||
public readonly string[] Produces = { };
|
||||
|
||||
public virtual object Create(ActorInitializer init) { return new Production(this); }
|
||||
}
|
||||
|
||||
public class Production : IIssueOrder, IResolveOrder, ITags, IOrderCursor
|
||||
{
|
||||
public virtual int2? CreationLocation( Actor self, ActorInfo producee )
|
||||
public readonly Dictionary<float2, int2> Spawns = new Dictionary<float2, int2>();
|
||||
public Production(ProductionInfo info)
|
||||
{
|
||||
var pos = Util.CellContaining(self.CenterLocation);
|
||||
var pi = self.Info.Traits.Get<ProductionInfo>();
|
||||
if (pi.ProductionOffset != null)
|
||||
pos += pi.ProductionOffset.AsInt2();
|
||||
return pos;
|
||||
}
|
||||
if (info.SpawnOffsets == null || info.ExitCells == null)
|
||||
return;
|
||||
|
||||
public virtual int2? ExitLocation(Actor self, ActorInfo producee)
|
||||
{
|
||||
var pos = Util.CellContaining(self.CenterLocation);
|
||||
var pi = self.Info.Traits.Get<ProductionInfo>();
|
||||
if (pi.ExitOffset != null)
|
||||
pos += pi.ExitOffset.AsInt2();
|
||||
return pos;
|
||||
}
|
||||
if (info.SpawnOffsets.Length != info.ExitCells.Length)
|
||||
throw new System.InvalidOperationException("SpawnOffset, ExitCells length mismatch");
|
||||
|
||||
public virtual int CreationFacing( Actor self, Actor newUnit )
|
||||
{
|
||||
return newUnit.traits.Get<IFacing>().InitialFacing;
|
||||
for (int i = 0; i < info.ExitCells.Length; i+=2)
|
||||
Spawns.Add(new float2(info.SpawnOffsets[i],info.SpawnOffsets[i+1]), new int2(info.ExitCells[i], info.ExitCells[i+1]));
|
||||
}
|
||||
|
||||
public virtual bool Produce( Actor self, ActorInfo producee )
|
||||
{
|
||||
var location = CreationLocation( self, producee );
|
||||
if( location == null || self.World.WorldActor.traits.Get<UnitInfluence>().GetUnitsAt( location.Value ).Any() )
|
||||
return false;
|
||||
|
||||
var newUnit = self.World.CreateActor( producee.Name, new TypeDictionary
|
||||
var newUnit = self.World.CreateActor(false, producee.Name, new TypeDictionary
|
||||
{
|
||||
new LocationInit( location.Value ),
|
||||
new OwnerInit( self.Owner ),
|
||||
});
|
||||
|
||||
var pi = self.Info.Traits.Get<ProductionInfo>();
|
||||
var rp = self.traits.GetOrDefault<RallyPoint>();
|
||||
if (rp != null || pi.ExitOffset != null)
|
||||
// Todo: remove assumption on Mobile
|
||||
var mobile = newUnit.traits.Get<Mobile>();
|
||||
|
||||
// Pick an exit that we can move to
|
||||
var exit = int2.Zero;
|
||||
var spawn = float2.Zero;
|
||||
var success = false;
|
||||
|
||||
// Pick a spawn/exit point
|
||||
// Todo: Reorder in a synced random way
|
||||
foreach (var s in Spawns)
|
||||
{
|
||||
var mobile = newUnit.traits.GetOrDefault<Mobile>();
|
||||
if (mobile != null)
|
||||
exit = self.Location + s.Value;
|
||||
spawn = self.CenterLocation + s.Key;
|
||||
if (mobile.CanEnterCell(exit,self,true))
|
||||
{
|
||||
int2? target = null;
|
||||
if (pi.ExitOffset != null)
|
||||
{
|
||||
target = ExitLocation(self, producee).Value;
|
||||
newUnit.QueueActivity(new Activities.Move(target.Value, 1));
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
// Hack around mobile being a tard; remove from UIM (we shouldn't be there in the first place)
|
||||
newUnit.traits.Get<Mobile>().RemoveInfluence();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unit can be built; add to the world
|
||||
self.World.Add(newUnit);
|
||||
|
||||
// Set the physical position of the unit as the exit cell
|
||||
mobile.SetPosition(newUnit,exit);
|
||||
var to = Util.CenterOfCell(exit);
|
||||
|
||||
// Animate the spawn -> exit transition
|
||||
newUnit.CenterLocation = spawn;
|
||||
mobile.Facing = Util.GetFacing(to - spawn, mobile.Facing);
|
||||
var speed = mobile.MovementSpeedForCell(self, exit);
|
||||
var length = speed > 0 ? (int)( ( to - spawn ).Length*3 / speed ) : 0;
|
||||
newUnit.QueueActivity(new Activities.Drag(spawn, to, length));
|
||||
|
||||
// For the target line
|
||||
var target = exit;
|
||||
var rp = self.traits.GetOrDefault<RallyPoint>();
|
||||
if (rp != null)
|
||||
{
|
||||
target = rp.rallyPoint;
|
||||
newUnit.QueueActivity(new Activities.Move(target.Value, 1));
|
||||
newUnit.QueueActivity(new Activities.Move(target, 1));
|
||||
}
|
||||
|
||||
if (target != null && newUnit.Owner == self.World.LocalPlayer)
|
||||
if (newUnit.Owner == self.World.LocalPlayer)
|
||||
{
|
||||
self.World.AddFrameEndTask(w =>
|
||||
{
|
||||
var line = newUnit.traits.GetOrDefault<DrawLineToTarget>();
|
||||
if (line != null)
|
||||
line.SetTargetSilently(newUnit, Target.FromCell(target.Value), Color.Green);
|
||||
line.SetTargetSilently(newUnit, Target.FromCell(target), Color.Green);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pi != null && pi.SpawnOffset != null)
|
||||
newUnit.CenterLocation = self.CenterLocation + pi.SpawnOffset.AsInt2();
|
||||
|
||||
foreach (var t in self.traits.WithInterface<INotifyProduction>())
|
||||
t.UnitProduced(self, newUnit);
|
||||
|
||||
@@ -21,11 +21,13 @@ namespace OpenRA.Mods.Cnc
|
||||
{
|
||||
public class ProductionAirdropInfo : ProductionInfo
|
||||
{
|
||||
public override object Create(ActorInitializer init) { return new ProductionAirdrop(); }
|
||||
public override object Create(ActorInitializer init) { return new ProductionAirdrop(this); }
|
||||
}
|
||||
|
||||
class ProductionAirdrop : Production
|
||||
{
|
||||
public ProductionAirdrop(ProductionAirdropInfo info) : base(info) {}
|
||||
|
||||
public override bool Produce( Actor self, ActorInfo producee )
|
||||
{
|
||||
var owner = self.Owner;
|
||||
|
||||
@@ -44,12 +44,11 @@ namespace OpenRA.Mods.RA.Activities
|
||||
if (res != null)
|
||||
self.traits.Get<Helicopter>().reservation = res.Reserve(self);
|
||||
|
||||
var pi = dest.Info.Traits.GetOrDefault<ProductionInfo>();
|
||||
var offset = pi != null ? pi.SpawnOffset : null;
|
||||
var offsetVec = offset != null ? new float2(offset[0], offset[1]) : float2.Zero;
|
||||
var pi = dest.traits.Get<Production>();
|
||||
var offset = pi != null ? pi.Spawns.First().Key : float2.Zero;
|
||||
|
||||
return Util.SequenceActivities(
|
||||
new HeliFly(dest.CenterLocation + offsetVec),
|
||||
new HeliFly(dest.CenterLocation + offset),
|
||||
new Turn(initialFacing),
|
||||
new HeliLand(false),
|
||||
new Rearm(),
|
||||
|
||||
@@ -104,9 +104,8 @@ namespace OpenRA.Mods.RA
|
||||
if (res != null)
|
||||
reservation = res.Reserve(self);
|
||||
|
||||
var productionInfo = order.TargetActor.Info.Traits.GetOrDefault<ProductionInfo>();
|
||||
var offset = productionInfo != null ? productionInfo.SpawnOffset : null;
|
||||
var offsetVec = offset != null ? new float2(offset[0], offset[1]) : float2.Zero;
|
||||
var pi = order.TargetActor.traits.Get<Production>();
|
||||
var offset = pi != null ? pi.Spawns.First().Key : float2.Zero;
|
||||
|
||||
if (self.Owner == self.World.LocalPlayer)
|
||||
self.World.AddFrameEndTask(w =>
|
||||
@@ -118,7 +117,7 @@ namespace OpenRA.Mods.RA
|
||||
});
|
||||
|
||||
self.CancelActivity();
|
||||
self.QueueActivity(new HeliFly(order.TargetActor.CenterLocation + offsetVec));
|
||||
self.QueueActivity(new HeliFly(order.TargetActor.CenterLocation + offset));
|
||||
self.QueueActivity(new Turn(Info.InitialFacing));
|
||||
self.QueueActivity(new HeliLand(false));
|
||||
self.QueueActivity(Info.RearmBuildings.Contains(order.TargetActor.Info.Name)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
@@ -215,7 +215,6 @@
|
||||
<Compile Include="Invulnerable.cs" />
|
||||
<Compile Include="ReplaceWithActor.cs" />
|
||||
<Compile Include="OreRefineryDockAction.cs" />
|
||||
<Compile Include="Activities\Drag.cs" />
|
||||
<Compile Include="ProducesHelicopters.cs" />
|
||||
<Compile Include="StoresOre.cs" />
|
||||
<Compile Include="PaletteFromCurrentTheatre.cs" />
|
||||
|
||||
@@ -17,11 +17,14 @@ namespace OpenRA.Mods.RA
|
||||
{
|
||||
public class ProducesHelicoptersInfo : ProductionInfo
|
||||
{
|
||||
public override object Create(ActorInitializer init) { return new ProducesHelicopters(); }
|
||||
public override object Create(ActorInitializer init) { return new ProducesHelicopters(this); }
|
||||
}
|
||||
|
||||
class ProducesHelicopters : Production
|
||||
{
|
||||
public ProducesHelicopters(ProducesHelicoptersInfo info) : base(info) {}
|
||||
|
||||
/*
|
||||
// Hack around visibility bullshit in Production
|
||||
public override bool Produce( Actor self, ActorInfo producee )
|
||||
{
|
||||
@@ -29,13 +32,14 @@ namespace OpenRA.Mods.RA
|
||||
if( location == null || self.World.WorldActor.traits.Get<UnitInfluence>().GetUnitsAt( location.Value ).Any() )
|
||||
return false;
|
||||
|
||||
var pi = self.Info.Traits.Get<ProductionInfo>();
|
||||
var newUnit = self.World.CreateActor( producee.Name, new TypeDictionary
|
||||
{
|
||||
new LocationInit( location.Value ),
|
||||
new OwnerInit( self.Owner ),
|
||||
new FacingInit( pi.ProductionFacing ),
|
||||
});
|
||||
|
||||
var pi = self.Info.Traits.Get<ProductionInfo>();
|
||||
var rp = self.traits.GetOrDefault<RallyPoint>();
|
||||
if( rp != null || pi.ExitOffset != null)
|
||||
{
|
||||
@@ -60,5 +64,6 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,13 @@ namespace OpenRA.Mods.RA
|
||||
{
|
||||
class ProductionSurroundInfo : ProductionInfo
|
||||
{
|
||||
public override object Create(ActorInitializer init) { return new ProductionSurround(); }
|
||||
public override object Create(ActorInitializer init) { return new ProductionSurround(this); }
|
||||
}
|
||||
|
||||
class ProductionSurround : Production
|
||||
{
|
||||
public ProductionSurround(ProductionSurroundInfo info) : base(info) {}
|
||||
|
||||
static int2? FindAdjacentTile(Actor self, bool waterBound)
|
||||
{
|
||||
var tiles = Footprint.Tiles(self);
|
||||
@@ -34,7 +36,7 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
public override int2? CreationLocation(Actor self, ActorInfo producee)
|
||||
{
|
||||
return FindAdjacentTile(self, self.Info.Traits.Get<BuildingInfo>().WaterBound);
|
||||
@@ -44,5 +46,6 @@ namespace OpenRA.Mods.RA
|
||||
{
|
||||
return Util.GetFacing(newUnit.CenterLocation - self.CenterLocation, 128);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace OpenRA.Mods.RA.Render
|
||||
|
||||
bool ChooseMoveAnim(Actor self)
|
||||
{
|
||||
if (!(self.GetCurrentActivity() is Move))
|
||||
if (!(self.GetCurrentActivity() is Move) && !(self.GetCurrentActivity() is Drag)) // A bit of a hack
|
||||
return false;
|
||||
|
||||
var mobile = self.traits.Get<Mobile>();
|
||||
|
||||
@@ -17,11 +17,13 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
public class ReservableProductionInfo : ProductionInfo, ITraitPrerequisite<ReservableInfo>
|
||||
{
|
||||
public override object Create(ActorInitializer init) { return new ReservableProduction(); }
|
||||
public override object Create(ActorInitializer init) { return new ReservableProduction(this); }
|
||||
}
|
||||
|
||||
class ReservableProduction : Production
|
||||
{
|
||||
public ReservableProduction(ReservableProductionInfo info) : base(info) {}
|
||||
|
||||
public override bool Produce(Actor self, ActorInfo producee)
|
||||
{
|
||||
if (Reservable.IsReserved(self))
|
||||
|
||||
@@ -158,6 +158,8 @@ PYLE:
|
||||
RallyPoint:
|
||||
Production:
|
||||
Produces: Infantry
|
||||
SpawnOffsets: -10,2, 7,7
|
||||
ExitCells: 0,1, 1,1
|
||||
|
||||
HAND:
|
||||
Inherits: ^Building
|
||||
@@ -184,6 +186,8 @@ HAND:
|
||||
RallyPoint:
|
||||
Production:
|
||||
Produces: Infantry
|
||||
SpawnOffsets: 12,24
|
||||
ExitCells:1,2
|
||||
|
||||
AFLD:
|
||||
Inherits: ^Building
|
||||
@@ -237,7 +241,7 @@ WEAP:
|
||||
RenderWarFactory:
|
||||
RallyPoint:
|
||||
Production:
|
||||
ExitOffset:-1,1
|
||||
# ExitOffset:-1,1
|
||||
Produces: Vehicle
|
||||
HQ:
|
||||
RequiresPower:
|
||||
@@ -335,7 +339,7 @@ HPAD:
|
||||
Range: 5
|
||||
Bib:
|
||||
ProducesHelicopters:
|
||||
SpawnOffset: 0,-4
|
||||
SpawnOffsets: 0,-4
|
||||
Produces: Plane
|
||||
BelowUnits:
|
||||
Reservable:
|
||||
|
||||
Reference in New Issue
Block a user