diff --git a/About/About.xml b/About/About.xml
index 9a4e1d1..27ce32f 100755
--- a/About/About.xml
+++ b/About/About.xml
@@ -1,8 +1,8 @@
- A2B_Core v0.12.1
+ A2B_Core v0.13.0
noone, asarium, FredrikLH, TehJoE, bigmap001, 1000101
- Alpha 12d
+ Alpha 13
http://bit.ly/1EdE0Xc
- This mod adds conveyor belts to Rimworld. Now you can efficiently transport goods to the most remote locations of your encampment.
+ This mod adds conveyor belts to Rimworld. Now you can efficiently transport goods to the most remote locations of your encampment.
\ No newline at end of file
diff --git a/Assemblies/A2B.dll b/Assemblies/A2B.dll
index 964d76a..723efda 100755
Binary files a/Assemblies/A2B.dll and b/Assemblies/A2B.dll differ
diff --git a/Defs/A2BDataDefs/A2BData.xml b/Defs/A2BDataDefs/A2BData.xml
index d7e79ff..a35b8f0 100644
--- a/Defs/A2BDataDefs/A2BData.xml
+++ b/Defs/A2BDataDefs/A2BData.xml
@@ -1,6 +1,6 @@
-
-
-
-
- A2BCore
-
-
- 0.12.1
-
-
- 100
-
-
- 180
- -90
-
-
- A2B_BeltSpeed
-
-
-
- -10.0
- -20.0
-
-
- A2B_Climatization
-
-
-
- 0.05
- -0.025
-
-
- A2B_Durability
-
-
-
- 5.0
- 5.0
- 0.20
- 0.20
-
-
- A2B_Reliability
-
-
-
+
+
+
+ A2BCore
+
+
+ 0.13.0
+
+
+ 100
+
+
+ 0.1
+ 10
+
+
+ 180
+ -90
+
+
+ A2B_BeltSpeed
+
+
+
+ -10.0
+ -20.0
+
+
+ A2B_Climatization
+
+
+
+ 0.03
+ -0.015
+
+
+ A2B_Durability
+
+
+
+ 5.0
+ 5.0
+ 0.20
+ 0.20
+
+
+ A2B_Reliability
+
+
+
\ No newline at end of file
diff --git a/Defs/DesignationDefs/A2B_Designations.xml b/Defs/DesignationDefs/A2B_Designations.xml
index 41b2f0d..ee1e900 100644
--- a/Defs/DesignationDefs/A2B_Designations.xml
+++ b/Defs/DesignationDefs/A2B_Designations.xml
@@ -5,7 +5,7 @@
A2BUndercoverCoverToggleDesignation
Designations/Flick
Thing
- true
+ true
\ No newline at end of file
diff --git a/Defs/DesignatorDefs/A2B_Designators.xml b/Defs/DesignatorDefs/A2B_Designators.xml
deleted file mode 100644
index fe033d0..0000000
--- a/Defs/DesignatorDefs/A2B_Designators.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
- A2BUndercoverCoverToggleDesignator
- A2B.Designator_ToggleUndercoverCover
- ConveyorBelts
-
-
-
\ No newline at end of file
diff --git a/Defs/ThingDefs/Building_A2B.xml b/Defs/ThingDefs/Building_A2B.xml
index cb20a72..4f10936 100755
--- a/Defs/ThingDefs/Building_A2B.xml
+++ b/Defs/ThingDefs/Building_A2B.xml
@@ -26,13 +26,27 @@
1
0.34
+
+
+
+
+
Normal
ConveyorBelts
- A2B
-
+
+
+ A2B
+
+
+
+
+ MinifiedFurniture
+
+
+
A2BBelt
conveyor belt
A2B.Building_ConveyorBelt
@@ -48,7 +62,7 @@
The basic unit of a conveyor belt.
-
+
CompPowerTrader
10
PowerOnSmall
@@ -56,7 +70,7 @@
true
true
-
+
CompGlower
1
(255,200,0,0)
@@ -67,13 +81,14 @@
(1,1)
- 15
+ 10
+ 1
B
- 1
+ 1
-
+
A2BCurve
curved belt
Building
@@ -89,7 +104,7 @@
The basic unit of a conveyor belt, only curved.
-
+
CompPowerTrader
10
PowerOnSmall
@@ -97,7 +112,7 @@
true
true
-
+
CompGlower
1
(255,200,0,0)
@@ -108,12 +123,13 @@
(1,1)
- 15
+ 10
+ 1
- V
+ V
-
+
A2BLoader
loader
Building_Storage
@@ -150,7 +166,7 @@
Loads any item you want onto a belt.
-
+
CompPowerTrader
10
PowerOnSmall
@@ -158,7 +174,7 @@
true
true
-
+
CompGlower
1
(255,200,0,0)
@@ -168,14 +184,15 @@
- 15
+ 10
+ 1
true
L
- Item
+ Item
-
+
A2BUnloader
unloader
Building
@@ -191,7 +208,7 @@
Unload the content of a conveyor belt into a pile or onto a hopper.
-
+
CompPowerTrader
10
PowerOnSmall
@@ -199,7 +216,7 @@
true
true
-
+
CompGlower
1
(255,200,0,0)
@@ -210,12 +227,13 @@
(1,1)
- 15
+ 10
+ 1
- U
+ U
-
+
A2BSplitter
splitter
Building
@@ -231,7 +249,7 @@
Sends items left, forward, and right in sequence.
-
+
CompPowerTrader
15
PowerOnSmall
@@ -239,7 +257,7 @@
true
true
-
+
CompGlower
1
(255,200,0,0)
@@ -250,12 +268,13 @@
(1,1)
- 20
+ 10
+ 2
- P
+ P
-
+
A2BMerger
merger
Building
@@ -271,7 +290,7 @@
Merges up to three belts into one.
-
+
CompPowerTrader
15
PowerOnSmall
@@ -279,7 +298,7 @@
true
true
-
+
CompGlower
1
(255,200,0,0)
@@ -290,7 +309,8 @@
(1,1)
- 20
+ 10
+ 1
M
diff --git a/Defs/ThingDefs/Building_A2B2.xml b/Defs/ThingDefs/Building_A2B2.xml
index afa95cf..876c72c 100644
--- a/Defs/ThingDefs/Building_A2B2.xml
+++ b/Defs/ThingDefs/Building_A2B2.xml
@@ -1,38 +1,17 @@
-
- Building
-
- BulletImpactSteel
-
- true
- true
-
- Light
- ConstructMetal
- Repair
- false
- false
- true
- BuildingRubble
-
- Waist
- PassThroughOnly
- 1000
-
- MapMeshAndRealTime
- true
- 1
- 0.34
-
- Normal
+
+
+ A2B2
+
+
- ConveyorBelts
- A2B2
+
+ MinifiedFurniture
-
+
A2BSelector
selector
Building_Storage
@@ -51,7 +30,7 @@
Sort and redirect items.
-
+
CompPowerTrader
25
PowerOnSmall
@@ -59,7 +38,7 @@
true
true
-
+
CompGlower
1
(255,200,0,0)
@@ -70,12 +49,13 @@
(1,1)
- 25
+ 10
+ 2
H
-
+
A2BUndercover
underground belt
Building
@@ -114,13 +94,14 @@
(1,1)
- 25
+ 20
+ 1
1
G
-
+
A2BUndercoverCover
underground belt cover
Building
@@ -161,7 +142,7 @@
None
-
+
A2BUndertaker
undertaker
Building
@@ -185,12 +166,13 @@
(1,1)
- 50
+ 20
+ 1
R
-
+
A2BLift
undertaker
Building
@@ -208,7 +190,7 @@
Connects surface and underground belts.
-
+
CompPowerTrader
50
PowerOnSmall
@@ -216,7 +198,7 @@
true
true
-
+
CompGlower
3
(255,58,0,0)
@@ -227,12 +209,13 @@
(1,1)
- 50
+ 20
+ 1
None
-
+
A2BSlide
undertaker
Building
@@ -256,7 +239,8 @@
(1,1)
- 50
+ 20
+ 1
None
diff --git a/Languages/English/Keyed/A2B.xml b/Languages/English/Keyed/A2B.xml
index 9840faa..8216909 100755
--- a/Languages/English/Keyed/A2B.xml
+++ b/Languages/English/Keyed/A2B.xml
@@ -34,4 +34,7 @@
South
West
+ Output {0}\nto ground
+ Allow selector output\n{0} to ground
+
\ No newline at end of file
diff --git a/Source/A2B/A2B.csproj b/Source/A2B/A2B.csproj
index 43251b9..6179bb4 100755
--- a/Source/A2B/A2B.csproj
+++ b/Source/A2B/A2B.csproj
@@ -12,7 +12,7 @@
v3.5
512
- 0.12.1.0
+ 0.12.2.0
none
diff --git a/Source/A2B/A2B.sln b/Source/A2B/A2B.sln
index 6160723..30a46b3 100755
--- a/Source/A2B/A2B.sln
+++ b/Source/A2B/A2B.sln
@@ -23,7 +23,7 @@ Global
$1.inheritsSet = VisualStudio
$1.inheritsScope = text/plain
$1.scope = text/plain
- version = 0.12.1.0
+ version = 0.12.2.0
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Source/A2B/A2B.userprefs b/Source/A2B/A2B.userprefs
index 63a3c0b..45c1a17 100644
--- a/Source/A2B/A2B.userprefs
+++ b/Source/A2B/A2B.userprefs
@@ -1,15 +1,22 @@
-
-
-
-
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/A2B/Buildings/Building_ConveyorBelt.cs b/Source/A2B/Buildings/Building_ConveyorBelt.cs
index 546b749..76534a2 100644
--- a/Source/A2B/Buildings/Building_ConveyorBelt.cs
+++ b/Source/A2B/Buildings/Building_ConveyorBelt.cs
@@ -40,8 +40,8 @@ public override void Tick()
{
base.Tick();
- CompPowerTrader power = GetComp();
- BeltComponent belt = GetComp();
+ //CompPowerTrader power = GetComp();
+ //BeltComponent belt = GetComp();
if (Graphic.GetType() == typeof(AnimatedGraphic))
{
diff --git a/Source/A2B/Components/BeltComponent.cs b/Source/A2B/Components/BeltComponent.cs
index 626eee8..974ef8d 100644
--- a/Source/A2B/Components/BeltComponent.cs
+++ b/Source/A2B/Components/BeltComponent.cs
@@ -121,8 +121,12 @@ public virtual IntVec3 GetDestinationForThing([NotNull] Thing thing)
public virtual bool CanAcceptFrom( BeltComponent belt, bool onlyCheckConnection = false )
{
// If I can't accept from anyone, I certainly can't accept from you.
- if( !onlyCheckConnection && !CanAcceptSomething() )
- return false;
+ /*
+ if( !onlyCheckConnection )
+ foreach( var thing in belt.ItemContainer.ThingsToMove )
+ if( !CanAcceptThing( thing ) )
+ return false;
+ */
// This belt isn't on the other belts output level
if( belt.OutputLevel != this.InputLevel )
@@ -152,16 +156,39 @@ public virtual bool CanAcceptFrom(Rot4 direction)
* Returns whether the component can accept items at all. Useful for locking/disabling components without
* messing with directional routing code.
**/
- public virtual bool CanAcceptSomething()
+ public virtual bool CanAcceptThing( Thing thing )
{
- return (Empty && BeltPhase == Phase.Active);
+ if( BeltPhase != Phase.Active )
+ return false;
+ if( Empty )
+ return true;
+ foreach( var item in ItemContainer.ThingStatus )
+ {
+ if(
+ ( item.Status == MovementStatus.WaitClear )&&
+ ( item.Thing.def == thing.def )&&
+ ( item.Thing.stackCount < item.Thing.def.stackLimit )
+ )
+ {
+ item.Status = MovementStatus.WaitMerge;
+ return true;
+ }
+ if(
+ ( item.Status == MovementStatus.WaitMerge )&&
+ ( item.Merge == thing )
+ )
+ {
+ return true;
+ }
+ }
+ return false;
}
/**
* Returns whether the component is allowed to output to anything other than a belt. Most can not - the unloader
* is an example of one that can, however.
**/
- public virtual bool CanOutputToNonBelt()
+ public virtual bool CanOutputToNonBelt( IntVec3 beltDest, Thing thing )
{
return false;
}
@@ -171,17 +198,17 @@ protected virtual void MoveThingTo([NotNull] Thing thing, IntVec3 beltDest)
{
OnBeginMove(thing, beltDest);
- if( CanOutputToNonBelt() && beltDest.NoStorageBlockersIn( thing ) )
+ if( CanOutputToNonBelt( beltDest, thing ) && beltDest.NoStorageBlockersIn( thing ) )
{
ItemContainer.DropItem(thing, beltDest);
}
else if ( OutputLevel == Level.Surface )
{
// Find a belt component at our output level
- var belt = beltDest.GetBeltComponent();
+ var belt = beltDest.GetBeltSurfaceComponent();
- // Check if there is a belt, if it is empty, and also check if it is active !
- if (belt == null || !belt.ItemContainer.Empty || belt.BeltPhase != Phase.Active)
+ // Check if there is a belt, if it can accept this thing
+ if( belt == null || !belt.CanAcceptThing( thing ) )
{
return;
}
@@ -197,6 +224,7 @@ protected virtual void MoveThingTo([NotNull] Thing thing, IntVec3 beltDest)
#region Drawing Stuff
+ /*
protected static void DrawGUIOverlay([NotNull] ThingStatus status, Vector3 drawPos )
{
if( Find.CameraMap.CurrentZoom != CameraZoomRange.Closest )
@@ -227,7 +255,7 @@ protected static void DrawGUIOverlay([NotNull] ThingStatus status, Vector3 drawP
labelText,
Color.white );
- }
+ }*/
protected virtual Vector3 GetOffset([NotNull] ThingStatus status)
{
@@ -279,11 +307,11 @@ protected virtual Vector3 GetOffset([NotNull] ThingStatus status)
#region Callbacks (Core)
- public override void PostDestroy(DestroyMode mode = DestroyMode.Vanish)
+ public override void PostDeSpawn ()
{
ItemContainer.Destroy();
- base.PostDestroy(mode);
+ base.PostDeSpawn();
}
public override void PostSpawnSetup()
@@ -321,7 +349,7 @@ public override void PostDraw()
status.Thing.DrawAt(drawPos);
- DrawGUIOverlay(status, drawPos);
+ //DrawGUIOverlay(status, drawPos);
}
}
@@ -329,10 +357,10 @@ public override void CompTick()
{
base.CompTick();
- if ((Find.TickManager.TicksGame + GetHashCode()) % 250 == 0)
+ if( parent.IsHashIntervalTick( 250 ) )
ItemContainer.TickRare();
- if ((Find.TickManager.TicksGame + GetHashCode()) % A2BData.OccasionalTicks == 0)
+ if( parent.IsHashIntervalTick( A2BData.OccasionalTicks ) )
OnOccasionalTick();
if (BeltPhase == Phase.Frozen && Rand.Range(0.0f, 1.0f) < 0.05)
@@ -417,7 +445,7 @@ private void DoBeltTick()
// Turn on, incl. 'system online' glow
_beltPhase = Phase.Active;
if( GlowerComponent != null )
- GlowerComponent.Lit = true;
+ GlowerComponent.UpdateLit();
// If it's an underground belt, don't auto-pickup
// as it has lost it's targeting vector
@@ -448,9 +476,9 @@ private void DoBeltTick()
// Active 'yellow' color
if( GlowerComponent != null )
- GlowerComponent.Lit = true; // in principle not required (should be already ON ...)
+ GlowerComponent.UpdateLit(); // in principle not required (should be already ON ...)
- ItemContainer.Tick();
+ ItemContainer.MoveTick();
PostItemContainerTick();
@@ -480,7 +508,7 @@ private void DoBeltTick()
// Turn glower off
if( GlowerComponent != null )
- GlowerComponent.Lit = false;
+ GlowerComponent.UpdateLit();
// Phase, inactive
_beltPhase = Phase.Offline;
@@ -496,6 +524,29 @@ private void DoBeltTick()
}
}
+ public virtual bool MovingThings()
+ {
+ return ItemContainer.MovingThings();
+ }
+
+ #region Power Stuff
+
+ public virtual bool AllowLowPowerMode()
+ {
+ return true;
+ }
+
+ public virtual float GetBasePowerConsumption()
+ {
+ if( PowerComponent == null )
+ {
+ return 0f;
+ }
+ return PowerComponent.Props.basePowerConsumption;
+ }
+
+ #endregion
+
#region Reliability Stuff
public virtual void DoJamCheck()
@@ -557,7 +608,7 @@ public override string CompInspectStringExtra()
return statusText
+ "\n"
+ Constants.TxtContents.Translate()
- + " " + ((IThingContainerOwner) ItemContainer).GetContainer().ContentsString;
+ + " " + ItemContainer.ContentsString;
}
}
}
diff --git a/Source/A2B/Components/BeltItemContainer.cs b/Source/A2B/Components/BeltItemContainer.cs
index 265303a..1dad3c8 100644
--- a/Source/A2B/Components/BeltItemContainer.cs
+++ b/Source/A2B/Components/BeltItemContainer.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Text;
using A2B.Annotations;
using RimWorld;
using Verse;
@@ -12,25 +13,81 @@
namespace A2B
{
- public class ThingStatus
+ public enum MovementStatus
{
- public ThingStatus([NotNull] Thing thing, int counter)
+ Undefined,
+ Moving,
+ WaitClear,
+ WaitMerge,
+ MergingIn,
+ MergingOut
+ }
+
+ public class ThingStatus : IExposable
+ {
+ public ThingStatus([NotNull] Thing thing, int counter, MovementStatus status)
{
Thing = thing;
Counter = counter;
+ Status = status;
+ Merge = null;
+ }
+
+ public ThingStatus()
+ {
+ Thing = null;
+ Counter = 0;
+ Status = MovementStatus.Undefined;
+ Merge = null;
+ }
+
+ public void ExposeData()
+ {
+ var t = Thing;
+ var c = Counter;
+ var s = Status;
+ var m = Merge;
+ Scribe_Values.LookValue( ref c, "counter" );
+ Scribe_Values.LookValue( ref s, "status" );
+ Scribe_References.LookReference( ref m, "merge" );
+ Scribe_Deep.LookDeep( ref t, "thing" );
+ Thing = t;
+ Counter = c;
+ Status = s;
+ Merge = m;
+ }
+
+ public bool IsWaiting
+ {
+ get
+ {
+ if(
+ ( Status == MovementStatus.WaitClear )||
+ ( Status == MovementStatus.WaitMerge )
+ )
+ return true;
+ return false;
+ }
}
[NotNull]
public Thing Thing { get; private set; }
- public int Counter { get; private set; }
+ public int Counter { get; set; }
+
+ public MovementStatus Status { get; set; }
+
+ public Thing Merge { get; set; }
+
}
public class BeltItemContainer : IExposable, IThingContainerOwner
{
private readonly BeltComponent _parentComponent;
- private readonly Dictionary _thingCounter;
+ private List _thingStatus;
+
+ //private readonly Dictionary _thingCount;
private ThingContainer _container;
@@ -40,7 +97,7 @@ static BeltItemContainer()
}
private static int cycle = 0;
- public static bool DoAtmosphereEffects()
+ public static bool DoAtmosphereEffects( object target )
{
int cells = (int) (Find.Map.Area * 0.0006f);
@@ -49,7 +106,7 @@ public static bool DoAtmosphereEffects()
cycle = 0;
var cell = MapCellsInRandomOrder.Get(cycle++);
- var belt = cell.GetBeltComponent();
+ var belt = cell.GetBeltSurfaceComponent();
if (belt != null) {
belt.ItemContainer.AtmosphereEffectsTick();
@@ -63,30 +120,37 @@ public BeltItemContainer([NotNull] BeltComponent component)
{
_parentComponent = component;
+ _thingStatus = new List();
+
_container = new ThingContainer(this);
- _thingCounter = new Dictionary();
+
+ //_thingCount = new Dictionary();
}
[NotNull]
public IEnumerable Contents
{
- get { return _container; }
+ //get { return _container; }
+ get { return _thingStatus.Select( s => s.Thing ).ToList(); }
}
[NotNull]
public IEnumerable ThingsToMove
{
- get { return _thingCounter.Where(pair => pair.Value >= TicksToMove).Select(pair => pair.Key).ToList(); }
+ //get { return _thingCount.Where(pair => pair.Value >= TicksToMove).Select(pair => pair.Key).ToList(); }
+ get { return _thingStatus.Where( s => ( !s.IsWaiting )&&( s.Counter >= TicksToMove ) ).Select( s => s.Thing ).ToList(); }
}
public bool WorkToDo
{
- get { return _thingCounter.Any(pair => pair.Value >= TicksToMove); }
+ //get { return _thingCount.Any(pair => pair.Value >= TicksToMove); }
+ get { return _thingStatus.Any( s => !s.IsWaiting ); }
}
public bool Empty
{
- get { return _container.Count < 1 ; }
+ //get { return _container.Count < 1 ; }
+ get { return _thingStatus.Count < 1; }
}
public int TicksToMove {
@@ -96,13 +160,25 @@ public bool Empty
[NotNull]
public IEnumerable ThingStatus
{
- get { return _container.Select(thing => new ThingStatus(thing, _thingCounter[thing])); }
+ //get { return _container.Select(thing => new ThingStatus(thing, _thingCount[thing])); }
+ get { return _thingStatus; }
}
#region Saveable Members
public void ExposeData()
{
+ Scribe_Collections.LookList( ref _thingStatus, "contents", LookMode.Deep );
+
+ if(
+ ( Scribe.mode == LoadSaveMode.LoadingVars )&&
+ ( _thingStatus == null )
+ )
+ {
+ _thingStatus = new List();
+ }
+
+ /*
Scribe_Deep.LookDeep(ref _container, "container");
if (Scribe.mode == LoadSaveMode.LoadingVars)
@@ -110,7 +186,7 @@ public void ExposeData()
Dictionary counterDictionary = null;
Scribe_Fixed.LookDictionary(ref counterDictionary, "thingCounter", LookMode.Value);
- _thingCounter.Clear();
+ _thingCount.Clear();
if (counterDictionary != null)
{
foreach (var pair in counterDictionary)
@@ -119,23 +195,45 @@ public void ExposeData()
if (thing != null)
{
- _thingCounter.Add(thing, pair.Value);
+ _thingCount.Add(thing, pair.Value);
}
}
}
}
else if (Scribe.mode == LoadSaveMode.Saving)
{
- var counterDictionary = _thingCounter.ToDictionary(pair => pair.Key.ThingID, pair => pair.Value);
+ var counterDictionary = _thingCount.ToDictionary(pair => pair.Key.ThingID, pair => pair.Value);
Scribe_Fixed.LookDictionary(ref counterDictionary, "thingCounter", LookMode.Value);
}
+ */
}
#endregion
#region ThingContainerOwner Members
+ public string ContentsString
+ {
+ get
+ {
+ if( _thingStatus.Count == 0 )
+ return "NothingLower".Translate();
+ StringBuilder stringBuilder = new StringBuilder();
+ for( int index = 0; index < _thingStatus.Count; ++index )
+ {
+ if( index != 0 )
+ stringBuilder.Append( ", " );
+ stringBuilder.Append( _thingStatus[ index ].Thing.Label );
+ #if DEBUG
+ stringBuilder.Append( " " + _thingStatus[ index ].Status );
+ stringBuilder.Append( " " + _thingStatus[ index ].Counter );
+ #endif
+ }
+ return stringBuilder.ToString();
+ }
+ }
+
[NotNull]
ThingContainer IThingContainerOwner.GetContainer()
{
@@ -147,15 +245,183 @@ IntVec3 IThingContainerOwner.GetPosition()
{
return _parentComponent.parent.PositionHeld;
}
+
+ [NotNull]
+ bool IThingContainerOwner.Spawned
+ {
+ get
+ {
+ return this._parentComponent.parent.Spawned;
+ }
+ }
+
#endregion
- public void Tick()
+ public bool MovingThings()
+ {
+ return _thingStatus.Count( s => !s.IsWaiting ) > 0 ;
+ }
+
+ public void MoveTick()
{
- _container.ThingContainerTick();
+ if( _parentComponent.AllowLowPowerMode() )
+ {
+ if( _parentComponent.MovingThings() )
+ {
+ _parentComponent.PowerComponent.PowerOutput = -_parentComponent.GetBasePowerConsumption();
+ }
+ else
+ {
+ _parentComponent.PowerComponent.PowerOutput = -_parentComponent.GetBasePowerConsumption() * A2BData.LowPowerFactor;
+ }
+ }
+
+ foreach( var thingStatus in _thingStatus.Where(ShouldIncreaseCounter))
+ {
+ thingStatus.Counter++;
+ }
+
+ if( !_parentComponent.parent.IsHashIntervalTick( 30 ) )
+ {
+ // Only do a status update twice per second
+ return;
+ }
- foreach (var thing in Contents.Where(ShouldIncreaseCounter))
+ for( int index = _thingStatus.Count - 1; index >= 0; --index )
{
- _thingCounter[thing]++;
+ var thingStatus = _thingStatus[ index ];
+
+ if( thingStatus.Status == MovementStatus.Moving )
+ {
+ // Item it moving
+ if( thingStatus.Counter >= TicksToMove / 2 )
+ {
+ // It's at least half way, get destination for item
+ var destination = _parentComponent.GetDestinationForThing( thingStatus.Thing );
+ var belt = destination.GetBeltComponent( _parentComponent );
+ if(
+ (
+ ( belt != null )&&
+ ( !belt.Empty )
+ )||
+ (
+ ( belt == null )&&
+ (
+ ( !_parentComponent.CanOutputToNonBelt( destination, thingStatus.Thing ) )||
+ ( !destination.NoStorageBlockersIn( thingStatus.Thing ) )
+ )
+ )
+ )
+ {
+ // Belt isn't empty or no belt and can't output to non-belt or non-belt is blocked
+ thingStatus.Status = MovementStatus.WaitClear;
+ }
+ }
+ }
+ else if( thingStatus.Status == MovementStatus.MergingIn )
+ {
+ var mergeStatus = GetWaitMerge();
+ if(
+ ( mergeStatus != null )&&
+ ( mergeStatus.Merge == thingStatus.Thing )&&
+ ( thingStatus.Merge == mergeStatus.Thing )
+ )
+ {
+ // Merging item into existing stack when it reaches it
+ if( thingStatus.Counter >= mergeStatus.Counter )
+ {
+ // Try absorb incoming stack
+ if( mergeStatus.Thing.TryAbsorbStack( thingStatus.Thing, true ) )
+ {
+ // Merged stacks, change status of waiting stack
+ mergeStatus.Merge = null;
+ mergeStatus.Status = MovementStatus.WaitClear;
+ _thingStatus.Remove( thingStatus );
+ break;
+ }
+ // Make the left-overs(!?) wait
+ thingStatus.Merge = null;
+ thingStatus.Status = MovementStatus.WaitClear;
+ }
+ }
+ else
+ {
+ // Could find merge wait?
+ Log.Error( string.Format( "Merge source {0} ({1}) does not match merge target {2} ({3})!", thingStatus.Thing.ThingID, thingStatus.Merge?.ThingID, mergeStatus.Thing.ThingID, mergeStatus.Merge?.ThingID ) );
+ thingStatus.Status = MovementStatus.WaitClear;
+ }
+ }
+ else if( thingStatus.Status == MovementStatus.WaitClear )
+ {
+ if( !MovingThings() )
+ {
+ // Nothing moving on this belt
+
+ // Get destination for thing
+ var destination = _parentComponent.GetDestinationForThing( thingStatus.Thing );
+ var belt = destination.GetBeltComponent( _parentComponent );
+ if(
+ ( belt != null )&&
+ ( belt.CanAcceptThing( thingStatus.Thing ) )
+ )
+ {
+ if( belt.Empty )
+ {
+ // Next belt is ready
+ thingStatus.Status = MovementStatus.Moving;
+ }
+ else
+ {
+ var mergeStatus = belt.ItemContainer.GetWaitMerge();
+ if(
+ ( mergeStatus.Merge == null )&&
+ ( belt.ItemContainer.GetWantedDef() == thingStatus.Thing.def )
+ )
+ {
+ // Merge this with the next belts stack
+
+ var count = belt.ItemContainer.GetWantedCount();
+ if( thingStatus.Thing.stackCount > count )
+ {
+ // Split the off the amount needed
+ var newStack = thingStatus.Thing.SplitOff( count );
+ if( newStack != null )
+ {
+ AddItem( newStack, thingStatus.Counter, MovementStatus.MergingOut, mergeStatus.Thing );
+ mergeStatus.Merge = newStack;
+ }
+ }
+ else
+ {
+ // Merge whole stack
+ mergeStatus.Merge = thingStatus.Thing;
+ thingStatus.Merge = mergeStatus.Thing;
+ thingStatus.Status = MovementStatus.MergingOut;
+ }
+ break;
+ }
+ }
+ }
+ else if(
+ ( belt == null )&&
+ ( _parentComponent.CanOutputToNonBelt( destination, thingStatus.Thing ) )&&
+ ( destination.NoStorageBlockersIn( thingStatus.Thing ) )
+ )
+ {
+ // Dumping on floor which is now clear
+ thingStatus.Status = MovementStatus.Moving;
+ }
+ }
+ }
+ else if( thingStatus.Status == MovementStatus.WaitMerge )
+ {
+ // Waiting for something to come in
+ if( thingStatus.Merge == null )
+ {
+ // No source for merge???
+ thingStatus.Status = MovementStatus.WaitClear;
+ }
+ }
}
}
@@ -167,80 +433,153 @@ public void AtmosphereEffectsTick()
}
}
+ #region Tickers for items on the belt
+
+ public void Tick()
+ {
+ for( int index = _thingStatus.Count - 1; index >= 0; --index )
+ {
+ if( _thingStatus[ index ].Thing.def.tickerType == TickerType.Normal )
+ _thingStatus[ index ].Thing.Tick();
+ }
+ }
+
// We still want items to rot while sitting on the belts, but ThingContainer doesn't call
// TickRare on its contents, which is where the rotting mechanic takes place.
public void TickRare()
{
- foreach (var thing in Contents.ToList()) {
- if (thing.def.tickerType == TickerType.Rare)
- thing.TickRare();
+ for( int index = _thingStatus.Count - 1; index >= 0; --index )
+ {
+ if( _thingStatus[ index ].Thing.def.tickerType == TickerType.Rare )
+ _thingStatus[ index ].Thing.TickRare();
}
}
- private bool ShouldIncreaseCounter([NotNull] Thing thing)
+ #endregion
+
+ public ThingStatus GetStatusForThing( [NotNull] Thing thing )
{
- var currentCounter = _thingCounter[thing];
- if (currentCounter < TicksToMove / 2 )//&& !_parentComponent.IsReceiver())
+ foreach( var thingStatus in _thingStatus )
{
- // Always increase the counter until half the belt speed is reached
- return true;
+ if( thingStatus.Thing == thing )
+ return thingStatus;
}
+ return null;
+ }
- // Never go above 100%
- if (currentCounter >= TicksToMove)
+ private ThingStatus GetWaitMerge()
+ {
+ foreach( var thingStatus in _thingStatus )
{
- return false;
+ if( thingStatus.Status == MovementStatus.WaitMerge )
+ {
+ return thingStatus;
+ }
}
+ return null;
+ }
- var destination = _parentComponent.GetDestinationForThing(thing);
- BeltComponent belt = null;
+ private int GetWantedCount()
+ {
+ if( _thingStatus.Count < 1 )
+ {
+ return 0;
+ }
+ var thingStatus = GetWaitMerge();
+ if( thingStatus != null )
+ {
+ return thingStatus.Thing.def.stackLimit - thingStatus.Thing.stackCount;
+ }
+ return 0;
+ }
- if( _parentComponent.OutputLevel == Level.Surface )
+ private ThingDef GetWantedDef()
+ {
+ if( _thingStatus.Count < 1 )
+ {
+ return null;
+ }
+ var thingStatus = GetWaitMerge();
+ if( thingStatus != null )
{
- // Surface belts get the fast treatment
+ return thingStatus.Thing.def;
+ }
+ return null;
+ }
- belt = destination.GetBeltComponent();
+ private bool ShouldIncreaseCounter([NotNull] ThingStatus thingStatus)
+ {
+ if( thingStatus.IsWaiting )
+ {
+ return false;
+ }
- } else {
- // Underground belts need more robust checking to handle strange configurations
- var belts = destination.GetBeltUndergroundComponents();
+ if( thingStatus.Counter < TicksToMove / 2 )//&& !_parentComponent.IsReceiver())
+ {
+ // Always increase the counter until half the belt speed is reached
+ return true;
+ }
- // Scan for prefered belt (lift) otherwise continue underground
- if( ( belts != null )&&
- ( belts.Count > 0 ) )
- {
+ // Never go above 100%
+ if( thingStatus.Counter >= TicksToMove )
+ {
+ return false;
+ }
- var p = _parentComponent as BeltUndergroundComponent;
- var lift = belts.Find( b => b.IsLift() && b.CanAcceptFrom( _parentComponent ) );
- var under = belts.Find( b => b.IsUndercover() );
- if( ( lift != null )&&
- ( ( lift.BeltPhase == Phase.Active )||
- ( under == null ) ) )
- belt = lift;
- else
- belt = under;
-
- }
+ if( thingStatus.Status == MovementStatus.MergingIn )
+ {
+ // Keep moving item until it merges with it's target
+ return true;
}
+ // Get destination for thing
+ var destination = _parentComponent.GetDestinationForThing( thingStatus.Thing );
+ var belt = destination.GetBeltComponent( _parentComponent );
+
// If no belt items, then move things only if this can output to non-belts
if (belt == null)
{
- return (_parentComponent.CanOutputToNonBelt() && destination.NoStorageBlockersIn(thing));
+ return (_parentComponent.CanOutputToNonBelt( destination, thingStatus.Thing ) && destination.NoStorageBlockersIn( thingStatus.Thing ));
}
// There is a belt, only move things if it can accept them from us
- return belt.CanAcceptFrom(_parentComponent);
+ if( !belt.CanAcceptFrom( _parentComponent, true ) )
+ return false;
+
+ // An empty belt accepts all
+ if( belt.Empty )
+ return true;
+
+ // Only move the stack if the next belt wants it
+ ThingDef wantedDef = belt.ItemContainer.GetWantedDef();
+ return wantedDef == thingStatus.Thing.def;
}
- public bool AddItem([NotNull] Thing t, int initialCounter = 0)
+ public bool AddItem([NotNull] Thing t, int initialCounter = 0, MovementStatus initialStatus = MovementStatus.Moving, Thing mergeTarget = null )
{
+ var thingStatus = new ThingStatus( t, initialCounter, initialStatus );
+ if( thingStatus == null )
+ return false;
+
+ thingStatus.Merge = mergeTarget;
+ _thingStatus.Add( thingStatus );
+
+ SlotGroupUtility.Notify_TakingThing( t );
+ if( t.Spawned )
+ t.DeSpawn();
+ if( t.HasAttachment(ThingDefOf.Fire ) )
+ t.GetAttachment(ThingDefOf.Fire ).Destroy( DestroyMode.Vanish );
+
+ t.holder = _container;
+
+ /*
if (!_container.TryAdd(t))
{
return false;
}
- _thingCounter[t] = initialCounter;
+ _thingCount[t] = initialCounter;
+ */
return true;
}
@@ -249,14 +588,54 @@ public void TransferItem([NotNull] Thing item, [NotNull] BeltItemContainer other
if (!_parentComponent.PreItemTransfer(item, other._parentComponent))
return;
- _container.Remove(item);
- _thingCounter.Remove(item);
- other.AddItem(item);
+ var thingStatus = GetStatusForThing( item );
+ _thingStatus.Remove( thingStatus );
+
+ if( thingStatus.Status == MovementStatus.MergingOut )
+ {
+ thingStatus.Status = MovementStatus.MergingIn;
+ }
+ other.AddItem( item, 0, thingStatus.Status, thingStatus.Merge );
_parentComponent.OnItemTransfer(item, other._parentComponent);
other._parentComponent.OnItemReceived(item, _parentComponent);
}
+ private bool TryDrop( ThingStatus thingStatus, IntVec3 dropLoc, ThingPlaceMode mode, out Thing lastResultingThing )
+ {
+ lastResultingThing = null;
+ if(
+ ( thingStatus == null )||
+ ( thingStatus.Thing == null )
+ )
+ {
+ return false;
+ }
+ if( thingStatus.Merge != null )
+ {
+ // Make sure any items which are merging release their lock on their target
+ var belt = thingStatus.Merge.PositionHeld.GetBeltComponent( this._parentComponent );
+ if( belt == null )
+ {
+ Log.Error( string.Format( "Can not find belt for merge target {0}!", thingStatus.Merge ) );
+ }
+ else
+ {
+ var mergeStatus = belt.ItemContainer.GetStatusForThing( thingStatus.Merge );
+ if( mergeStatus == null )
+ {
+ Log.Error( string.Format( "Can not get ThingStatus for merge target {0} from belt {1}!", thingStatus.Merge, belt.parent ) );
+ }
+ else
+ {
+ mergeStatus.Merge = null;
+ mergeStatus.Status = MovementStatus.WaitClear;
+ }
+ }
+ }
+ return GenDrop.TryDropSpawn( thingStatus.Thing, dropLoc, mode, out lastResultingThing );
+ }
+
public void DropItem([NotNull] Thing item, IntVec3 position, bool forced = false)
{
var backupSound = item.def.soundDrop;
@@ -265,40 +644,54 @@ public void DropItem([NotNull] Thing item, IntVec3 position, bool forced = false
{
item.def.soundDrop = null;
- if (!_container.Contains(item))
+ var thingStatus = GetStatusForThing( item );
+ if( thingStatus == null )
+ {
+ Log.Message( string.Format( "Unable to find ThingStatus for {0} in {1}!", item, _parentComponent.parent ) );
return;
+ }
Thing droppedItem;
- if (!_container.TryDrop(item, position, ThingPlaceMode.Direct, out droppedItem) && !forced)
- {
- return;
+ if( !forced )
+ {
+ if( !TryDrop( thingStatus, position, ThingPlaceMode.Direct, out droppedItem ) )
+ {
+ Log.Message( string.Format( "Unable to drop {0} at {1}!", thingStatus.Thing, position ) );
+ }
}
// Might prevent those "has null owner" errors...
- else if (forced && _container.Contains(item) && !_container.TryDrop(item, position, ThingPlaceMode.Near, out droppedItem))
+ else if( !TryDrop( thingStatus, position, ThingPlaceMode.Near, out droppedItem ) )
{
- _container.Remove(item);
- item.holder = null;
- return;
+ Log.Message( string.Format( "Unable to drop {0} near {1}!", thingStatus.Thing, position ) );
}
+ _thingStatus.Remove( thingStatus );
- // Play the sound as that isn't handled by the ThingContainer anymore...
- if (backupSound != null)
+ if( droppedItem == null )
{
- backupSound.PlayOneShot(position);
+ return;
}
- _thingCounter.Remove(item);
- item.holder = null;
+ droppedItem.holder = null;
- if (droppedItem is ThingWithComps)
+ // Play the drop sound
+ if( backupSound != null )
{
- droppedItem.SetForbidden(false);
+ backupSound.PlayOneShot( position );
+ droppedItem.def.soundDrop = backupSound;
}
- if (droppedItem.def.defName.Contains("Chunk") && Find.DesignationManager.DesignationOn(droppedItem, DesignationDefOf.Haul) == null)
+ if( droppedItem is ThingWithComps )
+ {
+ droppedItem.SetForbidden( false );
+ }
+
+ if(
+ ( droppedItem.def.defName.Contains( "Chunk" ) )&&
+ ( Find.DesignationManager.DesignationOn( droppedItem, DesignationDefOf.Haul ) == null )
+ )
{
// If this is a chunk AND not already haulable ("designated twice" warning) make it haulable
- Find.DesignationManager.AddDesignation(new Designation(droppedItem, DesignationDefOf.Haul));
+ Find.DesignationManager.AddDesignation( new Designation( droppedItem, DesignationDefOf.Haul ) );
}
}
finally
@@ -311,18 +704,27 @@ public void DropItem([NotNull] Thing item, IntVec3 position, bool forced = false
public void DropAll(IntVec3 position, bool forced = false)
{
// Check if there is anything on the belt: yes? -> make it accessible to colonists
+ for( int index = _thingStatus.Count - 1; index >= 0; index-- )
+ {
+ var thingStatus = _thingStatus[ index ];
+ DropItem( thingStatus.Thing, position, forced );
+ }
+ if( _thingStatus.Count > 0 )
+ Log.Error( "A2B: Tried DropAll but items remain!" );
+ /*
foreach (var thing in _container.ToList())
{
DropItem(thing, position, forced);
}
- _thingCounter.Clear();
+ _thingCount.Clear();
+ */
}
public void Destroy()
{
DropAll(_parentComponent.parent.Position, true);
- _container.ClearAndDestroyContents();
+ //_container.ClearAndDestroyContents();
}
}
}
diff --git a/Source/A2B/Components/BeltLiftComponent.cs b/Source/A2B/Components/BeltLiftComponent.cs
index bf9f2cf..4f88911 100644
--- a/Source/A2B/Components/BeltLiftComponent.cs
+++ b/Source/A2B/Components/BeltLiftComponent.cs
@@ -42,6 +42,37 @@ public override void PostExposeData()
}
}
+ public override float GetBasePowerConsumption()
+ {
+ if( PowerComponent == null )
+ {
+ return 0f;
+ }
+ // Powered lifts use additional power based
+ // on how many components it's driving
+ return PowerComponent.Props.basePowerConsumption + poweredCount * A2BData.PowerPerUndercover;
+ }
+
+ public override bool MovingThings()
+ {
+ // Is the lift itself moving an item?
+ if( ItemContainer.MovingThings() )
+ {
+ return true;
+ }
+ if( poweredBelts.NullOrEmpty() )
+ return false;
+
+ // Check all the undercovers the lift is pulling, don't include slides in the scan
+ foreach( var undercover in poweredBelts.FindAll( b => b is BeltUndercoverComponent ) )
+ {
+ if( undercover.MovingThings() )
+ {
+ return true;
+ }
+ }
+ return false;
+ }
public override void OnItemTransfer(Thing item, BeltComponent other)
{
@@ -65,10 +96,10 @@ protected override void MoveThingTo([NotNull] Thing thing, IntVec3 beltDest)
OnBeginMove(thing, beltDest);
// Lifts only output to surface
- var belt = beltDest.GetBeltComponent();
+ var belt = beltDest.GetBeltSurfaceComponent();
- // Check if there is a belt, if it is empty, and also check if it is active !
- if (belt == null || !belt.ItemContainer.Empty || belt.BeltPhase != Phase.Active)
+ // Check if there is a belt, if it can accept this thing
+ if( belt == null || !belt.CanAcceptThing( thing ) )
{
return;
}
diff --git a/Source/A2B/Components/BeltLoaderComponent.cs b/Source/A2B/Components/BeltLoaderComponent.cs
index b384436..f1aad1d 100644
--- a/Source/A2B/Components/BeltLoaderComponent.cs
+++ b/Source/A2B/Components/BeltLoaderComponent.cs
@@ -55,7 +55,7 @@ public override void Jam()
/**
* Belt loaders never accept items from other belt components.
**/
- public override bool CanAcceptSomething()
+ public override bool CanAcceptThing( Thing thing )
{
return false;
}
@@ -65,25 +65,46 @@ protected override void PostItemContainerTick()
// Check the things that are on the ground at our position
// If the thing can be moved and the destination is empty it can be added to our container
// This should fix the "pawn carry items to the loader all the time"-bug
- foreach (var thing in Find.ThingGrid.ThingsAt(parent.Position))
+ var thingsAt = Find.ThingGrid.ThingsAt( parent.Position ).ToList();
+ for( var index = thingsAt.Count - 1; index >= 0; index-- )
{
- if ((thing.def.category == ThingCategory.Item) && (thing != parent))
+ var thing = thingsAt[ index ];
+ if(
+ ( thing.def.category == ThingCategory.Item )&&
+ ( thing != parent )
+ )
{
- var destination = GetDestinationForThing(thing);
- var destBelt = destination.GetBeltComponent();
+ var destination = GetDestinationForThing( thing );
+ var destBelt = destination.GetBeltSurfaceComponent();
- if (destBelt == null)
+ if( destBelt == null )
{
continue;
}
// Do not load items unless the next element can accept it
- if (!destBelt.CanAcceptFrom(this))
+ if( !destBelt.CanAcceptFrom( this ) )
{
continue;
}
- ItemContainer.AddItem(thing, BeltSpeed / 2);
+ // Try to merge with existing stacks
+ bool fullyMerged = false;
+ foreach( var thingStatus in ItemContainer.ThingStatus.Where( status => status.IsWaiting ) )
+ {
+ if( thingStatus.Thing.def == thing.def )
+ {
+ if( thingStatus.Thing.TryAbsorbStack( thing, true ) )
+ {
+ fullyMerged = true;
+ break;
+ }
+ }
+ }
+
+ // If not fully merged, add the remaining stack
+ if( !fullyMerged )
+ ItemContainer.AddItem( thing, BeltSpeed / 2 );
}
}
}
diff --git a/Source/A2B/Components/BeltSelectorComponent.cs b/Source/A2B/Components/BeltSelectorComponent.cs
index 6bbe020..8070a7d 100644
--- a/Source/A2B/Components/BeltSelectorComponent.cs
+++ b/Source/A2B/Components/BeltSelectorComponent.cs
@@ -1,98 +1,285 @@
using System;
+using System.Collections.Generic;
+
using RimWorld;
using Verse;
+using UnityEngine;
namespace A2B
{
public class BeltSelectorComponent : BeltComponent
{
- protected Rot4 nextDest = Rot4.West;
+ protected ISlotGroupParent slotParent;
+
protected bool hasStorageSettings;
protected string _mythingID;
- protected IntVec3 _splitterDest;
+
+ protected Rot4[] inputVectors;
+ protected Rot4[] outputOneVectors;
+ protected Rot4[] outputTwoVectors;
+
+ protected bool allowOutputOneToGround = false;
+ protected bool allowOutputTwoToGround = false;
+
+ protected IntVec3[] inputPos;
+ protected IntVec3[] outputOnePos;
+ protected IntVec3[] outputTwoPos;
+
+ protected IntVec3 _lastOnePosition;
+ protected IntVec3 _lastTwoPosition;
public override void PostExposeData()
{
base.PostExposeData();
Scribe_Values.LookValue(ref hasStorageSettings, "hasStorageSettings");
+ Scribe_Values.LookValue(ref allowOutputOneToGround, "allowOutputOneToGround");
+ Scribe_Values.LookValue(ref allowOutputTwoToGround, "allowOutputTwoToGround");
}
public override void PostSpawnSetup()
{
base.PostSpawnSetup();
- ISlotGroupParent slotParent = parent as ISlotGroupParent;
- if (slotParent == null)
+ GetIOVectors();
+
+ inputPos = RelativeRotationToPosition( inputVectors );
+ outputOnePos = RelativeRotationToPosition( outputOneVectors );
+ outputTwoPos = RelativeRotationToPosition( outputTwoVectors );
+
+ _lastOnePosition = outputOnePos[ 0 ];
+ _lastTwoPosition = outputTwoPos[ 0 ];
+
+ slotParent = parent as ISlotGroupParent;
+ if( slotParent == null )
{
throw new InvalidOperationException("parent is not a SlotGroupParent!");
}
// we kinda want to not overwrite custom storage settings every save/load...
- if (!hasStorageSettings)
- slotParent.GetStoreSettings().filter.SetDisallowAll();
+ if( !hasStorageSettings )
+ {
+ // First disallow all
+ slotParent.GetStoreSettings().filter.SetDisallowAll();
+ foreach( var outputOne in outputOnePos )
+ { // Copy from output one vectors if available
+ var slotGroup = outputOne.GetSlotGroup();
+ if( slotGroup != null )
+ {
+ slotParent.GetStoreSettings().CopyFrom( slotGroup.Settings );
+ allowOutputOneToGround = true;
+ break;
+ }
+ }
+ }
hasStorageSettings = true;
}
- public override IntVec3 GetDestinationForThing(Thing thing)
+ private IntVec3[] RelativeRotationToPosition( Rot4[] vectors )
{
- // Test the 'selection' idea ...
- ISlotGroupParent slotParent = parent as ISlotGroupParent;
- if (slotParent == null)
+ int count = vectors.GetLength( 0 );
+ var dests = new IntVec3[ count ];
+ for( int index = 0; index < count; ++index )
{
- throw new InvalidOperationException("parent is not a SlotGroupParent!");
+ dests[ index ] = this.GetPositionFromRelativeRotation( vectors[ index ] );
}
-
- var selectionSettings = slotParent.GetStoreSettings();
- if (selectionSettings.AllowedToAccept(thing))
- return this.GetPositionFromRelativeRotation(Rot4.North);
+ return dests;
+ }
+
+ public virtual void GetIOVectors()
+ {
+ inputVectors = new Rot4[]{ Rot4.South };
+ outputOneVectors = new Rot4[]{ Rot4.North };
+ outputTwoVectors = new Rot4[]{ Rot4.West, Rot4.East };
+ }
- // A list of destinations - indexing modulo 2 lets us cycle them and avoid
- // long chains of if-statements.
- IntVec3[] dests = {
- this.GetPositionFromRelativeRotation(Rot4.West),
- this.GetPositionFromRelativeRotation(Rot4.East)
- };
+ private bool CanOutputToSlotGroup( IntVec3 beltDest, Thing thing )
+ {
+ var slotGroup = beltDest.GetSlotGroup();
+ if( slotGroup == null )
+ return true;
+ return slotGroup.Settings.AllowedToAccept( thing );
+ }
+
+ public override bool CanOutputToNonBelt( IntVec3 beltDest, Thing thing )
+ {
+ if( allowOutputOneToGround )
+ for( int index = 0; index < outputOnePos.GetLength( 0 ); ++index )
+ if( beltDest == outputOnePos[ index ] )
+ return CanOutputToSlotGroup( beltDest, thing );
+ if( allowOutputTwoToGround )
+ for( int index = 0; index < outputTwoPos.GetLength( 0 ); ++index )
+ if( beltDest == outputTwoPos[ index ] )
+ return CanOutputToSlotGroup( beltDest, thing );
+ return false;
+ }
- // Determine where we are going in the destination list (and default to left)
- int index = Math.Max(0, Array.FindIndex(dests, dir => (dir == _splitterDest)));
+ protected virtual IntVec3 GetGroundVector( Thing thing, IntVec3[] vectors, IntVec3 lastVector )
+ {
+ int limit = vectors.GetLength( 0 );
- // Do we have a new item ?
- if (_mythingID == thing.ThingID && IsFreeBelt(_splitterDest))
+ // Same item?
+ if(
+ ( _mythingID == thing.ThingID )&&
+ ( lastVector.NoStorageBlockersIn( thing ) )
+ )
{
- return _splitterDest;
+ return lastVector;
}
- else
- {
- _mythingID = thing.ThingID;
- // Try the next destination
- index = (index + 1) % 2;
- if (IsFreeBelt(dests[index]))
+ // New item
+ _mythingID = thing.ThingID;
+
+ // Vector index
+ int index = Math.Max( 0, Array.FindIndex( vectors, dest => dest == lastVector ) );
+ int lastIndex = index;
+
+ // Try vectors until all have been checked
+ do
+ {
+ // Try next vector
+ index = ( index + 1 ) % limit;
+ if( vectors[ index ].NoStorageBlockersIn( thing ) )
{
- _splitterDest = dests[index];
- return _splitterDest;
+ return vectors[ index ];
}
+ }while( index != lastIndex );
+
+ // Can't find a free one
+ return IntVec3.Invalid;
+ }
+
+ protected virtual IntVec3 GetOutputVector( Thing thing, IntVec3[] vectors, IntVec3 lastVector, bool allowGround )
+ {
+ int limit = vectors.GetLength( 0 );
+
+ // Same item?
+ if(
+ ( _mythingID == thing.ThingID )&&
+ ( IsFreeBelt( lastVector ) )
+ )
+ {
+ return lastVector;
+ }
+
+ // New item
+ _mythingID = thing.ThingID;
- // Try the one after that
- index = (index + 1) % 2;
- if (IsFreeBelt(dests[index]))
+ // Vector index
+ int index = Math.Max( 0, Array.FindIndex( vectors, dest => dest == lastVector ) );
+ int lastIndex = index;
+
+ // Try vectors until all have been checked
+ do
+ {
+ // Try next vector
+ index = ( index + 1 ) % limit;
+ if( IsFreeBelt( vectors[ index ] ) )
{
- _splitterDest = dests[index];
- return _splitterDest;
+ return vectors[ index ];
}
+ }while( index != lastIndex );
+
+ // Can't find a free one
+ if( !allowGround )
+ return IntVec3.Invalid;
+
+ // Check the ground
+ return GetGroundVector( thing, vectors, lastVector );
+ }
- // Give up and use our current destination
- return _splitterDest;
+ public override bool CanAcceptFrom( Rot4 direction )
+ {
+ return Array.Exists( inputVectors, v => v == direction );
+ }
+
+ public override IntVec3 GetDestinationForThing(Thing thing)
+ {
+ // Test the 'selection' idea ...
+ if( slotParent == null )
+ {
+ throw new InvalidOperationException("parent is not a SlotGroupParent!");
}
+
+ IntVec3 destination;
+
+ // Matches filter?
+ var selectionSettings = slotParent.GetStoreSettings();
+ if( selectionSettings.AllowedToAccept( thing ) )
+ {
+ // Send it to the next "1" output
+ destination = GetOutputVector( thing, outputOnePos, _lastOnePosition, allowOutputOneToGround );
+ if( destination != IntVec3.Invalid )
+ _lastOnePosition = destination;
+ return _lastOnePosition;
+ }
+
+ // Doesn't match, send it to the next "2" output
+ destination = GetOutputVector( thing, outputTwoPos, _lastTwoPosition, allowOutputTwoToGround );
+ if( destination != IntVec3.Invalid )
+ _lastTwoPosition = destination;
+ return _lastTwoPosition;
}
- protected bool IsFreeBelt(IntVec3 position)
+ protected bool IsFreeBelt( IntVec3 position )
{
- BeltComponent destBelt = position.GetBeltComponent();
- return (destBelt != null && destBelt.CanAcceptFrom(this));
+ BeltComponent destBelt = position.GetBeltSurfaceComponent();
+ return (
+ ( destBelt != null )&&
+ ( destBelt.CanAcceptFrom( this ) )&&
+ ( destBelt.Empty )
+ );
}
+ public override IEnumerable CompGetGizmosExtra()
+ {
+ // Show gizmo buttons to allow the player to allow outputing directly to the ground
+ Command_Action actionToggleOneToGround = new Command_Action();
+ if( actionToggleOneToGround != null )
+ {
+ if( allowOutputOneToGround )
+ {
+ actionToggleOneToGround.icon = Constants.IconSelectorToGroundTrue;
+ }
+ else
+ {
+ actionToggleOneToGround.icon = Constants.IconSelectorToGroundFalse;
+ }
+ actionToggleOneToGround.defaultDesc = Constants.TxtSelectorToGroundToggleDescription.Translate( "1" );
+ actionToggleOneToGround.defaultLabel = Constants.TxtSelectorToGroundToggle.Translate( "1" );
+ actionToggleOneToGround.activateSound = Constants.ButtonClick;
+ actionToggleOneToGround.action = new Action( delegate()
+ {
+ allowOutputOneToGround = !allowOutputOneToGround;
+ } );
+ }
+ yield return actionToggleOneToGround;
+
+ Command_Action actionToggleTwoToGround = new Command_Action();
+ if( actionToggleTwoToGround != null )
+ {
+ if( allowOutputTwoToGround )
+ {
+ actionToggleTwoToGround.icon = Constants.IconSelectorToGroundTrue;
+ }
+ else
+ {
+ actionToggleTwoToGround.icon = Constants.IconSelectorToGroundFalse;
+ }
+ actionToggleTwoToGround.defaultDesc = Constants.TxtSelectorToGroundToggleDescription.Translate( "2" );
+ actionToggleTwoToGround.defaultLabel = Constants.TxtSelectorToGroundToggle.Translate( "2" );
+ actionToggleTwoToGround.activateSound = Constants.ButtonClick;
+ actionToggleTwoToGround.action = new Action( delegate()
+ {
+ allowOutputTwoToGround = !allowOutputTwoToGround;
+ } );
+ }
+ yield return actionToggleTwoToGround;
+
+ // No more gizmos
+ yield break;
+ }
+
}
}
\ No newline at end of file
diff --git a/Source/A2B/Components/BeltSlideComponent.cs b/Source/A2B/Components/BeltSlideComponent.cs
index 67e75e5..459b239 100644
--- a/Source/A2B/Components/BeltSlideComponent.cs
+++ b/Source/A2B/Components/BeltSlideComponent.cs
@@ -28,6 +28,12 @@ public override void PostSpawnSetup()
_outputLevel = Level.Underground;
}
+ public override bool AllowLowPowerMode()
+ {
+ // Powered lifts will handle this for us
+ return false;
+ }
+
public override IntVec3 GetDestinationForThing( Thing thing )
{
return this.GetPositionFromRelativeRotation( Rot4.North );
@@ -47,16 +53,21 @@ protected override void MoveThingTo([NotNull] Thing thing, IntVec3 beltDest)
var belts = beltDest.GetBeltUndergroundComponents();
var lift = belts.Find( b => b.IsLift() && b.outputDirection == this.outputDirection );
var under = belts.Find( tuc => tuc.IsUndercover() );
- if( ( lift != null )&&
- ( ( lift.BeltPhase == Phase.Active )||
- ( under == null ) ) )
- // Use the lift unless it's unpowered and there is an undercover
+ if(
+ ( lift != null )&&
+ (
+ ( lift.BeltPhase == Phase.Active )||
+ ( under == null )
+ )
+ )
+ { // Use the lift unless it's unpowered and there is an undercover
belt = lift;
+ }
else
belt = under;
- // Check if there is a belt, if it is empty, and also check if it is active !
- if (belt == null || !belt.ItemContainer.Empty || belt.BeltPhase != Phase.Active)
+ // Check if there is a belt, if it can accept this thing
+ if( belt == null || !belt.CanAcceptThing( thing ) )
{
return;
}
diff --git a/Source/A2B/Components/BeltSplitterComponent.cs b/Source/A2B/Components/BeltSplitterComponent.cs
index f0a1ea6..b74b808 100644
--- a/Source/A2B/Components/BeltSplitterComponent.cs
+++ b/Source/A2B/Components/BeltSplitterComponent.cs
@@ -80,7 +80,7 @@ public override IntVec3 GetDestinationForThing(Thing thing)
private bool IsFreeBelt(IntVec3 position, bool onlyCheckConnection = false)
{
- BeltComponent destBelt = position.GetBeltComponent();
+ BeltComponent destBelt = position.GetBeltSurfaceComponent();
return (destBelt != null && destBelt.CanAcceptFrom(this, onlyCheckConnection));
}
diff --git a/Source/A2B/Components/BeltUndercoverComponent.cs b/Source/A2B/Components/BeltUndercoverComponent.cs
index 571bb6b..3bcb99e 100644
--- a/Source/A2B/Components/BeltUndercoverComponent.cs
+++ b/Source/A2B/Components/BeltUndercoverComponent.cs
@@ -51,6 +51,12 @@ public BeltUndercoverComponent ()
get { return ( Cover != null ); }
}
+ public override bool AllowLowPowerMode()
+ {
+ // Powered lifts will handle this for us
+ return false;
+ }
+
public override IntVec3 GetDestinationForThing( Thing thing )
{
// Prefer straight
@@ -60,8 +66,12 @@ public override IntVec3 GetDestinationForThing( Thing thing )
public override bool CanAcceptFrom( BeltComponent belt, bool onlyCheckConnection = false )
{
// If I can't accept from anyone, I certainly can't accept from you.
- if( !onlyCheckConnection && !CanAcceptSomething() )
- return false;
+ /*
+ if( !onlyCheckConnection )
+ foreach( var thing in belt.ItemContainer.ThingsToMove )
+ if( !CanAcceptThing( thing ) )
+ return false;
+ */
// This belt isn't on the other belts output level
if( belt.OutputLevel != this.InputLevel )
@@ -90,15 +100,21 @@ protected override void MoveThingTo([NotNull] Thing thing, IntVec3 beltDest)
var belts = beltDest.GetBeltUndergroundComponents();
var lift = belts.Find( b => b.IsLift() && b.outputDirection == this.outputDirection );
var under = belts.Find( u => u.IsUndercover() );
- if( ( lift != null )&&
- ( ( lift.BeltPhase == Phase.Active )||
- ( under == null ) ) )
+ if(
+ ( lift != null )&&
+ (
+ ( lift.BeltPhase == Phase.Active )||
+ ( under == null )
+ )
+ )
+ {
belt = lift;
+ }
else
belt = under;
- // Check if there is a belt, if it is empty, and also check if it is active !
- if (belt == null || !belt.ItemContainer.Empty || belt.BeltPhase != Phase.Active)
+ // Check if there is a belt, if it can accept this thing
+ if( belt == null || !belt.CanAcceptThing( thing ) )
{
return;
}
@@ -160,7 +176,7 @@ public override void PostDraw()
Graphics.DrawMesh( MeshPool.plane10, thingMatrix, thingMat, 0 );
- DrawGUIOverlay( status, overlayPos );
+ //DrawGUIOverlay( status, overlayPos );
}
// Draw frame
diff --git a/Source/A2B/Components/BeltUndercoverCover.cs b/Source/A2B/Components/BeltUndercoverCover.cs
index 1ceee16..6f4cb29 100644
--- a/Source/A2B/Components/BeltUndercoverCover.cs
+++ b/Source/A2B/Components/BeltUndercoverCover.cs
@@ -42,14 +42,14 @@ public override void PostSpawnSetup()
ParentBelt.CoverWasDestroyed = false;
}
- public override void PostDestroy( DestroyMode mode = DestroyMode.Vanish)
+ public override void PostDestroy( DestroyMode mode, bool wasSpawned )
{
// If we were destroyed, tell our parent undercover belt
if( ( mode == DestroyMode.Kill )&&
( ParentBelt != null ) ){
ParentBelt.CoverWasDestroyed = true;
}
- base.PostDestroy( mode );
+ base.PostDestroy( mode, wasSpawned );
}
}
diff --git a/Source/A2B/Components/BeltUndergroundComponent.cs b/Source/A2B/Components/BeltUndergroundComponent.cs
index 0c3118e..a66c6ab 100644
--- a/Source/A2B/Components/BeltUndergroundComponent.cs
+++ b/Source/A2B/Components/BeltUndergroundComponent.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using A2B.Annotations;
using RimWorld;
using UnityEngine;
@@ -71,13 +72,18 @@ public virtual bool CoverIsOn
get { return true; }
}
+ private bool gameJustLoaded = false;
+
// Belt component of actual power source
+ private string _headParentString = string.Empty;
private Thing _headParent = null;
private BeltUndergroundComponent _powerHead = null;
public BeltUndergroundComponent PowerHead {
get { return _powerHead; }
set { // Only allow set if this belt doesn't have CompPowerTrader
if( value == null ){
+ _headParentString = string.Empty;
+ _beltPhase = Phase.Offline;
_headParent = null;
_powerHead = null;
PowerComponent = null;
@@ -87,6 +93,7 @@ public virtual bool CoverIsOn
_powerHead = value;
_headParent = _powerHead.parent;
PowerComponent = _headParent.TryGetComp();
+ _beltPhase = PowerComponent.PowerOn ? Phase.Active : Phase.Offline;
}
}
}
@@ -98,8 +105,8 @@ public virtual bool CoverIsOn
protected List< BeltUndergroundComponent > poweredBelts = null;
protected int poweredCount
{ // Make sure we only return undercover count, slides require a powered lift but do not draw power
- get { return poweredBelts == null ? 0 :
- poweredBelts.FindAll( b => ( ( b as BeltUndercoverComponent ) != null ) ).Count; }
+ get { return poweredBelts.NullOrEmpty() ? 0 :
+ poweredBelts.FindAll( b => b is BeltUndercoverComponent ).Count; }
}
@@ -110,16 +117,7 @@ public BeltUndergroundComponent()
_outputLevel = Level.Underground;
}
- #region Infered Power Stuff
-
- public void RecomputerPower()
- {
- if( this.IsLift() ){
- // Powered lifts use additional power based
- // on how many components it's driving
- PowerComponent.PowerOutput = -( PowerComponent.props.basePowerConsumption + poweredCount * A2BData.powerPerUndercover );
- }
- }
+ #region Power Stuff
public bool RegisterInferedPowerComponent( BeltUndergroundComponent belt, Rot4 dir )
{
@@ -137,15 +135,17 @@ public bool RegisterInferedPowerComponent( BeltUndergroundCompon
if( belt.MultiVector == true )
belt.outputDirection = dir;
- RecomputerPower();
return true;
}
public bool UnregisterInferedPowerComponent( BeltUndergroundComponent belt )
{
- if( ( poweredBelts == null )||
- ( !poweredBelts.Contains( belt ) ) ){
+ if(
+ ( poweredBelts.NullOrEmpty() )||
+ ( !poweredBelts.Contains( belt ) )
+ )
+ {
return false;
}
@@ -157,7 +157,6 @@ public bool UnregisterInferedPowerComponent( BeltUndergroundComp
belt.outputDirection = Rot4.Invalid;
// Unregistered
- RecomputerPower();
return true;
}
@@ -290,6 +289,42 @@ public override void OnOccasionalTick()
}
}
+ public override void CompTick ()
+ {
+ if( gameJustLoaded )
+ {
+ if( _headParentString != string.Empty )
+ {
+ if( PowerDirection == Rot4.Invalid )
+ {
+ Log.Error( parent.ThingID + " :: PowerDirection is invalid!" );
+ }
+ else
+ {
+ var headThing = Find.ListerThings.AllThings.FirstOrDefault( thing => thing.ThingID == _headParentString );
+ if( headThing == null )
+ {
+ Log.Error( parent.ThingID + " :: Unable to get Thing from ThingID " + _headParentString );
+ }
+ else
+ {
+ var parentBelt = headThing.TryGetComp();
+ if( parentBelt == null )
+ {
+ Log.Error( parent.ThingID + " :: " + _headParentString + " is not a valid underground belt component!" );
+ }
+ else
+ {
+ parentBelt.RegisterInferedPowerComponent( this, PowerDirection );
+ }
+ }
+ }
+ }
+ gameJustLoaded = false;
+ }
+ base.CompTick();
+ }
+
public override void OnItemTransfer(Thing item, BeltComponent other)
{
// Tell the undercover which direction the item came from
@@ -322,37 +357,33 @@ public override void PostExposeData()
if( this.IsLift() == false ){
Scribe_Values.LookValue( ref PowerDirection, "powerDirection", Rot4.Invalid, true );
- Scribe_References.LookReference( ref _headParent, "powerHead" );
+ if( Scribe.mode == LoadSaveMode.Saving )
+ _headParentString = _headParent.ThingID;
- if( Scribe.mode == LoadSaveMode.PostLoadInit ){
- if( ( _headParent != null )&&
- ( PowerDirection != Rot4.Invalid ) ){
- var p = _headParent.TryGetComp();
- if( p != null ){
- p.RegisterInferedPowerComponent( this, PowerDirection );
- }
- } else {
- PowerHead = null;
- }
+ Scribe_Values.LookValue( ref _headParentString, "powerHead", string.Empty, true );
+
+ if( Scribe.mode == LoadSaveMode.ResolvingCrossRefs )
+ {
+ gameJustLoaded = true;
}
}
}
- public override void PostDestroy(DestroyMode mode = DestroyMode.Vanish)
+ public override void PostDeSpawn()
{
ItemContainer.Destroy();
// Disconnect all infered power users
- if( poweredBelts != null )
- foreach( var b in poweredBelts )
- UnregisterInferedPowerComponent( b );
+ if( !poweredBelts.NullOrEmpty() )
+ for( int index = poweredBelts.Count - 1; index >= 0; index-- )
+ UnregisterInferedPowerComponent( poweredBelts[ index ] );
// Disconnect from power head
if( ( PowerHead != null )&&
( PowerHead != this ) )
PowerHead.UnregisterInferedPowerComponent( this );
- base.PostDestroy(mode);
+ base.PostDeSpawn();
}
public override string CompInspectStringExtra()
diff --git a/Source/A2B/Components/BeltUndertakerComponent.cs b/Source/A2B/Components/BeltUndertakerComponent.cs
index 8e8f1c5..39ed908 100644
--- a/Source/A2B/Components/BeltUndertakerComponent.cs
+++ b/Source/A2B/Components/BeltUndertakerComponent.cs
@@ -12,6 +12,18 @@
namespace A2B
{
+ public struct UndertakerToggleData
+ {
+ public BeltUndertakerComponent target;
+ public bool forced;
+
+ public UndertakerToggleData( BeltUndertakerComponent target, bool forced )
+ {
+ this.target = target;
+ this.forced = forced;
+ }
+ }
+
[UsedImplicitly]
public class BeltUndertakerComponent : BeltUndergroundComponent
{
@@ -33,7 +45,7 @@ public override void PostSpawnSetup()
public override void PostExposeData()
{
base.PostExposeData();
- Scribe_Values.LookValue( ref forcedMode, "forcedMode" );
+ Scribe_Values.LookValue( ref forcedMode, "forcedMode" );
}
private bool modeReset()
@@ -43,41 +55,16 @@ private bool modeReset()
if( forcedMode )
return false;
- // Get the top belt connection
- BeltComponent topBelt = this.GetPositionFromRelativeRotation( Rot4.South ).GetBeltComponent();
+ // Needs mode toggle, register for update
+ if(
+ ( !this.IsSlide() )&&
+ ( !this.IsLift() )
+ )
+ {
+ A2BMonitor.RegisterTickAction( this.parent.ThingID, UndertakerToggleMode, new UndertakerToggleData( this, false ) );
+ return true;
+ }
- if( topBelt != null )
- {
- // We have a belt connected to the top
- if( topBelt.CanAcceptFrom( this, true ) )
- {
- // The top belt can accept from this belt,
- // therefore this is a powered lift
- if( !this.IsLift() )
- {
- // Make sure it's a powered version
- ChangeOperationalMode( UndertakerMode.PoweredLift );
-
- // Force exit now to allow change
- return true;
- }
- }
- else
- {
- // This undertaker can't feed the top belt, assume the top
- // belt feeds the undertaker and operate as a slide
- if( !this.IsSlide() )
- {
- // Slides don't use power and we don't want
- // them to transmit to allow segmenting the
- // power network used by the conveyors
- ChangeOperationalMode( UndertakerMode.UnpoweredSlide );
-
- // Force exit now to allow change
- return true;
- }
- }
- }
return false;
}
@@ -95,11 +82,6 @@ public override void OnOccasionalTick()
if( modeReset() )
return;
- // Abort if still in config mode
- if( ( !this.IsSlide() )&&
- ( !this.IsLift() ) )
- return;
-
// Configured, now process
base.OnOccasionalTick();
@@ -117,45 +99,6 @@ public override void OnOccasionalTick()
}
- private void ChangeOperationalMode( UndertakerMode newMode, bool forced = false )
- {
- // Get the def we need
- string beltDefName;
- switch ( newMode )
- {
- case UndertakerMode.PoweredLift:
- beltDefName = "A2BLift";
- break;
- case UndertakerMode.UnpoweredSlide:
- beltDefName = "A2BSlide";
- break;
- default:
- return; // Invalid mode change
- }
-
- // Get the thing def for the belt
- ThingDef beltDef = DefDatabase.GetNamed( beltDefName );
-
- // Get our current position and rotation
- IntVec3 beltPos = parent.Position;
- Rot4 beltRot = parent.Rotation;
-
- // Make the new belt
- Thing beltThing = ThingMaker.MakeThing( beltDef );
- beltThing.SetFactionDirect( Faction.OfColony );
- beltThing.HitPoints = parent.HitPoints;
-
- // Set the new belt mode
- BeltUndertakerComponent beltComp = beltThing.TryGetComp();
- beltComp.forcedMode = forced;
-
- // Remove this belt
- parent.Destroy( DestroyMode.Vanish );
-
- // Spawn new belt
- GenSpawn.Spawn( beltThing, beltPos, beltRot );
- }
-
public override IntVec3 GetDestinationForThing( Thing thing)
{
return IntVec3.Invalid;
@@ -174,7 +117,7 @@ public override void PostDraw()
status.Thing.DrawAt(drawPos);
- DrawGUIOverlay(status, drawPos);
+ //DrawGUIOverlay(status, drawPos);
}
if( ( ( !this.IsSlide() )&&( !this.IsLift() ) )||
( ( this.IsSlide() )&&( BeltPhase == Phase.Offline ) ) )
@@ -245,25 +188,21 @@ public override IEnumerable CompGetGizmosExtra()
Command_Action actionToggleMode = new Command_Action();
if( actionToggleMode != null )
{
- actionToggleMode.icon = ContentFinder.Get( "UI/Icons/Commands/UndertakerMode", true);;
+ actionToggleMode.icon = Constants.IconUndertakerToggle;
actionToggleMode.defaultLabel = Constants.TxtUndertakerModeToggle.Translate();
- actionToggleMode.activateSound = SoundDef.Named( "Click" );
+ actionToggleMode.activateSound = Constants.ButtonClick;
if( this.IsLift() )
{
actionToggleMode.defaultDesc = Constants.TxtUndertakerModeSlide.Translate();
- actionToggleMode.action = new Action( delegate()
- {
- ChangeOperationalMode( UndertakerMode.UnpoweredSlide, true );
- } );
}
else
{
actionToggleMode.defaultDesc = Constants.TxtUndertakerModeLift.Translate();
- actionToggleMode.action = new Action( delegate()
- {
- ChangeOperationalMode( UndertakerMode.PoweredLift, true );
- } );
}
+ actionToggleMode.action = new Action( delegate()
+ {
+ A2BMonitor.RegisterTickAction( this.parent.ThingID, UndertakerToggleMode, new UndertakerToggleData( this, true ) );
+ } );
if( actionToggleMode.action != null )
{
yield return actionToggleMode;
@@ -272,5 +211,104 @@ public override IEnumerable CompGetGizmosExtra()
// No more gizmos
yield break;
}
+
+ #region Static Callbacks
+
+ public static bool UndertakerToggleMode( object target )
+ {
+ var toggleData = (UndertakerToggleData) target;
+ UndertakerMode toggleMode = UndertakerMode.Undefined;
+ if( toggleData.target.IsLift() )
+ {
+ toggleMode = UndertakerMode.UnpoweredSlide;
+ }
+ else if( toggleData.target.IsSlide() )
+ {
+ toggleMode = UndertakerMode.PoweredLift;
+ }
+ else
+ {
+ toggleMode = UndertakerMode.AutoDetect;
+ }
+ return ChangeOperationalMode( toggleData.target, toggleMode, toggleData.forced );
+ }
+
+ private static bool ChangeOperationalMode( BeltUndertakerComponent undertaker, UndertakerMode newMode, bool forced )
+ {
+ // Get the new def
+ ThingDef beltDef;
+ switch ( newMode )
+ {
+ case UndertakerMode.PoweredLift:
+ beltDef = Constants.DefBeltLift;
+ break;
+ case UndertakerMode.UnpoweredSlide:
+ beltDef = Constants.DefBeltSlide;
+ break;
+ case UndertakerMode.AutoDetect:
+ BeltComponent topBelt = undertaker.GetPositionFromRelativeRotation( Rot4.South ).GetBeltSurfaceComponent();
+
+ if( topBelt != null )
+ {
+ // We have a belt connected to the top
+ if( topBelt.CanAcceptFrom( undertaker, true ) )
+ {
+ // The top belt can accept from this belt,
+ // therefore this is a powered lift
+ if( undertaker.IsLift() )
+ {
+ // Already a lift
+ return true;
+ }
+
+ // Switch this to a lift
+ beltDef = Constants.DefBeltLift;
+ break;
+ }
+ else
+ {
+ // This undertaker can't feed the top belt, assume the top
+ // belt feeds the undertaker and operate as a slide
+ if( undertaker.IsSlide() )
+ {
+ // Already a slide
+ return true;
+ }
+
+ // Switch this to a slide
+ beltDef = Constants.DefBeltSlide;
+ break;
+ }
+ }
+ // No top belt, don't do anything yet
+ return false;
+ default:
+ // Invalid mode change, deregister to allow for a proper mode change
+ return true;
+ }
+
+ // Get target position and rotation
+ IntVec3 beltPos = undertaker.parent.Position;
+ Rot4 beltRot = undertaker.parent.Rotation;
+
+ // Make the new belt
+ Thing beltThing = ThingMaker.MakeThing( beltDef );
+ beltThing.SetFactionDirect( Faction.OfColony );
+ beltThing.HitPoints = undertaker.parent.HitPoints;
+
+ // Set the new belt mode
+ BeltUndertakerComponent beltComp = beltThing.TryGetComp();
+ beltComp.forcedMode = forced;
+
+ // Remove the existing belt
+ undertaker.parent.Destroy();
+
+ // Spawn new belt
+ GenSpawn.Spawn( beltThing, beltPos, beltRot );
+ return true;
+ }
+
+ #endregion
+
}
}
diff --git a/Source/A2B/Components/BeltUnloaderComponent.cs b/Source/A2B/Components/BeltUnloaderComponent.cs
index b049719..0b7c1cd 100644
--- a/Source/A2B/Components/BeltUnloaderComponent.cs
+++ b/Source/A2B/Components/BeltUnloaderComponent.cs
@@ -9,7 +9,7 @@ namespace A2B
{
public class BeltUnloaderComponent : BeltComponent
{
- public override bool CanOutputToNonBelt()
+ public override bool CanOutputToNonBelt( IntVec3 beltDest, Thing thing )
{
return true;
}
diff --git a/Source/A2B/Components/Extensions/BeltUtilities.cs b/Source/A2B/Components/Extensions/BeltUtilities.cs
index 6e8a1d8..5c64aa6 100644
--- a/Source/A2B/Components/Extensions/BeltUtilities.cs
+++ b/Source/A2B/Components/Extensions/BeltUtilities.cs
@@ -59,21 +59,58 @@ public static void DrawUndercoverFrame( this BeltUndercoverComponent belt )
}
[CanBeNull]
- public static BeltComponent GetBeltComponent(this IntVec3 position )
+ public static BeltComponent GetBeltComponent( this IntVec3 position, BeltComponent source )
+ {
+ switch( source.OutputLevel )
+ {
+ case Level.Surface:
+ return position.GetBeltSurfaceComponent();
+
+ case Level.Underground:
+ var belts = position.GetBeltUndergroundComponents();
+
+ // Scan for prefered belt (lift) otherwise continue underground
+ if( ( belts != null )&&
+ ( belts.Count > 0 ) )
+ {
+
+ //var p = _parentComponent as BeltUndergroundComponent;
+ var lift = belts.Find( b => b.IsLift() && b.CanAcceptFrom( source ) );
+ var under = belts.Find( b => b.IsUndercover() );
+ if(
+ ( lift != null )&&
+ (
+ ( lift.BeltPhase == Phase.Active )||
+ ( under == null )
+ )
+ )
+ return lift;
+ else
+ return under;
+ }
+ return null;
+
+ default:
+ return null;
+ }
+ }
+
+ [CanBeNull]
+ public static BeltComponent GetBeltSurfaceComponent(this IntVec3 position )
{
// BUGFIX: Previously, this function would grab the first building it saw at a given position. This is a problem
// if a power conduit was on the same tile, as it was possible to miss the BeltComponent entirely. This is a more
// robust method of identifying BeltComponents at a given location because it first finds ALL buildings on a tile.
-
- // CHANGE: Belts now have a level (underground and surface), this function returns a surface component
+
+ // CHANGE: Belts now have a level (underground and surface), this function returns a surface component
// Since this query is lazily evaluated, it is much faster than using ThingsListAt.
try {
return Find.ThingGrid.ThingsAt(position) // All things at a given position
- .OfType() // Only ones that can be converted to ThingWithComps
- .Select(tc => tc.TryGetComp()) // Grab the BeltComponent from each one
- .First(b => (b != null)&&(b.InputLevel & Level.Surface)!= 0);// Get the first non-null entry on the surface
+ .OfType() // Only ones that can be converted to ThingWithComps
+ .Select(tc => tc.TryGetComp()) // Grab the BeltComponent from each one
+ .First(b => (b != null)&&(b.InputLevel & Level.Surface)!= 0);// Get the first non-null entry on the surface
} catch (InvalidOperationException) {
return null; // Didn't find one at all
}
diff --git a/Source/A2B/Components/UndertakerMode.cs b/Source/A2B/Components/UndertakerMode.cs
index 9b8ebab..214c3e5 100644
--- a/Source/A2B/Components/UndertakerMode.cs
+++ b/Source/A2B/Components/UndertakerMode.cs
@@ -4,6 +4,7 @@ public enum UndertakerMode
{
Undefined = 0,
PoweredLift,
- UnpoweredSlide
+ UnpoweredSlide,
+ AutoDetect
}
}
\ No newline at end of file
diff --git a/Source/A2B/Designators/Designator_ToggleUndercoverCover.cs b/Source/A2B/Designators/Designator_ToggleUndercoverCover.cs
index ec56ea8..9bdbec7 100644
--- a/Source/A2B/Designators/Designator_ToggleUndercoverCover.cs
+++ b/Source/A2B/Designators/Designator_ToggleUndercoverCover.cs
@@ -13,15 +13,21 @@ namespace A2B
public class Designator_ToggleUndercoverCover : Designator
{
- public Designator_ToggleUndercoverCover()
+
+ public void LoadDesignatorIcon()
{
this.icon = Constants.IconUndercoverCoverToggle;
+ }
+
+ public Designator_ToggleUndercoverCover()
+ {
+ LongEventHandler.ExecuteWhenFinished( LoadDesignatorIcon );
this.defaultLabel = Constants.TxtUndercoverCoverToggle.Translate();
this.defaultDesc = Constants.TxtUnderUndercoverCoverToggleDesc.Translate();
this.useMouseIcon = true;
this.soundDragSustain = SoundDefOf.DesignateDragStandard;
this.soundDragChanged = SoundDefOf.DesignateDragStandardChanged;
- this.soundSucceeded = SoundDef.Named( "Click" );
+ this.soundSucceeded = Constants.ButtonClick;
this.hotKey = Constants.KeyUndercoverCoverToggle;
}
diff --git a/Source/A2B/JobDrivers/JobDriver_UndercoverCoverToggle.cs b/Source/A2B/JobDrivers/JobDriver_UndercoverCoverToggle.cs
index c2bb1cb..a6972da 100644
--- a/Source/A2B/JobDrivers/JobDriver_UndercoverCoverToggle.cs
+++ b/Source/A2B/JobDrivers/JobDriver_UndercoverCoverToggle.cs
@@ -19,7 +19,7 @@ protected override IEnumerable MakeNewToils()
// Destroyed,
// On fire
// Designator removed
- this.FailOnDestroyed( TargetIndex.A );
+ this.FailOnDespawnedNullOrForbidden( TargetIndex.A );
this.FailOnBurningImmobile( TargetIndex.A );
this.FailOnThingMissingDesignation( TargetIndex.A, Constants.DesignationUndercoverCoverToggle );
// Reserve the target
diff --git a/Source/A2B/Properties/AssemblyInfo.cs b/Source/A2B/Properties/AssemblyInfo.cs
index d1dcae0..83d563a 100755
--- a/Source/A2B/Properties/AssemblyInfo.cs
+++ b/Source/A2B/Properties/AssemblyInfo.cs
@@ -10,7 +10,7 @@
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("A2B")]
-[assembly: AssemblyCopyright("Copyright © 2014, 2015")]
+[assembly: AssemblyCopyright("Copyright © 2014-2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -35,5 +35,5 @@
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.12.1.0")]
-[assembly: AssemblyFileVersion("0.12.1.0")]
+[assembly: AssemblyVersion("0.13.0.0")]
+[assembly: AssemblyFileVersion("0.13.0.0")]
diff --git a/Source/A2B/Utilities/A2BDataDef.cs b/Source/A2B/Utilities/A2BDataDef.cs
index f125aef..0ffbe47 100644
--- a/Source/A2B/Utilities/A2BDataDef.cs
+++ b/Source/A2B/Utilities/A2BDataDef.cs
@@ -11,6 +11,7 @@
namespace A2B
{
+
public class A2BDataDef : Def
{
// Core mod versioning
@@ -41,6 +42,10 @@ public class A2BDataDef : Def
public float ReliabilityStartThresholdOffset;
public List< string > ReliabilityResearch;
+ // Power data
+ public float LowPowerFactor = 0.1f;
+ public float PowerPerUndercover = 10f;
+
}
}
diff --git a/Source/A2B/Utilities/A2BMonitor.cs b/Source/A2B/Utilities/A2BMonitor.cs
index f4a6ee5..a5b9377 100644
--- a/Source/A2B/Utilities/A2BMonitor.cs
+++ b/Source/A2B/Utilities/A2BMonitor.cs
@@ -7,29 +7,29 @@ namespace A2B
// Return true to automatically deregister
// DO NOT DEREGISTER FROM WITHIN A CALLBACK!
// Invalidated lists are bad, mmm'kay?
- public delegate bool MonitorAction();
+ public delegate bool MonitorAction( object target );
public class A2BMonitor : MapComponent
{
- private static Dictionary tickActions = new Dictionary();
- private static Dictionary occasionalActions = new Dictionary();
- private static Dictionary updateActions = new Dictionary();
- private static Dictionary guiActions = new Dictionary();
- private static Dictionary exposeActions = new Dictionary();
+ private static Dictionary> tickActions = new Dictionary>();
+ private static Dictionary> occasionalActions = new Dictionary>();
+ private static Dictionary> updateActions = new Dictionary>();
+ private static Dictionary> guiActions = new Dictionary>();
+ private static Dictionary> exposeActions = new Dictionary>();
private static List< string > removeKeys = new List< string >();
private bool firstTick = true;
- private void ProcessCallbacks( Dictionary d )
+ private void ProcessCallbacks( Dictionary> d )
{
removeKeys.Clear();
- foreach (var p in d)
- if( p.Value() == true )
+ foreach( var p in d )
+ if( p.Value.First( p.Value.Second ) == true )
removeKeys.Add( p.Key );
- foreach (var k in removeKeys)
+ foreach( var k in removeKeys )
d.Remove( k );
}
@@ -46,7 +46,7 @@ public override void MapComponentTick()
ProcessCallbacks( tickActions );
- // Occasional only get fewer ticks so they don't bomb the system
+ // Occasional get fewer ticks so they don't bomb the system
if( ( firstTick == true )||
( ( Find.TickManager.TicksGame + GetHashCode() ) % A2BData.OccasionalTicks == 0 ) )
ProcessCallbacks( occasionalActions );
@@ -70,62 +70,62 @@ public override void ExposeData()
#region Register/Deregister Actions
- public static void RegisterUpdateAction(string name, MonitorAction action)
+ public static void RegisterUpdateAction( string name, MonitorAction action, object target = null )
{
if( !updateActions.ContainsKey( name ) )
- updateActions.Add(name, action);
+ updateActions.Add( name, new Pair( action, target ) );
}
- public static void DeregisterUpdateAction(string name)
+ public static void DeregisterUpdateAction( string name )
{
- updateActions.Remove(name);
+ updateActions.Remove( name );
}
- public static void RegisterTickAction(string name, MonitorAction action)
+ public static void RegisterTickAction( string name, MonitorAction action, object target = null )
{
if( !tickActions.ContainsKey( name ) )
- tickActions.Add(name, action);
+ tickActions.Add( name, new Pair( action, target ) );
}
- public static void DeregisterTickAction(string name)
+ public static void DeregisterTickAction( string name )
{
- tickActions.Remove(name);
+ tickActions.Remove( name );
}
- public static void RegisterOccasionalAction(string name, MonitorAction action)
+ public static void RegisterOccasionalAction( string name, MonitorAction action, object target = null )
{
if( !occasionalActions.ContainsKey( name ) ){
// Invoke accasional actions immediately
- if( action.Invoke() == false )
- occasionalActions.Add(name, action);
+ if( action.Invoke( target ) == false )
+ occasionalActions.Add( name, new Pair( action, target ) );
}
}
- public static void DeregisterOccasionalAction(string name)
+ public static void DeregisterOccasionalAction( string name )
{
- occasionalActions.Remove(name);
+ occasionalActions.Remove( name );
}
- public static void RegisterGUIAction(string name, MonitorAction action)
+ public static void RegisterGUIAction( string name, MonitorAction action, object target = null )
{
if( !guiActions.ContainsKey( name ) )
- guiActions.Add(name, action);
+ guiActions.Add( name, new Pair( action, target ) );
}
- public static void DeregisterGUIAction(string name)
+ public static void DeregisterGUIAction( string name )
{
- guiActions.Remove(name);
+ guiActions.Remove( name );
}
- public static void RegisterExposeDataAction(string name, MonitorAction action)
+ public static void RegisterExposeDataAction( string name, MonitorAction action, object target = null )
{
if( !exposeActions.ContainsKey( name ) )
- exposeActions.Add(name, action);
+ exposeActions.Add( name, new Pair( action, target ) );
}
- public static void DeregisterExposeDataAction(string name)
+ public static void DeregisterExposeDataAction( string name )
{
- exposeActions.Remove(name);
+ exposeActions.Remove( name );
}
#endregion
diff --git a/Source/A2B/Utilities/A2BResearch.cs b/Source/A2B/Utilities/A2BResearch.cs
index bd71cee..491fe0b 100644
--- a/Source/A2B/Utilities/A2BResearch.cs
+++ b/Source/A2B/Utilities/A2BResearch.cs
@@ -47,7 +47,8 @@ public static class A2BData
public static A2B_Reliability Reliability;
// Power for underground powered belts
- public static float powerPerUndercover = 1000f;
+ public static float LowPowerFactor;
+ public static float PowerPerUndercover;
public static A2BDataDef def
{
@@ -82,7 +83,9 @@ static A2BData()
Reliability.StartThreshold = def.ReliabilityStartThresholdBase;
Reliability.FlatRateThreshold = def.ReliabilityFlatRateThresholdBase;
- A2BMonitor.RegisterTickAction( "A2BResearch.UndercoverPowerInit", A2BResearch.UndercoverPowerInit );
+ LowPowerFactor = def.LowPowerFactor;
+ PowerPerUndercover = def.PowerPerUndercover;
+
A2BMonitor.RegisterTickAction( "A2BResearch.BeltSpeedInit", A2BResearch.BeltSpeedInit );
A2BMonitor.RegisterOccasionalAction( "A2BResearch.BeltSpeed", A2BResearch.BeltSpeed );
@@ -119,25 +122,14 @@ public static void CheckVersion(Version version)
public static class A2BResearch
{
- public static bool UndercoverPowerInit()
- {
- var baseBelt = DefDatabase.GetNamed( "A2BBelt" );
- if( baseBelt != null ){
- var beltComps = baseBelt.CompDefFor();
- if( beltComps != null )
- A2BData.powerPerUndercover = beltComps.basePowerConsumption;
- }
- return true;
- }
-
- public static bool BeltSpeedInit()
+ public static bool BeltSpeedInit( object target )
{
A2BData.BeltSpeed.TicksToMove = A2BData.def.BeltSpeedBase;
AnimatedGraphic.animationRate = ( (float)A2BData.BeltSpeed.TicksToMove / 90.0f);
return true;
}
- public static bool BeltSpeed()
+ public static bool BeltSpeed( object target )
{
if (A2BResearch.ResearchGroupComplete(A2BData.def.BeltSpeedResearch)) {
A2BData.BeltSpeed.TicksToMove += A2BData.def.BeltSpeedOffset;
@@ -148,7 +140,7 @@ public static bool BeltSpeed()
return false;
}
- public static bool Climatization()
+ public static bool Climatization( object target )
{
if (A2BResearch.ResearchGroupComplete(A2BData.def.ClimatizationResearch)) {
A2BData.Climatization.FreezeTemperature += A2BData.def.ClimatizationMinTemperatureOffset;
@@ -158,7 +150,7 @@ public static bool Climatization()
return false;
}
- public static bool Durability()
+ public static bool Durability( object target )
{
if (A2BResearch.ResearchGroupComplete(A2BData.def.DurabilityResearch)) {
A2BData.Durability.DeteriorateChance += A2BData.def.DurabilityOffset;
@@ -168,7 +160,7 @@ public static bool Durability()
return false;
}
- public static bool Reliability()
+ public static bool Reliability( object target )
{
if (A2BResearch.ResearchGroupComplete(A2BData.def.ReliabilityResearch)) {
A2BData.Reliability.FlatRateThreshold += A2BData.def.ReliabilityFlatRateThresholdOffset;
diff --git a/Source/A2B/Utilities/Constants.cs b/Source/A2B/Utilities/Constants.cs
index 2663887..7856c37 100755
--- a/Source/A2B/Utilities/Constants.cs
+++ b/Source/A2B/Utilities/Constants.cs
@@ -3,9 +3,14 @@
namespace A2B
{
+
+ [StaticConstructorOnStartup]
public static class Constants
{
- public const string msgPowerDisconnect = "PowerDisconnect";
+
+ #region Text Keys
+
+ public const string msgPowerDisconnect = "PowerDisconnect";
public const string msgPowerConnect = "PowerConnect";
public const string TxtActive = "A2B_Active";
@@ -23,6 +28,9 @@ public static class Constants
public const string TxtLiftDrivingComponents = "A2B_LiftDrivingComponents";
+ public const string TxtSelectorToGroundToggleDescription = "A2B_Selector_To_Ground_Toggle_Desc";
+ public const string TxtSelectorToGroundToggle = "A2B_Selector_To_Ground_Toggle";
+
public const string TxtUndertakerMode = "A2B_Undertaker_Mode";
public const string TxtUndertakerModeToggle = "A2B_Undertaker_Mode_Toggle";
public const string TxtUndertakerModeUndefined = "A2B_Undertaker_Mode_Undefined";
@@ -41,11 +49,13 @@ public static class Constants
public const string TxtDirectionSouth = "A2B_Direction_South";
public const string TxtDirectionWest = "A2B_Direction_West";
- public static ThingDef DefBeltUndercover = DefDatabase.GetNamed( "A2BUndercover", true );
+ #endregion
- public static Texture2D IconUndercoverCoverToggle = ContentFinder.Get( "UI/Icons/Commands/UndercoverCoverToggle", true);
+ #region Key Defs
- //public static Material UndercoverFrame = MaterialPool.MatFrom( "Things/Building/UndergroundFrame" );
+ public static ThingDef DefBeltUndercover = DefDatabase.GetNamed( "A2BUndercover", true );
+ public static ThingDef DefBeltLift = DefDatabase.GetNamed( "A2BLift", true );
+ public static ThingDef DefBeltSlide = DefDatabase.GetNamed( "A2BSlide", true );
public static DesignationDef DesignationUndercoverCoverToggle = DefDatabase.GetNamed( "A2BUndercoverCoverToggleDesignation", true );
@@ -53,5 +63,42 @@ public static class Constants
public static KeyBindingDef KeyUndercoverCoverToggle = DefDatabase.GetNamed( "A2BUndercoverCoverToggleKeyBinding", true );
+ public static SoundDef ButtonClick = DefDatabase.GetNamed( "Click", true );
+
+ #endregion
+
+ #region Icon Paths
+
+ public static string PathIconSelectorToGroundTrue = "UI/Icons/Commands/UndertakerMode";
+ public static string PathIconSelectorToGroundFalse = "UI/Icons/Commands/UndercoverCoverToggle";
+
+ public static string PathIconUndertakerToggle = "UI/Icons/Commands/UndertakerMode";
+ public static string PathIconUndercoverCoverToggle = "UI/Icons/Commands/UndercoverCoverToggle";
+
+ #endregion
+
+ #region Icon Textures
+
+ public static Texture2D IconSelectorToGroundTrue;
+ public static Texture2D IconSelectorToGroundFalse;
+ public static Texture2D IconUndertakerToggle;
+ public static Texture2D IconUndercoverCoverToggle;
+
+ #endregion
+
+ //public static Material UndercoverFrame = MaterialPool.MatFrom( "Things/Building/UndergroundFrame" );
+
+ static Constants()
+ {
+ LongEventHandler.ExecuteWhenFinished( LoadIcons );
+ }
+
+ static void LoadIcons()
+ {
+ IconSelectorToGroundTrue = ContentFinder.Get( PathIconSelectorToGroundTrue, true );
+ IconSelectorToGroundFalse = ContentFinder.Get( PathIconSelectorToGroundFalse, true );
+ IconSelectorToGroundFalse = ContentFinder.Get( PathIconSelectorToGroundFalse, true );
+ IconUndercoverCoverToggle = ContentFinder.Get( PathIconUndercoverCoverToggle, true );
+ }
}
}