fixes and ammobins and staleTarget rework - #820
Conversation
-Scalable Ammo bin implementation -Ghost gimbal 'aim assist' for custom turrets
-MissileMagazine hullMat mass -variantPart HP bloat
reworks staleTarget to track per-vessel Fixes target timeout Target selection now weights out-of-los craft down by 50% to prevent target fixation on hidden tgts Maintain min dist SrfAI option now requires Los, no more getting stuck in a city street because there's a enemy on the other side of a building Tighten up missile interception, now needs active detection of missile Adds more DEBUG mode logging for staleTarget stuff
fix box width scaling, add dynamic bin mass, better part movement when scaling with attached parts
-ammo bin mass clamped to nearest kg to hopefully reduce Hitpoint hp calc triggering -removed redundant refreshAssoc.Win. call -fix ammo drum area calc
-Convert CanSeeTarget to Enum. -Add null checking for various StaleTarget dict references -staletarget dict cleaning
|
Also, C.A.S.E. level 2 is breaking the amount of ammo. |
|
OK, this is what I've got so far with eliminating unnecessary PAW refresh calls. diff --git a/BDArmory/Ammo/ModuleCASE.cs b/BDArmory/Ammo/ModuleCASE.cs
index 4aa411d41..030e6a059 100644
--- a/BDArmory/Ammo/ModuleCASE.cs
+++ b/BDArmory/Ammo/ModuleCASE.cs
@@ -186,6 +186,7 @@ void CASESetup(BaseField field, object obj)
//if (resource.Current.maxAmount < 80) //original value < 100, at risk of fractional amount
{
resource.Current.maxAmount = resourceAmount[i];
+ GUIUtils.RefreshPAWResource(part, resource.Current);
}
//else resource.Current.maxAmount = Math.Floor(resource.Current.maxAmount * 1.25);
i++;
@@ -200,6 +201,7 @@ void CASESetup(BaseField field, object obj)
resource.Current.maxAmount *= 0.8;
resource.Current.maxAmount = Math.Floor(resource.Current.maxAmount);
resource.Current.amount = Math.Min(resource.Current.amount, resource.Current.maxAmount);
+ GUIUtils.RefreshPAWResource(part, resource.Current);
}
}
using (List<Part>.Enumerator pSym = part.symmetryCounterparts.GetEnumerator())
@@ -222,6 +224,7 @@ void CASESetup(BaseField field, object obj)
if (resource.Current == null) continue;
resource.Current.maxAmount = Math.Floor(resource.Current.maxAmount * 1.25);
resource.Current.amount = Math.Min(resource.Current.amount, resource.Current.maxAmount);
+ GUIUtils.RefreshPAWResource(pSym.Current, resource.Current);
}
}
if (!CASE.Case2 && CASE.CASELevel == 2)
@@ -232,14 +235,15 @@ void CASESetup(BaseField field, object obj)
if (resource.Current == null) continue;
resource.Current.maxAmount *= 0.8;
resource.Current.amount = Math.Min(resource.Current.amount, resource.Current.maxAmount);
+ GUIUtils.RefreshPAWResource(pSym.Current, resource.Current);
}
}
CASE.Case2 = CASE.CASELevel == 2 ? true : false;
CASE.externallyCalled = false;
- GUIUtils.RefreshAssociatedWindows(pSym.Current);
+ // GUIUtils.RefreshAssociatedWindows(pSym.Current);
}
Case2 = CASELevel == 2 ? true : false;
- GUIUtils.RefreshAssociatedWindows(part);
+ // GUIUtils.RefreshAssociatedWindows(part);
}
public override void OnLoad(ConfigNode node)
{
diff --git a/BDArmory/Control/BDModuleOrbitalAI.cs b/BDArmory/Control/BDModuleOrbitalAI.cs
index 4a5c66595..8117feb99 100644
--- a/BDArmory/Control/BDModuleOrbitalAI.cs
+++ b/BDArmory/Control/BDModuleOrbitalAI.cs
@@ -461,7 +461,7 @@ public void SetChooseOptions()
public void ChooseOptionsUpdated(BaseField field, object obj)
{
- this.part.RefreshAssociatedWindows();
+ GUIUtils.UpdateChooseOptionPAW(field, this);
if (BDArmoryAIGUI.Instance != null)
{
BDArmoryAIGUI.Instance.SetChooseOptionSliders();
diff --git a/BDArmory/Control/BDModuleSurfaceAI.cs b/BDArmory/Control/BDModuleSurfaceAI.cs
index 23309f2c3..057f74320 100644
--- a/BDArmory/Control/BDModuleSurfaceAI.cs
+++ b/BDArmory/Control/BDModuleSurfaceAI.cs
@@ -299,7 +299,7 @@ public void ChooseOptionsUpdated(BaseField field, object obj)
Fields[nameof(CombatAltitude)].guiActiveEditor = SurfaceType == AIUtils.VehicleMovementType.Submarine;
Fields[nameof(maintainMinRange)].guiActive = SurfaceType == AIUtils.VehicleMovementType.Land;
Fields[nameof(maintainMinRange)].guiActiveEditor = SurfaceType == AIUtils.VehicleMovementType.Land;
- part.RefreshAssociatedWindows();
+ GUIUtils.UpdateChooseOptionPAW(field, this);
if (BDArmoryAIGUI.Instance != null)
{
BDArmoryAIGUI.Instance.SetChooseOptionSliders();
diff --git a/BDArmory/Control/BDModuleVTOLAI.cs b/BDArmory/Control/BDModuleVTOLAI.cs
index 8f1d84f26..32da205fd 100644
--- a/BDArmory/Control/BDModuleVTOLAI.cs
+++ b/BDArmory/Control/BDModuleVTOLAI.cs
@@ -277,7 +277,7 @@ public void SetChooseOptions()
public void ChooseOptionsUpdated(BaseField field, object obj)
{
- this.part.RefreshAssociatedWindows();
+ GUIUtils.UpdateChooseOptionPAW(field, this);
if (BDArmoryAIGUI.Instance != null)
{
BDArmoryAIGUI.Instance.SetChooseOptionSliders();
diff --git a/BDArmory/Damage/HitpointTracker.cs b/BDArmory/Damage/HitpointTracker.cs
index 3515f7aed..8483db037 100644
--- a/BDArmory/Damage/HitpointTracker.cs
+++ b/BDArmory/Damage/HitpointTracker.cs
@@ -312,7 +312,7 @@ public bool SetupPrefab()
}
previousHitpoints = maxHitPoints_;
- part.RefreshAssociatedWindows();
+ // part.RefreshAssociatedWindows();
return true;
}
else
@@ -390,7 +390,7 @@ public override void OnStart(StartState state)
HullTypeNum = HullInfo.materials.FindIndex(t => t.name == "Aluminium") + 1;
}
SetHullMass();
- part.RefreshAssociatedWindows();
+ // part.RefreshAssociatedWindows();
}
if (HighLogic.LoadedSceneIsFlight || HighLogic.LoadedSceneIsEditor)
{
@@ -1454,7 +1454,7 @@ public void SetArmor()
armorFieldEditor.onFieldChanged = ArmorModified;
if (!armorReset)
{
- part.RefreshAssociatedWindows();
+ // part.RefreshAssociatedWindows();
}
armorReset = true;
}
@@ -1470,7 +1470,7 @@ public void SetArmor()
//armorFieldEditor.maxValue = 10; //max none armor to 10 (simulate part skin of alimunium)
//armorFieldEditor.minValue = 10;
- part.RefreshAssociatedWindows();
+ // part.RefreshAssociatedWindows();
//GameEvents.onEditorShipModified.Fire(EditorLogic.fetch.ship);
}
}
@@ -1664,7 +1664,8 @@ public bool CheckForChanges(bool forceUpdate = false)
if (++iterations > 10)
{
// Note: this happens for very small parts with light mass types whose mass values don't stabilise sufficiently for the Mathf.Approximately check. Using BDAMath.Approximately seems to avoid this.
- Debug.LogError($"[BDArmory.HitpointTracker]: Excessive number of loops when updating mass/armor/hull/hp of {part.name} on {part.vessel.GetName()}. Aborting.");
+ // It also seems to happen for some material changes that oscillate between two values. FIXME
+ Debug.LogWarning($"[BDArmory.HitpointTracker]: Excessive number of loops when updating mass/armor/hull/hp of {part.name} on {(HighLogic.LoadedSceneIsEditor ? part.ship.shipName : part.vessel.GetName())}. Aborting.");
break;
}
if (_updateMass)
@@ -1697,7 +1698,7 @@ public bool CheckForChanges(bool forceUpdate = false)
}
}
UpdatePartMass(ref safetyMass, ref missileMass, ref ammoMass);
- if (!Mathf.Approximately(tmpMass, partMass))
+ if (!BDAMath.Approximately(tmpMass, partMass, oldMass))
{
_hullModified = _armorModified = true;
}
diff --git a/BDArmory/Extensions/PartExtensions.cs b/BDArmory/Extensions/PartExtensions.cs
index 0e6ff29f8..8b6da8f5f 100644
--- a/BDArmory/Extensions/PartExtensions.cs
+++ b/BDArmory/Extensions/PartExtensions.cs
@@ -441,24 +441,22 @@ public static float GetDamagePercentage(this Part p)
return damage_ / maxDamage_;
}
- public static void RefreshAssociatedWindows(this Part part)
- {
- //Thanks FlowerChild
- //refreshes part action window
-
- //IEnumerator<UIPartActionWindow> window = UnityEngine.Object.FindObjectsOfType(typeof(UIPartActionWindow)).Cast<UIPartActionWindow>().GetEnumerator();
- //while (window.MoveNext())
- //{
- // if (window.Current == null) continue;
- // if (window.Current.part == part)
+ // public static void RefreshAssociatedWindows(this Part part)
// {
- // window.Current.displayDirty = true;
+ // //Thanks FlowerChild
+ // //refreshes part action window
+ // //IEnumerator<UIPartActionWindow> window = UnityEngine.Object.FindObjectsOfType(typeof(UIPartActionWindow)).Cast<UIPartActionWindow>().GetEnumerator();
+ // //while (window.MoveNext())
+ // //{
+ // // if (window.Current == null) continue;
+ // // if (window.Current.part == part)
+ // // {
+ // // window.Current.displayDirty = true;
+ // // }
+ // //}
+ // //window.Dispose();
+ // MonoUtilities.RefreshContextWindows(part); // This does a full rebuild of the PAW!
// }
- //}
- //window.Dispose();
-
- MonoUtilities.RefreshContextWindows(part);
- }
public static bool IsMissile(this Part part)
{
diff --git a/BDArmory/Modules/ModuleSelfSealingTank.cs b/BDArmory/Modules/ModuleSelfSealingTank.cs
index a4b673eed..f75f56160 100644
--- a/BDArmory/Modules/ModuleSelfSealingTank.cs
+++ b/BDArmory/Modules/ModuleSelfSealingTank.cs
@@ -38,6 +38,7 @@ public void ToggleTankOption()
if (resource.Current == null) continue;
resource.Current.maxAmount = Math.Floor(resource.Current.maxAmount * 1.11112);
resource.Current.amount = Math.Min(resource.Current.amount, resource.Current.maxAmount);
+ GUIUtils.RefreshPAWResource(part, resource.Current);
}
}
else
@@ -50,9 +51,10 @@ public void ToggleTankOption()
if (resource.Current == null) continue;
resource.Current.maxAmount *= 0.9;
resource.Current.amount = Math.Min(resource.Current.amount, resource.Current.maxAmount);
+ GUIUtils.RefreshPAWResource(part, resource.Current);
}
}
- GUIUtils.RefreshAssociatedWindows(part);
+ // GUIUtils.RefreshAssociatedWindows(part);
using (List<Part>.Enumerator pSym = part.symmetryCounterparts.GetEnumerator())
while (pSym.MoveNext())
{
@@ -73,6 +75,7 @@ public void ToggleTankOption()
if (resource.Current == null) continue;
resource.Current.maxAmount = Math.Floor(resource.Current.maxAmount * 1.11112);
resource.Current.amount = Math.Min(resource.Current.amount, resource.Current.maxAmount);
+ GUIUtils.RefreshPAWResource(part, resource.Current);
}
}
else
@@ -85,9 +88,10 @@ public void ToggleTankOption()
if (resource.Current == null) continue;
resource.Current.maxAmount *= 0.9;
resource.Current.amount = Math.Min(resource.Current.amount, resource.Current.maxAmount);
+ GUIUtils.RefreshPAWResource(part, resource.Current);
}
}
- GUIUtils.RefreshAssociatedWindows(pSym.Current);
+ // GUIUtils.RefreshAssociatedWindows(pSym.Current);
}
}
diff --git a/BDArmory/UI/BDArmoryAIGUI.cs b/BDArmory/UI/BDArmoryAIGUI.cs
index fa4270261..2f759843a 100644
--- a/BDArmory/UI/BDArmoryAIGUI.cs
+++ b/BDArmory/UI/BDArmoryAIGUI.cs
@@ -1778,7 +1778,7 @@ void WindowAIGUI(int windowID)
if (Drivertype != (Drivertype = Mathf.RoundToInt(GUI.HorizontalSlider(SettingSliderRect(line++, contentWidth), Drivertype, 0, VehicleMovementTypes.Length - 1))))
{
AI.SurfaceTypeName = VehicleMovementTypes[Drivertype].ToString();
- AI.ChooseOptionsUpdated(null, null);
+ AI.ChooseOptionsUpdated(AI.Fields[nameof(AI.SurfaceTypeName)], AI);
}
if (contextTipsEnabled)
{
@@ -1839,7 +1839,7 @@ void WindowAIGUI(int windowID)
if (broadsideDir != (broadsideDir = Mathf.RoundToInt(GUI.HorizontalSlider(SettingSliderRect(line, contentWidth), broadsideDir, 0, AI.orbitDirections.Length - 1))))
{
AI.SetBroadsideDirection(AI.orbitDirections[broadsideDir]);
- AI.ChooseOptionsUpdated(null, null);
+ AI.ChooseOptionsUpdated(AI.Fields[nameof(AI.OrbitDirectionName)], AI);
}
GUI.Label(SettinglabelRect(line++), StringUtils.Localize("#LOC_BDArmory_AIWindow_PreferredBroadsideDirection") + $": {AI.OrbitDirectionName}", Label);
if (contextTipsEnabled)
diff --git a/BDArmory/Utils/GUIUtils.cs b/BDArmory/Utils/GUIUtils.cs
index a05832092..d9d2daf8b 100644
--- a/BDArmory/Utils/GUIUtils.cs
+++ b/BDArmory/Utils/GUIUtils.cs
@@ -505,7 +505,7 @@ public static bool MouseIsInRect(Rect rect, Vector2 inverseMousePos)
public static void RefreshAssociatedWindows(Part part)
{
if (part == null || part.PartActionWindow == null) return;
- part.PartActionWindow.UpdateWindow();
+ // part.PartActionWindow.UpdateWindow();
// part.PartActionWindow.displayDirty = true;
// IEnumerator<UIPartActionWindow> window = Object.FindObjectsOfType(typeof(UIPartActionWindow)).Cast<UIPartActionWindow>().GetEnumerator();
// while (window.MoveNext())
@@ -536,18 +536,43 @@ public static void RefreshPAWResource(Part part, PartResource resource, bool all
if (resourceUI.Resource != resource) continue;
resourceUI.resourceMax.text = KSPUtil.LocalizeNumber(resource.maxAmount, "F1");
resourceUI.resourceAmnt.text = KSPUtil.LocalizeNumber(resource.amount, "F1");
- if (resourceUI.Window.usingNumericValue)
+ if (resourceUI.Window.NumericSliders)
{
resourceUI.inputField.text = KSPUtil.LocalizeNumber(resource.amount, "#.0##");
}
else
{
- resourceUI.slider.onValueChanged.Invoke(resourceUI.slider.value);
+ // Note: we set the value without triggering callbacks as that is what KSP does to round the slider to a nearest position, which we don't want.
+ resourceUI.slider.SetValueWithoutNotify(Mathf.Lerp(resourceUI.slider.minValue, resourceUI.slider.maxValue, (float)(resource.amount / resource.maxAmount)));
}
if (!all) break;
}
}
+ /// <summary>
+ /// Update a UI_ChooseOption PAW slider when the field value is changed.
+ /// KSP updates most sliders automatically, but not these apparently.
+ /// </summary>
+ /// <param name="field">The field to update. If field is null, then all UI_ChooseOption fields are updated.</param>
+ /// <param name="obj">The partmodule object.</param>
+ public static void UpdateChooseOptionPAW(BaseField field, PartModule obj)
+ {
+ if (obj is null) return;
+ if (field is null)
+ {
+ foreach (var f in obj.Fields)
+ {
+ if ((HighLogic.LoadedSceneIsFlight ? f.uiControlFlight : f.uiControlEditor) is UI_ChooseOption)
+ UpdateChooseOptionPAW(f, obj);
+ }
+ return;
+ }
+ UI_ChooseOption uiControl = (HighLogic.LoadedSceneIsFlight ? field.uiControlFlight : field.uiControlEditor) as UI_ChooseOption;
+ var pawChooseOption = uiControl.partActionItem as UIPartActionChooseOption;
+ if (pawChooseOption is null) return; // Not shown.
+ int newIndex = uiControl.options.IndexOf(field.GetValue(obj));
+ if (newIndex != -1) pawChooseOption.slider.value = newIndex;
+ }
/// <summary>
/// Disable zooming with the scroll wheel if the mouse is over a registered GUI window.
diff --git a/BDArmory/Weapons/Missiles/MissileBase.cs b/BDArmory/Weapons/Missiles/MissileBase.cs
index 6ad8a62bd..d6606ce73 100644
--- a/BDArmory/Weapons/Missiles/MissileBase.cs
+++ b/BDArmory/Weapons/Missiles/MissileBase.cs
@@ -2246,7 +2246,7 @@ public void CruiseAltitudeRange()
cruiseAltitudField.minValue = 500;
cruiseAltitudField.stepIncrement = 500f;
}
- this.part.RefreshAssociatedWindows();
+ // this.part.RefreshAssociatedWindows();
}
public virtual bool HasTurrets() |
Let me guess - setting case on a bin, then changing the bin capacity, CASE change then resets ammo to what the capacity was originally when CASE first added? |
No, moving the CASE setting to 2 and back is sometimes halving the capacity. I didn't look into it much, but something is wrong there. |
|
Giving ModuleAmmoMagazine internal CASE support and having moduleCASE only modify non-adjustable ammobin capacity seems to work; I'm not seeing sudden halving of capacity when moving the CASE level about |
-PAWRefresh fixes. -Move CASE implementation for adjustableAmmo over to ModuleAmmoMagazine. -Fix adjustableBins allowing setting AmmoCapacity slider to 0. -Fix wrong VisualTarget enum type.
fix partMass gaining a ton and breaking hull material mass changes
| public static void RefreshAssociatedWindows(Part part) | ||
| { | ||
| if (part == null || part.PartActionWindow == null) return; | ||
| //public static void RefreshAssociatedWindows(Part part) |
There was a problem hiding this comment.
All the places this was being called from need commenting out too.
We need to do a thorough test to make sure that I haven't missed anything and all the GUIs are updating as expected before we fully remove this. Everything I tested seemed to be working, but I'm not sure I covered everything.
There was a problem hiding this comment.
OK, this is a bit of a big patch. I went through all the places where RefreshAssociatedWindows was being called and checked that things were updating as expected, so these commented out lines can be removed.
However, I also discovered that setting the value of a UI_Toggle or UI_ChooseOption (vs clicking on it) doesn't trigger the onFieldChanged response that other sliders do. This means that when those values are set from the AI GUI, they weren't being properly set in the PAW (the slider value and the actual value were out of sync) and they weren't triggering the onFieldChanged handlers. Similarly, setting these toggles and choose options in one PAW wasn't updating or triggering onFieldChanged handlers in symmetric PAWs.
On top of this, I also found various KSPEvent functions in ModuleWeapon that weren't applying to symmetric parts, when I think they should (at least, I think they should in the editor).
I've fixed all these (except for some auto-tuning toggles in the AI GUI, which I think probably shouldn't be propagated to symmetric parts, at least, not while in flight) and I've added some calls to SetDefaultChooseOptionHandlers and SetDefaultToggleHanders in EngageableWeapon and BDGenericAIBase that set handlers for any UI_Toggle or UI_ChooseOption in derived classes to propagate changes to symmetric parts. If there are some toggles/choose options in those classes that shouldn't apply symmetrically, then we'll need to adjust that, but I think they should all apply symmetrically.
Something else I noticed, but wasn't sure how to fix, is that if you change the "Ordnance Available" in a C-VLS-24 in the SPH, the mini-missiles in it get messed up. I think they end up clipped into each other.
I've attached the diff patch.zip as well as showing it here to make it easier to apply/look through.
Edit (2026-07-29): I've updated the diff for a couple of bugfixes and the changes I mentioned in discord to use BDAPartModule:
diff --git a/BDArmory/Ammo/ModuleAmmoSwitch.cs b/BDArmory/Ammo/ModuleAmmoSwitch.cs
index 7738c9b77..35485cb0e 100644
--- a/BDArmory/Ammo/ModuleAmmoSwitch.cs
+++ b/BDArmory/Ammo/ModuleAmmoSwitch.cs
@@ -7,7 +7,7 @@
namespace BDArmory.Ammo
{
- public class ModuleAmmoSwitch : PartModule, IPartCostModifier
+ public class ModuleAmmoSwitch : BDAPartModule, IPartCostModifier
{
[KSPField]
public string resourceNames = "ElectricCharge;LiquidFuel,Oxidizer;MonoPropellant";
diff --git a/BDArmory/Ammo/ModuleCASE.cs b/BDArmory/Ammo/ModuleCASE.cs
index 620252b66..1684c46c9 100644
--- a/BDArmory/Ammo/ModuleCASE.cs
+++ b/BDArmory/Ammo/ModuleCASE.cs
@@ -16,7 +16,7 @@
namespace BDArmory.Ammo
{
- class ModuleCASE : PartModule, IPartMassModifier, IPartCostModifier
+ class ModuleCASE : BDAPartModule, IPartMassModifier, IPartCostModifier
{
public static Dictionary<int, ObjectPool> detSpheres = new Dictionary<int, ObjectPool>();
GameObject visSphere;
diff --git a/BDArmory/Armor/BDAdjustableArmor.cs b/BDArmory/Armor/BDAdjustableArmor.cs
index 25e37ac9a..846b0dd65 100644
--- a/BDArmory/Armor/BDAdjustableArmor.cs
+++ b/BDArmory/Armor/BDAdjustableArmor.cs
@@ -9,7 +9,7 @@
namespace BDArmory.Armor
{
- public class BDAdjustableArmor : PartModule
+ public class BDAdjustableArmor : BDAPartModule
{
[KSPField(isPersistant = true, guiActive = false, guiActiveEditor = true, guiName = "#LOC_BDArmory_ArmorAdjustParts"),//Move Child Parts
UI_Toggle(disabledText = "#LOC_BDArmory_false", enabledText = "#LOC_BDArmory_true")]//false--true
@@ -63,7 +63,6 @@ void ToggleTriTypeOptionHandler(bool applySym = true, Toggle state = Toggle.Togg
Fields[nameof(Width)].guiName = StringUtils.Localize("#LOC_BDArmory_ArmorWidth");
Events[nameof(ToggleTriTypeOption)].guiName = StringUtils.Localize("#LOC_BDArmory_ArmorTriIso");
}
- GUIUtils.RefreshAssociatedWindows(part);
if (applySym)
{
using (List<Part>.Enumerator sym = part.symmetryCounterparts.GetEnumerator())
@@ -109,7 +108,6 @@ public void ToggleScaleClampHandler(bool applySym = true, Toggle state = Toggle.
{
Events[nameof(ToggleScaleClamp)].guiName = StringUtils.Localize("#LOC_BDArmory_AI_UnclampTuning_disabledText");
}
- GUIUtils.RefreshAssociatedWindows(part);
if (applySym)
{
using (List<Part>.Enumerator sym = part.symmetryCounterparts.GetEnumerator())
@@ -190,7 +188,6 @@ public override void OnStart(StartState state)
armor = GetComponent<HitpointTracker>();
UpdateScale(Width, Length, scaleneWidth, false);
- GUIUtils.RefreshAssociatedWindows(part);
}
void ParseStackNodePosition()
{
diff --git a/BDArmory/Armor/ModuleReactiveArmor.cs b/BDArmory/Armor/ModuleReactiveArmor.cs
index 0f8ea401a..b5288d252 100644
--- a/BDArmory/Armor/ModuleReactiveArmor.cs
+++ b/BDArmory/Armor/ModuleReactiveArmor.cs
@@ -9,7 +9,7 @@
namespace BDArmory.Armor
{
- public class ModuleReactiveArmor : PartModule
+ public class ModuleReactiveArmor : BDAPartModule
{
[KSPField]
public string sectionTransformName = "sections";
diff --git a/BDArmory/BDArmory.csproj b/BDArmory/BDArmory.csproj
index d8f395aed..62c8a9156 100644
--- a/BDArmory/BDArmory.csproj
+++ b/BDArmory/BDArmory.csproj
@@ -240,6 +240,7 @@
<Compile Include="ModIntegration\ReflectionUtils.cs" />
<Compile Include="ModIntegration\SimpleRepaint.cs" />
<Compile Include="Weapons\ModuleAmmoMagazine.cs" />
+ <Compile Include="Modules\BDAPartModule.cs" />
<Compile Include="Modules\CFEnable.cs" />
<Compile Include="Modules\KerbalSafety.cs" />
<Compile Include="Modules\KerbalSuitSelector.cs" />
diff --git a/BDArmory/Control/BDAirspeedControl.cs b/BDArmory/Control/BDAirspeedControl.cs
index 0996d0d88..fdd425f9c 100644
--- a/BDArmory/Control/BDAirspeedControl.cs
+++ b/BDArmory/Control/BDAirspeedControl.cs
@@ -6,7 +6,7 @@
namespace BDArmory.Control
{
- public class BDAirspeedControl : MonoBehaviour //: PartModule
+ public class BDAirspeedControl : MonoBehaviour //: BDAPartModule
{
//[KSPField(isPersistant = false, guiActive = true, guiActiveEditor = false, guiName = "TargetSpeed"),
// UI_FloatRange(minValue = 1f, maxValue = 420f, stepIncrement = 1f, scene = UI_Scene.All)]
@@ -491,7 +491,7 @@ public void SetSecondaryThrottle(float value)
}
}
- public class BDOrbitalControl : MonoBehaviour //: PartModule
+ public class BDOrbitalControl : MonoBehaviour //: BDAPartModule
{
// /////////////////////////////////////////////////////
diff --git a/BDArmory/Control/BDGenericAIBase.cs b/BDArmory/Control/BDGenericAIBase.cs
index f4995015c..e313575f1 100644
--- a/BDArmory/Control/BDGenericAIBase.cs
+++ b/BDArmory/Control/BDGenericAIBase.cs
@@ -20,7 +20,7 @@ namespace BDArmory.Control
/// A base class for implementing AI.
/// Note: You do not have to use it, it is just for convenience, all the game cares about is that you implement the IBDAIControl interface.
/// </summary>
- public abstract class BDGenericAIBase : PartModule, IBDAIControl, IBDWMModule
+ public abstract class BDGenericAIBase : BDAPartModule, IBDAIControl, IBDWMModule
{
#region declarations
public virtual AIType aiType => AIType.GenericAI;
diff --git a/BDArmory/Control/BDModuleOrbitalAI.cs b/BDArmory/Control/BDModuleOrbitalAI.cs
index 72586a847..c2849ca15 100644
--- a/BDArmory/Control/BDModuleOrbitalAI.cs
+++ b/BDArmory/Control/BDModuleOrbitalAI.cs
@@ -457,13 +457,14 @@ public void SetChooseOptions()
{
UI_ChooseOption pidmode = (UI_ChooseOption)(HighLogic.LoadedSceneIsFlight ? Fields[nameof(pidMode)].uiControlFlight : Fields[nameof(pidMode)].uiControlEditor);
pidmode.onFieldChanged = ChooseOptionsUpdated;
+ UI_ChooseOption rolltowards = (UI_ChooseOption)(HighLogic.LoadedSceneIsFlight ? Fields[nameof(rollTowards)].uiControlFlight : Fields[nameof(rollTowards)].uiControlEditor);
+ rolltowards.onFieldChanged = ChooseOptionsUpdated;
}
public void ChooseOptionsUpdated(BaseField field, object obj)
{
- //this.part.RefreshAssociatedWindows();
- GUIUtils.UpdateChooseOptionPAW(field, this);
- if (BDArmoryAIGUI.Instance != null)
+ this.UpdateChooseOptionPAW(field, obj);
+ if (BDArmoryAIGUI.Instance != null && BDArmoryAIGUI.Instance.ActiveAI == this)
{
BDArmoryAIGUI.Instance.SetChooseOptionSliders();
}
diff --git a/BDArmory/Control/BDModulePilotAI.cs b/BDArmory/Control/BDModulePilotAI.cs
index 0bada658b..2941582f4 100644
--- a/BDArmory/Control/BDModulePilotAI.cs
+++ b/BDArmory/Control/BDModulePilotAI.cs
@@ -1558,6 +1558,7 @@ void SetOnDampingTogglesChanged()
public void OnPIDTogglesChanged(BaseField field = null, object obj = null)
{
ToggleDynamicPIDFields(); // Reconfigure the dynamic PID fields in the PAW.
+ if (field != null) this.UpdateToggle(field, obj);
}
public void ToggleDynamicPIDFields()
{
diff --git a/BDArmory/Control/BDModuleSurfaceAI.cs b/BDArmory/Control/BDModuleSurfaceAI.cs
index 4058a7fd6..594c17601 100644
--- a/BDArmory/Control/BDModuleSurfaceAI.cs
+++ b/BDArmory/Control/BDModuleSurfaceAI.cs
@@ -161,7 +161,7 @@ public AIUtils.VehicleMovementType SurfaceType
[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "#LOC_BDArmory_AI_GoesUp", advancedTweakable = true),//Goes up to
UI_Toggle(enabledText = "#LOC_BDArmory_AI_GoesUp_enabledText", disabledText = "#LOC_BDArmory_AI_GoesUp_disabledText", scene = UI_Scene.All),]//eleven--ten
bool upToEleven = false;
- public bool UpToEleven { get { return upToEleven; } set { if (upToEleven != value) { upToEleven = value; TurnItUpToEleven(); } } }
+ public bool UpToEleven { get { return upToEleven; } set { if (upToEleven != (upToEleven = value)) this.UpdateToggle(Fields[nameof(upToEleven)]); } }
const float AttackAngleAtMaxRange = 30f;
@@ -262,10 +262,8 @@ public override void DeactivatePilot()
motorControl.Deactivate();
}
- public void SetChooseOptions()
+ void SetChooseOptions()
{
- UI_ChooseOption broadside = (UI_ChooseOption)(HighLogic.LoadedSceneIsFlight ? Fields[nameof(OrbitDirectionName)].uiControlFlight : Fields[nameof(OrbitDirectionName)].uiControlEditor);
- broadside.onFieldChanged = ChooseOptionsUpdated;
UI_ChooseOption surface = (UI_ChooseOption)(HighLogic.LoadedSceneIsFlight ? Fields[nameof(SurfaceTypeName)].uiControlFlight : Fields[nameof(SurfaceTypeName)].uiControlEditor);
surface.onFieldChanged = ChooseOptionsUpdated;
ChooseOptionsUpdated(null, null);
@@ -299,12 +297,7 @@ public void ChooseOptionsUpdated(BaseField field, object obj)
Fields[nameof(CombatAltitude)].guiActiveEditor = SurfaceType == AIUtils.VehicleMovementType.Submarine;
Fields[nameof(maintainMinRange)].guiActive = SurfaceType == AIUtils.VehicleMovementType.Land;
Fields[nameof(maintainMinRange)].guiActiveEditor = SurfaceType == AIUtils.VehicleMovementType.Land;
- //part.RefreshAssociatedWindows();
- GUIUtils.UpdateChooseOptionPAW(field, this);
- if (BDArmoryAIGUI.Instance != null)
- {
- BDArmoryAIGUI.Instance.SetChooseOptionSliders();
- }
+ this.DefaultChooseOptionHandler(field, obj);
}
public void SetBroadsideDirection(string direction)
@@ -341,6 +334,7 @@ void TurnItUpToEleven(BaseField _field = null, object _obj = null)
field.UpdateLimits(altValues.Item1, altValues.Item2, altValues.Item3);
altSemiLogValues[fieldName] = temp;
}
+ this.UpdateToggle(Fields[nameof(upToEleven)]);
}
IEnumerator SetVar(string name, float value)
diff --git a/BDArmory/Control/BDModuleVTOLAI.cs b/BDArmory/Control/BDModuleVTOLAI.cs
index 9e6186db1..e60de1c1a 100644
--- a/BDArmory/Control/BDModuleVTOLAI.cs
+++ b/BDArmory/Control/BDModuleVTOLAI.cs
@@ -277,9 +277,8 @@ public void SetChooseOptions()
public void ChooseOptionsUpdated(BaseField field, object obj)
{
- //this.part.RefreshAssociatedWindows();
- GUIUtils.UpdateChooseOptionPAW(field, this);
- if (BDArmoryAIGUI.Instance != null)
+ this.UpdateChooseOptionPAW(field, obj);
+ if (BDArmoryAIGUI.Instance != null && BDArmoryAIGUI.Instance.ActiveAI == this)
{
BDArmoryAIGUI.Instance.SetChooseOptionSliders();
}
diff --git a/BDArmory/Control/MissileFire.cs b/BDArmory/Control/MissileFire.cs
index 0b85e5367..d0d249714 100644
--- a/BDArmory/Control/MissileFire.cs
+++ b/BDArmory/Control/MissileFire.cs
@@ -25,7 +25,7 @@
namespace BDArmory.Control
{
- public class MissileFire : PartModule
+ public class MissileFire : BDAPartModule
{
#region Declarations
diff --git a/BDArmory/Control/ModuleWingCommander.cs b/BDArmory/Control/ModuleWingCommander.cs
index 8a1812d33..917ea1270 100644
--- a/BDArmory/Control/ModuleWingCommander.cs
+++ b/BDArmory/Control/ModuleWingCommander.cs
@@ -14,7 +14,7 @@
namespace BDArmory.Control
{
- public class ModuleWingCommander : PartModule
+ public class ModuleWingCommander : BDAPartModule
{
public MissileFire WeaponManager
{
diff --git a/BDArmory/CounterMeasure/CMDropper.cs b/BDArmory/CounterMeasure/CMDropper.cs
index dd9384a6e..e39845e28 100644
--- a/BDArmory/CounterMeasure/CMDropper.cs
+++ b/BDArmory/CounterMeasure/CMDropper.cs
@@ -14,7 +14,7 @@
namespace BDArmory.CounterMeasure
{
- public class CMDropper : PartModule
+ public class CMDropper : BDAPartModule
{
public static ObjectPool flarePool;
public static ObjectPool chaffPool;
diff --git a/BDArmory/CounterMeasure/ModuleCloakingDevice.cs b/BDArmory/CounterMeasure/ModuleCloakingDevice.cs
index b2b6a6bdc..afa1bde97 100644
--- a/BDArmory/CounterMeasure/ModuleCloakingDevice.cs
+++ b/BDArmory/CounterMeasure/ModuleCloakingDevice.cs
@@ -5,7 +5,7 @@
namespace BDArmory.CounterMeasure
{
- public class ModuleCloakingDevice : PartModule
+ public class ModuleCloakingDevice : BDAPartModule
{
Coroutine cloakRoutine;
Coroutine decloakRoutine;
diff --git a/BDArmory/CounterMeasure/ModuleECMJammer.cs b/BDArmory/CounterMeasure/ModuleECMJammer.cs
index 4960e3ae7..b141c0f09 100644
--- a/BDArmory/CounterMeasure/ModuleECMJammer.cs
+++ b/BDArmory/CounterMeasure/ModuleECMJammer.cs
@@ -5,7 +5,7 @@
namespace BDArmory.CounterMeasure
{
- public class ModuleECMJammer : PartModule
+ public class ModuleECMJammer : BDAPartModule
{
[KSPField] public float jammerStrength = 700;
diff --git a/BDArmory/Damage/HitpointTracker.cs b/BDArmory/Damage/HitpointTracker.cs
index df9a91424..87c6b31a5 100644
--- a/BDArmory/Damage/HitpointTracker.cs
+++ b/BDArmory/Damage/HitpointTracker.cs
@@ -15,7 +15,7 @@
namespace BDArmory.Damage
{
- public class HitpointTracker : PartModule, IPartMassModifier, IPartCostModifier
+ public class HitpointTracker : BDAPartModule, IPartMassModifier, IPartCostModifier
{
#region KSP Fields
public float GetModuleMass(float baseMass, ModifierStagingSituation situation) => armorMass + HullMassAdjust;
@@ -390,7 +390,6 @@ public override void OnStart(StartState state)
HullTypeNum = HullInfo.materials.FindIndex(t => t.name == "Aluminium") + 1;
}
SetHullMass();
- //part.RefreshAssociatedWindows();
}
if (HighLogic.LoadedSceneIsFlight || HighLogic.LoadedSceneIsEditor)
{
diff --git a/BDArmory/Damage/ModuleDrainEC.cs b/BDArmory/Damage/ModuleDrainEC.cs
index 66cb92f7e..640d25698 100644
--- a/BDArmory/Damage/ModuleDrainEC.cs
+++ b/BDArmory/Damage/ModuleDrainEC.cs
@@ -18,7 +18,7 @@
namespace BDArmory.Damage
{
- public class ModuleDrainEC : PartModule
+ public class ModuleDrainEC : BDAPartModule
{
public float incomingDamage = 0; //damage from EMP source
public float EMPDamage = 0; //total EMP buildup accrued
diff --git a/BDArmory/Damage/ModuleDrainIntakes.cs b/BDArmory/Damage/ModuleDrainIntakes.cs
index c97b7ec7e..074f5e97e 100644
--- a/BDArmory/Damage/ModuleDrainIntakes.cs
+++ b/BDArmory/Damage/ModuleDrainIntakes.cs
@@ -5,7 +5,7 @@
namespace BDArmory.Damage
{
- public class ModuleDrainIntakes : PartModule
+ public class ModuleDrainIntakes : BDAPartModule
{
public float drainRate = 999;
public float drainDuration = 20;
diff --git a/BDArmory/Damage/ModuleMassAdjust.cs b/BDArmory/Damage/ModuleMassAdjust.cs
index 01b1ea47c..f58887cb8 100644
--- a/BDArmory/Damage/ModuleMassAdjust.cs
+++ b/BDArmory/Damage/ModuleMassAdjust.cs
@@ -5,7 +5,7 @@
namespace BDArmory.Damage
{
- public class ModuleMassAdjust : PartModule, IPartMassModifier
+ public class ModuleMassAdjust : BDAPartModule, IPartMassModifier
{
public float GetModuleMass(float baseMass, ModifierStagingSituation situation) => massMod;
public ModifierChangeWhen GetModuleMassChangeWhen() => ModifierChangeWhen.CONSTANTLY;
diff --git a/BDArmory/Extensions/ClawExtensions.cs b/BDArmory/Extensions/ClawExtensions.cs
index a56ecb31d..788f51c80 100644
--- a/BDArmory/Extensions/ClawExtensions.cs
+++ b/BDArmory/Extensions/ClawExtensions.cs
@@ -5,7 +5,7 @@
namespace BDArmory.Extensions
{
- public class ClawExtension : PartModule
+ public class ClawExtension : BDAPartModule
{
[KSPAction("Toggle Free Pivot")]
public void AGToggleFreePivot(KSPActionParam param)
diff --git a/BDArmory/FX/FireFX.cs b/BDArmory/FX/FireFX.cs
index 72fa9cd1c..b9edea806 100644
--- a/BDArmory/FX/FireFX.cs
+++ b/BDArmory/FX/FireFX.cs
@@ -444,7 +444,6 @@ void Detonate()
ec.maxAmount = 0;
ec.isVisible = false;
if (!parentBeingDestroyed) parentPart.RemoveResource(ec);//destroy battery. not calling part.destroy, since some batteries in cockpits.
- GUIUtils.RefreshAssociatedWindows(parentPart);
}
//tntMassEquivilent *= BDArmorySettings.BD_AMMO_DMG_MULT; //handled by EXP_DMG_MOD_BATTLE_DAMAGE
if (BDArmorySettings.DEBUG_OTHER && tntMassEquivalent > 0)
diff --git a/BDArmory/GameModes/ModuleSpaceFriction.cs b/BDArmory/GameModes/ModuleSpaceFriction.cs
index 3fc7f622f..e2848d465 100644
--- a/BDArmory/GameModes/ModuleSpaceFriction.cs
+++ b/BDArmory/GameModes/ModuleSpaceFriction.cs
@@ -9,7 +9,7 @@
namespace BDArmory.GameModes
{
- public class ModuleSpaceFriction : PartModule
+ public class ModuleSpaceFriction : BDAPartModule
{
/// <summary>
/// Adds friction/drag to craft in null-atmo porportional to AI MaxSpeed setting to ensure craft does not exceed said speed
diff --git a/BDArmory/GameModes/Mutators/BDAMutator.cs b/BDArmory/GameModes/Mutators/BDAMutator.cs
index 6896273b7..4e3c9f119 100644
--- a/BDArmory/GameModes/Mutators/BDAMutator.cs
+++ b/BDArmory/GameModes/Mutators/BDAMutator.cs
@@ -15,7 +15,7 @@
namespace BDArmory.GameModes
{
- class BDAMutator : PartModule
+ class BDAMutator : BDAPartModule
{
float startTime;
bool mutatorEnabled = false;
@@ -255,7 +255,7 @@ public void DisableMutator()
weapon.Current.roundsPerMinute = weapon.Current.baseRPM;
weapon.Current.instagib = false;
weapon.Current.strengthMutator = 1;
- weapon.Current.SetupAmmo(null, null);
+ weapon.Current.SetupAmmo(null, null, false);
weapon.Current.resourceSteal = false;
}
if (engineMult != 1)
diff --git a/BDArmory/Modules/CFEnable.cs b/BDArmory/Modules/CFEnable.cs
index 1ec7bbf37..bcba92cff 100644
--- a/BDArmory/Modules/CFEnable.cs
+++ b/BDArmory/Modules/CFEnable.cs
@@ -3,7 +3,7 @@
namespace BDArmory.Modules
{
- public class CFEnable : PartModule
+ public class CFEnable : BDAPartModule
{
// belt-and-suspenders: do this everywhere and everywhen.
public override void OnLoad(ConfigNode node)
diff --git a/BDArmory/Modules/KerbalSuitSelector.cs b/BDArmory/Modules/KerbalSuitSelector.cs
index a1f8a6bf3..e65a1c7a3 100644
--- a/BDArmory/Modules/KerbalSuitSelector.cs
+++ b/BDArmory/Modules/KerbalSuitSelector.cs
@@ -1,4 +1,5 @@
using System;
+using BDArmory.Utils;
namespace BDArmory.Modules
{
@@ -6,7 +7,7 @@ namespace BDArmory.Modules
/// This allows setting the suit worn by EVA kerbals if spawned via BDArmory or via going EVA from a part.
/// EVA kerbals can't have their suits changed once spawned.
/// </summary>
- public class KerbalSuitSelector : PartModule
+ public class KerbalSuitSelector : BDAPartModule
{
/// <summary>
/// Same as ProtoCrewMember.KerbalSuit, but with an extra "Random" option.
@@ -76,6 +77,7 @@ void OnSuitChanged(BaseField field = null, object obj = null)
Suit = Enum.IsDefined(typeof(ProtoCrewMember.KerbalSuit), (ProtoCrewMember.KerbalSuit)suitType) ?
(ProtoCrewMember.KerbalSuit)suitType :
(ProtoCrewMember.KerbalSuit)UnityEngine.Random.Range(0, 4);
+ this.UpdateChooseOptionPAW(field, obj);
}
/// <summary>
diff --git a/BDArmory/Modules/ModuleHMD.cs b/BDArmory/Modules/ModuleHMD.cs
index 69f8e587a..b27a119bc 100644
--- a/BDArmory/Modules/ModuleHMD.cs
+++ b/BDArmory/Modules/ModuleHMD.cs
@@ -13,7 +13,7 @@
namespace BDArmory.Modules
{
- public class ModuleHMD : PartModule, IPartCostModifier
+ public class ModuleHMD : BDAPartModule, IPartCostModifier
{
public float GetModuleCost(float defaultCost, ModifierStagingSituation situation)
{
@@ -40,7 +40,6 @@ public void ToggleHMD()
Events[nameof(ToggleHMD)].guiName = StringUtils.Localize("#LOC_BDArmory_HMD_Off");//"Remove HMD"
_HMDCost = BDArmorySettings.HMDCost + BDArmorySettings.HMDCostPerSeat * part.CrewCapacity;
}
- GUIUtils.RefreshAssociatedWindows(part);
using (List<Part>.Enumerator pSym = part.symmetryCounterparts.GetEnumerator())
while (pSym.MoveNext())
{
@@ -61,7 +60,6 @@ public void ToggleHMD()
HMDSym.Events[nameof(ToggleHMD)].guiName = StringUtils.Localize("#LOC_BDArmory_HMD_Off");//"Disable self-sealing tank"
HMDSym._HMDCost = BDArmorySettings.HMDCost + BDArmorySettings.HMDCostPerSeat * part.CrewCapacity;
}
- GUIUtils.RefreshAssociatedWindows(pSym.Current);
}
if (HighLogic.LoadedSceneIsEditor && EditorLogic.fetch != null)
GameEvents.onEditorShipModified.Fire(EditorLogic.fetch.ship);
@@ -89,7 +87,6 @@ public void Start()
}
else part.RemoveModule(this); //don't assign to drone cores
}
- GUIUtils.RefreshAssociatedWindows(part);
if (HighLogic.LoadedSceneIsEditor && EditorLogic.fetch != null)
GameEvents.onEditorShipModified.Fire(EditorLogic.fetch.ship);
if (HighLogic.LoadedSceneIsFlight)
diff --git a/BDArmory/Modules/ModuleMovingPart.cs b/BDArmory/Modules/ModuleMovingPart.cs
index 9aa56854e..409f2b313 100644
--- a/BDArmory/Modules/ModuleMovingPart.cs
+++ b/BDArmory/Modules/ModuleMovingPart.cs
@@ -6,7 +6,7 @@
namespace BDArmory.Modules
{
- public class ModuleMovingPart : PartModule
+ public class ModuleMovingPart : BDAPartModule
{
Transform parentTransform;
[KSPField] public string parentTransformName = string.Empty;
diff --git a/BDArmory/Modules/ModuleSelfSealingTank.cs b/BDArmory/Modules/ModuleSelfSealingTank.cs
index 2048efa63..1dcb6036f 100644
--- a/BDArmory/Modules/ModuleSelfSealingTank.cs
+++ b/BDArmory/Modules/ModuleSelfSealingTank.cs
@@ -13,7 +13,7 @@
namespace BDArmory.Modules
{
- class ModuleSelfSealingTank : PartModule, IPartMassModifier
+ class ModuleSelfSealingTank : BDAPartModule, IPartMassModifier
{
public float GetModuleMass(float baseMass, ModifierStagingSituation situation)
{
@@ -119,7 +119,6 @@ public void ToggleInertOption()
Fields[nameof(FBRemaining)].guiActive = false;
}
partmass = (FISmass + ArmorMass + FBmass);
- GUIUtils.RefreshAssociatedWindows(part);
using (List<Part>.Enumerator pSym = part.symmetryCounterparts.GetEnumerator())
while (pSym.MoveNext())
{
@@ -145,7 +144,6 @@ public void ToggleInertOption()
tank.Fields[nameof(FBRemaining)].guiActive = false;
}
tank.partmass = (tank.FISmass + tank.ArmorMass + tank.FBmass);
- GUIUtils.RefreshAssociatedWindows(pSym.Current);
}
if (HighLogic.LoadedSceneIsEditor && EditorLogic.fetch != null)
GameEvents.onEditorShipModified.Fire(EditorLogic.fetch.ship);
@@ -169,7 +167,6 @@ public void TogglecockpitArmor()
ArmorMass = 0.2f * part.CrewCapacity;
}
partmass = (FISmass + ArmorMass + FBmass);
- GUIUtils.RefreshAssociatedWindows(part);
using (List<Part>.Enumerator pSym = part.symmetryCounterparts.GetEnumerator())
while (pSym.MoveNext())
{
@@ -191,7 +188,6 @@ public void TogglecockpitArmor()
tank.ArmorMass = 0.2f * part.CrewCapacity;
}
tank.partmass = (tank.FISmass + tank.ArmorMass + tank.FBmass);
- GUIUtils.RefreshAssociatedWindows(pSym.Current);
}
if (HighLogic.LoadedSceneIsEditor && EditorLogic.fetch != null)
GameEvents.onEditorShipModified.Fire(EditorLogic.fetch.ship);
@@ -337,7 +333,6 @@ public void Start()
Fields[nameof(FireBottles)].guiActiveEditor = false;
Fields[nameof(FBRemaining)].guiActive = false;
}
- GUIUtils.RefreshAssociatedWindows(part);
partmass = (FISmass + ArmorMass + FBmass);
if (HighLogic.LoadedSceneIsEditor && EditorLogic.fetch != null)
GameEvents.onEditorShipModified.Fire(EditorLogic.fetch.ship);
@@ -453,9 +448,7 @@ void FBSetup(BaseField field, object obj)
tank.FBRemaining = FBRemaining;
tank.partmass = partmass + FISmass + ArmorMass;
tank.externallyCalled = false;
- GUIUtils.RefreshAssociatedWindows(pSym.Current);
}
- GUIUtils.RefreshAssociatedWindows(part);
}
public override string GetInfo()
@@ -526,7 +519,6 @@ IEnumerator ExtinguishRoutine(float time, bool useBottle)
{
FireBottles--;
FBRemaining = FireBottles;
- GUIUtils.RefreshAssociatedWindows(part);
//Debug.Log("[BDArmory.SelfSealingTank]: Consuming firebottle. FB remaining: " + FireBottles);
isOnFire = false;
}
diff --git a/BDArmory/Radar/ModuleIRST.cs b/BDArmory/Radar/ModuleIRST.cs
index e84c49ecf..9da5ec82c 100644
--- a/BDArmory/Radar/ModuleIRST.cs
+++ b/BDArmory/Radar/ModuleIRST.cs
@@ -15,7 +15,7 @@
namespace BDArmory.Radar
{
- public class ModuleIRST : PartModule
+ public class ModuleIRST : BDAPartModule
{
#region KSPFields (Part Configuration)
diff --git a/BDArmory/Radar/ModuleRadar.cs b/BDArmory/Radar/ModuleRadar.cs
index ed6020b20..7b1a041de 100644
--- a/BDArmory/Radar/ModuleRadar.cs
+++ b/BDArmory/Radar/ModuleRadar.cs
@@ -15,7 +15,7 @@
namespace BDArmory.Radar
{
- public class ModuleRadar : PartModule
+ public class ModuleRadar : BDAPartModule
{
#region KSPFields (Part Configuration)
diff --git a/BDArmory/Radar/RadarWarningReceiver.cs b/BDArmory/Radar/RadarWarningReceiver.cs
index ea7e1c3f4..4abbd179a 100644
--- a/BDArmory/Radar/RadarWarningReceiver.cs
+++ b/BDArmory/Radar/RadarWarningReceiver.cs
@@ -17,7 +17,7 @@
namespace BDArmory.Radar
{
- public class RadarWarningReceiver : PartModule
+ public class RadarWarningReceiver : BDAPartModule
{
public delegate void RadarPing(Vessel v, Vector3 source, RWRThreatTypes type, float persistTime, Vessel vSource);
diff --git a/BDArmory/Targeting/ModuleTargetingCamera.cs b/BDArmory/Targeting/ModuleTargetingCamera.cs
index 21412dcbc..09b81aa84 100644
--- a/BDArmory/Targeting/ModuleTargetingCamera.cs
+++ b/BDArmory/Targeting/ModuleTargetingCamera.cs
@@ -16,7 +16,7 @@
namespace BDArmory.Targeting
{
- public class ModuleTargetingCamera : PartModule
+ public class ModuleTargetingCamera : BDAPartModule
{
[KSPField]
public string cameraTransformName;
diff --git a/BDArmory/UI/BDAmmoSelector.cs b/BDArmory/UI/BDAmmoSelector.cs
index 9b69bc1e9..2ed73632a 100644
--- a/BDArmory/UI/BDAmmoSelector.cs
+++ b/BDArmory/UI/BDAmmoSelector.cs
@@ -170,7 +170,7 @@ void CloseWindowNow()
string[] applyWeaponGroupTo;
string _applyWeaponGroupTo;
- int _applyWeaponGroupToIndex = 0;
+ int _applyWeaponGroupToIndex = 1; // Default to symmetric belts.
protected virtual void OnGUI()
{
if (save)
diff --git a/BDArmory/UI/BDArmoryAIGUI.cs b/BDArmory/UI/BDArmoryAIGUI.cs
index 2f759843a..bcc5a31e2 100644
--- a/BDArmory/UI/BDArmoryAIGUI.cs
+++ b/BDArmory/UI/BDArmoryAIGUI.cs
@@ -1334,10 +1334,12 @@ void WindowAIGUI(int windowID)
inputFields["maxAltitude"].SetCurrentValue(AI.maxAltitude);
}
- AI.hardMinAltitude = GUI.Toggle(ToggleButtonRects(altLines, 0, 2, contentWidth), AI.hardMinAltitude,
- StringUtils.Localize("#LOC_BDArmory_AI_HardMinAltitude"), AI.hardMinAltitude ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);//"Hard Min Altitude"
- AI.maxAltitudeToggle = GUI.Toggle(ToggleButtonRects(altLines, 1, 2, contentWidth), AI.maxAltitudeToggle,
- StringUtils.Localize("#LOC_BDArmory_AIWindow_MaxAltitude"), AI.maxAltitudeToggle ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);//"max altitude AGL"
+ if (AI.hardMinAltitude != (AI.hardMinAltitude = GUI.Toggle(ToggleButtonRects(altLines, 0, 2, contentWidth), AI.hardMinAltitude,
+ StringUtils.Localize("#LOC_BDArmory_AI_HardMinAltitude"), AI.hardMinAltitude ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))//"Hard Min Altitude"
+ AI.UpdateToggle(AI.Fields[nameof(AI.hardMinAltitude)]);
+ if (AI.maxAltitudeToggle != (AI.maxAltitudeToggle = GUI.Toggle(ToggleButtonRects(altLines, 1, 2, contentWidth), AI.maxAltitudeToggle,
+ StringUtils.Localize("#LOC_BDArmory_AIWindow_MaxAltitude"), AI.maxAltitudeToggle ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))//"max altitude AGL"
+ AI.UpdateToggle(AI.Fields[nameof(AI.maxAltitudeToggle)]);
altLines += 1.25f;
if (AI.maxAltitudeToggle)
@@ -1415,7 +1417,8 @@ void WindowAIGUI(int windowID)
GUI.BeginGroup(new(contentBorder, contentHeight + bombingLines * entryHeight, contentWidth, sectionHeight * entryHeight), GUIContent.none, BDArmorySetup.SelectedButtonStyle);
bombingLines += 0.25f;
- AI.divebombing = GUI.Toggle(ToggleButtonRects(bombingLines, 0, 2, contentWidth), AI.divebombing, StringUtils.Localize("#LOC_BDArmory_AIWindow_DiveBomb"), AI.divebombing ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);
+ if (AI.divebombing != (AI.divebombing = GUI.Toggle(ToggleButtonRects(bombingLines, 0, 2, contentWidth), AI.divebombing, StringUtils.Localize("#LOC_BDArmory_AIWindow_DiveBomb"), AI.divebombing ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))
+ AI.UpdateToggle(AI.Fields[nameof(AI.divebombing)]);
bombingLines += 1.25f;
bombingLines = ContentEntry(ContentType.FloatSlider, bombingLines, contentWidth, ref AI.bombingAltitude, nameof(AI.bombingAltitude), "BombingAltitude", $"{AI.bombingAltitude:0}m");
@@ -1467,10 +1470,12 @@ void WindowAIGUI(int windowID)
evadeLines = ContentEntry(ContentType.SemiLogSlider, evadeLines, contentWidth, ref AI.evasionMinRangeThreshold, nameof(AI.evasionMinRangeThreshold), "EvasionMinRangeThreshold", AI.evasionMinRangeThreshold < 1000 ? $"{AI.evasionMinRangeThreshold:0}m" : $"{AI.evasionMinRangeThreshold / 1000:0}km");
evadeLines = ContentEntry(ContentType.FloatSlider, evadeLines, contentWidth, ref AI.evasionNonlinearity, nameof(AI.evasionNonlinearity), "EvasionNonlinearity", $"{AI.evasionNonlinearity:0.0}°");
- AI.evasionIgnoreMyTargetTargetingMe = GUI.Toggle(ToggleButtonRect(evadeLines, contentWidth), AI.evasionIgnoreMyTargetTargetingMe, StringUtils.Localize("#LOC_BDArmory_AI_EvasionIgnoreMyTargetTargetingMe"), AI.evasionIgnoreMyTargetTargetingMe ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);
+ if (AI.evasionIgnoreMyTargetTargetingMe != (AI.evasionIgnoreMyTargetTargetingMe = GUI.Toggle(ToggleButtonRect(evadeLines, contentWidth), AI.evasionIgnoreMyTargetTargetingMe, StringUtils.Localize("#LOC_BDArmory_AI_EvasionIgnoreMyTargetTargetingMe"), AI.evasionIgnoreMyTargetTargetingMe ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))
+ AI.UpdateToggle(AI.Fields[nameof(AI.evasionIgnoreMyTargetTargetingMe)]);
evadeLines += 1.25f;
- AI.evasionMissileKinematic = GUI.Toggle(ToggleButtonRect(evadeLines, contentWidth), AI.evasionMissileKinematic, StringUtils.Localize("#LOC_BDArmory_AI_EvasionMissileKinematic"), AI.evasionMissileKinematic ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);
+ if (AI.evasionMissileKinematic != (AI.evasionMissileKinematic = GUI.Toggle(ToggleButtonRect(evadeLines, contentWidth), AI.evasionMissileKinematic, StringUtils.Localize("#LOC_BDArmory_AI_EvasionMissileKinematic"), AI.evasionMissileKinematic ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))
+ AI.UpdateToggle(AI.Fields[nameof(AI.evasionMissileKinematic)]);
evadeLines += 1.25f;
evadeLines = ContentEntry(ContentType.FloatSlider, evadeLines, contentWidth, ref AI.evasionMissileEmergencyNotchVel, nameof(AI.evasionMissileEmergencyNotchVel), "EvasionMissileEmergencyNotch", $"{AI.evasionMissileEmergencyNotchVel:0.0} m/s");
#endregion
@@ -1500,7 +1505,8 @@ void WindowAIGUI(int windowID)
evadeLines = ContentEntry(ContentType.FloatSlider, evadeLines, contentWidth, ref AI.extendAbortTime, nameof(AI.extendAbortTime), "ExtendAbortTime", $"{AI.extendAbortTime:0}s");
evadeLines = ContentEntry(ContentType.FloatSlider, evadeLines, contentWidth, ref AI.extendMinGainRate, nameof(AI.extendMinGainRate), "ExtendMinGainRate", $"{AI.extendMinGainRate:0}m/s");
}
- AI.canExtend = GUI.Toggle(ToggleButtonRect(evadeLines, contentWidth), AI.canExtend, StringUtils.Localize("#LOC_BDArmory_AI_ExtendToggle"), AI.canExtend ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);//"Dynamic pid"
+ if (AI.canExtend != (AI.canExtend = GUI.Toggle(ToggleButtonRect(evadeLines, contentWidth), AI.canExtend, StringUtils.Localize("#LOC_BDArmory_AI_ExtendToggle"), AI.canExtend ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))//"Dynamic pid"
+ AI.UpdateToggle(AI.Fields[nameof(AI.canExtend)]);
evadeLines += 1.25f;
#endregion
@@ -1558,14 +1564,16 @@ void WindowAIGUI(int windowID)
GUI.Label(SettinglabelRect(ramLines++), StringUtils.Localize("#LOC_BDArmory_AIWindow_Ramming"), BoldLabel);//"Ramming"
- AI.allowRamming = GUI.Toggle(ToggleButtonRect(ramLines, contentWidth), AI.allowRamming,
- StringUtils.Localize("#LOC_BDArmory_AI_AllowRamming"), AI.allowRamming ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);//"Allow Ramming"
+ if (AI.allowRamming != (AI.allowRamming = GUI.Toggle(ToggleButtonRect(ramLines, contentWidth), AI.allowRamming,
+ StringUtils.Localize("#LOC_BDArmory_AI_AllowRamming"), AI.allowRamming ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))//"Allow Ramming"
+ AI.UpdateToggle(AI.Fields[nameof(AI.allowRamming)]);
ramLines += 1.25f;
if (AI.allowRamming)
{
- AI.allowRammingGroundTargets = GUI.Toggle(ToggleButtonRect(ramLines, contentWidth), AI.allowRammingGroundTargets,
- StringUtils.Localize("#LOC_BDArmory_AI_AllowRammingGroundTargets"), AI.allowRammingGroundTargets ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);//"Include Ground Targets"
+ if (AI.allowRammingGroundTargets != (AI.allowRammingGroundTargets = GUI.Toggle(ToggleButtonRect(ramLines, contentWidth), AI.allowRammingGroundTargets,
+ StringUtils.Localize("#LOC_BDArmory_AI_AllowRammingGroundTargets"), AI.allowRammingGroundTargets ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))//"Include Ground Targets"
+ AI.UpdateToggle(AI.Fields[nameof(AI.allowRammingGroundTargets)]);
ramLines += 1.25f;
ramLines = ContentEntry(ContentType.FloatSlider, ramLines, contentWidth, ref AI.controlSurfaceLag, nameof(AI.controlSurfaceLag), "ControlSurfaceLag", $"{AI.controlSurfaceLag:0.00}s");
}
@@ -1583,15 +1591,16 @@ void WindowAIGUI(int windowID)
miscLines += 0.25f;
GUI.Label(SettinglabelRect(miscLines++), StringUtils.Localize("#LOC_BDArmory_AI_Orbit"), BoldLabel);//"orbit"
- AI.ClockwiseOrbit = GUI.Toggle(ToggleButtonRect(miscLines, contentWidth), AI.ClockwiseOrbit,
+ if (AI.ClockwiseOrbit != (AI.ClockwiseOrbit = GUI.Toggle(ToggleButtonRect(miscLines, contentWidth), AI.ClockwiseOrbit,
AI.ClockwiseOrbit ? StringUtils.Localize("#LOC_BDArmory_AI_Orbit_Starboard") : StringUtils.Localize("#LOC_BDArmory_AI_Orbit_Port"),
- AI.ClockwiseOrbit ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);
+ AI.ClockwiseOrbit ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))
+ AI.UpdateToggle(AI.Fields[nameof(AI.ClockwiseOrbit)]);
miscLines += 1.25f;
if (contextTipsEnabled) GUI.Label(ContextLabelRect(miscLines++), StringUtils.Localize("#LOC_BDArmory_AIWindow_Orbit_Context"), Label);//"orbit direction"
GUI.Label(SettinglabelRect(miscLines++), StringUtils.Localize("#LOC_BDArmory_AI_Standby"), BoldLabel);//"Standby"
- AI.standbyMode = GUI.Toggle(ToggleButtonRect(miscLines, contentWidth),
- AI.standbyMode, AI.standbyMode ? StringUtils.Localize("#LOC_BDArmory_On") : StringUtils.Localize("#LOC_BDArmory_Off"), AI.standbyMode ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);//"Dynamic pid"
+ if (AI.standbyMode != (AI.standbyMode = GUI.Toggle(ToggleButtonRect(miscLines, contentWidth), AI.standbyMode, AI.standbyMode ? StringUtils.Localize("#LOC_BDArmory_On") : StringUtils.Localize("#LOC_BDArmory_Off"), AI.standbyMode ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))
+ AI.UpdateToggle(AI.Fields[nameof(AI.standbyMode)]);
miscLines += 1.25f;
if (contextTipsEnabled) GUI.Label(ContextLabelRect(miscLines++), StringUtils.Localize("#LOC_BDArmory_AIWindow_Standby_Context"), Label);//"Activate when target in guard range"
@@ -1778,7 +1787,7 @@ void WindowAIGUI(int windowID)
if (Drivertype != (Drivertype = Mathf.RoundToInt(GUI.HorizontalSlider(SettingSliderRect(line++, contentWidth), Drivertype, 0, VehicleMovementTypes.Length - 1))))
{
AI.SurfaceTypeName = VehicleMovementTypes[Drivertype].ToString();
- AI.ChooseOptionsUpdated(AI.Fields[nameof(AI.SurfaceTypeName)], AI);
+ AI.UpdateChooseOptionPAW(AI.Fields[nameof(AI.SurfaceTypeName)]);
}
if (contextTipsEnabled)
{
@@ -1839,7 +1848,7 @@ void WindowAIGUI(int windowID)
if (broadsideDir != (broadsideDir = Mathf.RoundToInt(GUI.HorizontalSlider(SettingSliderRect(line, contentWidth), broadsideDir, 0, AI.orbitDirections.Length - 1))))
{
AI.SetBroadsideDirection(AI.orbitDirections[broadsideDir]);
- AI.ChooseOptionsUpdated(AI.Fields[nameof(AI.OrbitDirectionName)], AI);
+ AI.UpdateChooseOptionPAW(AI.Fields[nameof(AI.OrbitDirectionName)]);
}
GUI.Label(SettinglabelRect(line++), StringUtils.Localize("#LOC_BDArmory_AIWindow_PreferredBroadsideDirection") + $": {AI.OrbitDirectionName}", Label);
if (contextTipsEnabled)
@@ -1847,9 +1856,10 @@ void WindowAIGUI(int windowID)
GUI.Label(ContextLabelRect(line++), StringUtils.Localize("#LOC_BDArmory_AIWindow_PreferredBroadsideDirection_Context"), contextLabel);
}
- AI.ManeuverRCS = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.ManeuverRCS,
+ if (AI.ManeuverRCS != (AI.ManeuverRCS = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.ManeuverRCS,
StringUtils.Localize("#LOC_BDArmory_AIWindow_ManeuverRCS") + " : " + (AI.ManeuverRCS ? StringUtils.Localize("#LOC_BDArmory_AI_ManeuverRCS_enabledText") : StringUtils.Localize("#LOC_BDArmory_AI_ManeuverRCS_disabledText")),
- AI.ManeuverRCS ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);
+ AI.ManeuverRCS ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))
+ AI.UpdateToggle(AI.Fields[nameof(AI.ManeuverRCS)]);
line += 1.25f;
if (contextTipsEnabled)
{
@@ -1878,9 +1888,10 @@ void WindowAIGUI(int windowID)
line = ContentEntry(ContentType.FloatSlider, line, contentWidth, ref AI.WeaveFactor, nameof(AI.WeaveFactor), "WeaveFactor", $"{AI.WeaveFactor:0.0}");
if (AI.SurfaceType == AIUtils.VehicleMovementType.Land)
{
- AI.maintainMinRange = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.maintainMinRange,
+ if (AI.maintainMinRange != (AI.maintainMinRange = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.maintainMinRange,
StringUtils.Localize("#LOC_BDArmory_AIWindow_MaintainEngagementRange") + " : " + (AI.maintainMinRange ? StringUtils.Localize("#LOC_BDArmory_true") : StringUtils.Localize("#LOC_BDArmory_false")),
- AI.maintainMinRange ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);//"Maintain Min range"
+ AI.maintainMinRange ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))//"Maintain Min range"
+ AI.UpdateToggle(AI.Fields[nameof(AI.maintainMinRange)]);
line += 1.25f;
if (contextTipsEnabled)
{
@@ -1888,9 +1899,10 @@ void WindowAIGUI(int windowID)
}
}
- AI.BroadsideAttack = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.BroadsideAttack,
+ if (AI.BroadsideAttack != (AI.BroadsideAttack = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.BroadsideAttack,
StringUtils.Localize("#LOC_BDArmory_AIWindow_BroadsideAttack") + " : " + (AI.BroadsideAttack ? StringUtils.Localize("#LOC_BDArmory_AI_BroadsideAttack_enabledText") : StringUtils.Localize("#LOC_BDArmory_AI_BroadsideAttack_disabledText")),
- AI.BroadsideAttack ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);//Broadside Attack"
+ AI.BroadsideAttack ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))//Broadside Attack"
+ AI.UpdateToggle(AI.Fields[nameof(AI.BroadsideAttack)]);
line += 1.25f;
if (contextTipsEnabled)
{
@@ -2065,16 +2077,17 @@ void WindowAIGUI(int windowID)
if (broadsideDir != (broadsideDir = Mathf.RoundToInt(GUI.HorizontalSlider(SettingSliderRect(line++, contentWidth), broadsideDir, 0, AI.orbitDirections.Length - 1))))
{
AI.SetBroadsideDirection(AI.orbitDirections[broadsideDir]);
- AI.ChooseOptionsUpdated(null, null);
+ AI.UpdateChooseOptionPAW(AI.Fields[nameof(AI.OrbitDirectionName)]);
}
if (contextTipsEnabled)
{
GUI.Label(ContextLabelRect(line++), StringUtils.Localize("#LOC_BDArmory_AIWindow_PreferredBroadsideDirection_Context"), contextLabel);
}
- AI.ManeuverRCS = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.ManeuverRCS,
+ if (AI.ManeuverRCS != (AI.ManeuverRCS = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.ManeuverRCS,
StringUtils.Localize("#LOC_BDArmory_AIWindow_ManeuverRCS") + " : " + (AI.ManeuverRCS ? StringUtils.Localize("#LOC_BDArmory_AI_ManeuverRCS_enabledText") : StringUtils.Localize("#LOC_BDArmory_AI_ManeuverRCS_disabledText")),
- AI.ManeuverRCS ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);
+ AI.ManeuverRCS ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))
+ AI.UpdateToggle(AI.Fields[nameof(AI.ManeuverRCS)]);
line += 1.25f;
if (contextTipsEnabled)
{
@@ -2098,9 +2111,10 @@ void WindowAIGUI(int windowID)
line = ContentEntry(ContentType.FloatSlider, line, contentWidth, ref AI.MinEngagementRange, nameof(AI.MinEngagementRange), "MinEngagementRange", $"{AI.MinEngagementRange:0}m");
line = ContentEntry(ContentType.FloatSlider, line, contentWidth, ref AI.MaxEngagementRange, nameof(AI.MaxEngagementRange), "MaxEngagementRange", $"{AI.MaxEngagementRange:0}m");
- AI.BroadsideAttack = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.BroadsideAttack,
+ if (AI.BroadsideAttack != (AI.BroadsideAttack = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.BroadsideAttack,
StringUtils.Localize("#LOC_BDArmory_AIWindow_BroadsideAttack") + " : " + (AI.BroadsideAttack ? StringUtils.Localize("#LOC_BDArmory_AI_BroadsideAttack_enabledText") : StringUtils.Localize("#LOC_BDArmory_AI_BroadsideAttack_disabledText")),
- AI.BroadsideAttack ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);
+ AI.BroadsideAttack ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))
+ AI.UpdateToggle(AI.Fields[nameof(AI.BroadsideAttack)]);
line += 1.25f;
if (contextTipsEnabled)
{
@@ -2187,7 +2201,7 @@ void WindowAIGUI(int windowID)
if (pidMode != (pidMode = Mathf.RoundToInt(GUI.HorizontalSlider(SettingSliderRect(line++, contentWidth), pidMode, 0, PIDModeTypes.Length - 1))))
{
AI.pidMode = PIDModeTypes[pidMode].ToString();
- AI.ChooseOptionsUpdated(null, null);
+ AI.UpdateChooseOptionPAW(AI.Fields[nameof(AI.pidMode)]);
}
line = ContentEntry(ContentType.FloatSlider, line, contentWidth, ref AI.steerMult, nameof(AI.steerMult), "SteerPower", $"{AI.steerMult:0.0}", true);
line = ContentEntry(ContentType.FloatSlider, line, contentWidth, ref AI.steerKiAdjust, nameof(AI.steerKiAdjust), "SteerKi", $"{AI.steerKiAdjust:0.00}", true);
@@ -2206,9 +2220,12 @@ void WindowAIGUI(int windowID)
GUI.BeginGroup(new Rect(contentBorder, contentHeight + line * entryHeight, contentWidth, sectionHeight * entryHeight), GUIContent.none, BDArmorySetup.SelectedButtonStyle);
line += 0.25f;
- AI.BroadsideAttack = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.BroadsideAttack,
+ if (AI.BroadsideAttack != (AI.BroadsideAttack = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.BroadsideAttack,
StringUtils.Localize("#LOC_BDArmory_AIWindow_BroadsideAttack") + " : " + (AI.BroadsideAttack ? StringUtils.Localize("#LOC_BDArmory_AI_BroadsideAttack_enabledText") : StringUtils.Localize("#LOC_BDArmory_AI_BroadsideAttack_disabledText")),
- AI.BroadsideAttack ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);//Broadside Attack"
+ AI.BroadsideAttack ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle))) //Broadside Attack"
+ {
+ AI.UpdateToggle(AI.Fields[nameof(AI.BroadsideAttack)]);
+ }
line += 1.25f;
if (contextTipsEnabled)
{
@@ -2219,7 +2236,7 @@ void WindowAIGUI(int windowID)
if (rollTowards != (rollTowards = Mathf.RoundToInt(GUI.HorizontalSlider(SettingSliderRect(line++, contentWidth), rollTowards, 0, RollModeTypes.Length - 1))))
{
AI.rollTowards = RollModeTypes[rollTowards].ToString();
- AI.ChooseOptionsUpdated(null, null);
+ AI.UpdateChooseOptionPAW(AI.Fields[nameof(AI.rollTowards)]);
}
var oldMinEngagementRange = AI.MinEngagementRange;
@@ -2240,8 +2257,9 @@ void WindowAIGUI(int windowID)
field.SetCurrentValue(AI.MinEngagementRange);
}
- AI.allowRamming = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.allowRamming,
- StringUtils.Localize("#LOC_BDArmory_AI_AllowRamming"), AI.allowRamming ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);//"Allow Ramming"
+ if (AI.allowRamming != (AI.allowRamming = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.allowRamming,
+ StringUtils.Localize("#LOC_BDArmory_AI_AllowRamming"), AI.allowRamming ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))//"Allow Ramming"
+ AI.UpdateToggle(AI.Fields[nameof(AI.allowRamming)]);
line += 1.25f;
GUI.EndGroup();
@@ -2300,45 +2318,50 @@ void WindowAIGUI(int windowID)
GUI.BeginGroup(new Rect(contentBorder, contentHeight + line * entryHeight, contentWidth, sectionHeight * entryHeight), GUIContent.none, BDArmorySetup.SelectedButtonStyle);
line += 0.25f;
- AI.FiringRCS = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.FiringRCS,
+ if (AI.FiringRCS != (AI.FiringRCS = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.FiringRCS,
StringUtils.Localize("#LOC_BDArmory_AIWindow_FiringRCS") + " : " + (AI.FiringRCS ? StringUtils.Localize("#LOC_BDArmory_AI_FiringRCS_enabledText") : StringUtils.Localize("#LOC_BDArmory_AI_FiringRCS_disabledText")),
- AI.FiringRCS ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);
+ AI.FiringRCS ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))
+ AI.UpdateToggle(AI.Fields[nameof(AI.FiringRCS)]);
line += 1.25f;
if (contextTipsEnabled)
{
GUI.Label(ContextLabelRect(line++), StringUtils.Localize("#LOC_BDArmory_AIWindow_FiringRCS_Context"), contextLabel);
}
- AI.ManeuverRCS = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.ManeuverRCS,
+ if (AI.ManeuverRCS != (AI.ManeuverRCS = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.ManeuverRCS,
StringUtils.Localize("#LOC_BDArmory_AIWindow_ManeuverRCS") + " : " + (AI.ManeuverRCS ? StringUtils.Localize("#LOC_BDArmory_AI_ManeuverRCS_enabledText") : StringUtils.Localize("#LOC_BDArmory_AI_ManeuverRCS_disabledText")),
- AI.ManeuverRCS ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);
+ AI.ManeuverRCS ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))
+ AI.UpdateToggle(AI.Fields[nameof(AI.ManeuverRCS)]);
line += 1.25f;
if (contextTipsEnabled)
{
GUI.Label(ContextLabelRect(line++), StringUtils.Localize("#LOC_BDArmory_AIWindow_ManeuverRCS_Context"), contextLabel);
}
- AI.ReverseThrust = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.ReverseThrust,
+ if (AI.ReverseThrust != (AI.ReverseThrust = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.ReverseThrust,
StringUtils.Localize("#LOC_BDArmory_AIWindow_ReverseEngines") + " : " + (AI.ReverseThrust ? StringUtils.Localize("#LOC_BDArmory_Enabled") : StringUtils.Localize("#LOC_BDArmory_Disabled")),
- AI.ReverseThrust ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);
+ AI.ReverseThrust ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))
+ AI.UpdateToggle(AI.Fields[nameof(AI.ReverseThrust)]);
line += 1.25f;
if (contextTipsEnabled)
{
GUI.Label(ContextLabelRect(line++), StringUtils.Localize("#LOC_BDArmory_AIWindow_ReverseEngines_Context"), contextLabel);
}
- AI.EngineRCSRotation = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.EngineRCSRotation,
+ if (AI.EngineRCSRotation != (AI.EngineRCSRotation = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.EngineRCSRotation,
StringUtils.Localize("#LOC_BDArmory_AIWindow_EngineRCSRotation") + " : " + (AI.EngineRCSRotation ? StringUtils.Localize("#LOC_BDArmory_Enabled") : StringUtils.Localize("#LOC_BDArmory_Disabled")),
- AI.EngineRCSRotation ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);
+ AI.EngineRCSRotation ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))
+ AI.UpdateToggle(AI.Fields[nameof(AI.EngineRCSRotation)]);
line += 1.25f;
if (contextTipsEnabled)
{
GUI.Label(ContextLabelRect(line++), StringUtils.Localize("#LOC_BDArmory_AIWindow_EngineRCSRotation_Context"), contextLabel);
}
- AI.EngineRCSTranslation = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.EngineRCSTranslation,
+ if (AI.EngineRCSTranslation != (AI.EngineRCSTranslation = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.EngineRCSTranslation,
StringUtils.Localize("#LOC_BDArmory_AIWindow_EngineRCSTranslation") + " : " + (AI.EngineRCSTranslation ? StringUtils.Localize("#LOC_BDArmory_Enabled") : StringUtils.Localize("#LOC_BDArmory_Disabled")),
- AI.EngineRCSTranslation ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);
+ AI.EngineRCSTranslation ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))
+ AI.UpdateToggle(AI.Fields[nameof(AI.EngineRCSTranslation)]);
line += 1.25f;
if (contextTipsEnabled)
{
@@ -2363,25 +2386,28 @@ void WindowAIGUI(int windowID)
line = ContentEntry(ContentType.FloatSlider, line, contentWidth, ref AI.evasionTimeThreshold, nameof(AI.evasionTimeThreshold), "EvasionTimeThreshold", $"{AI.evasionTimeThreshold:0.0}s");
line = ContentEntry(ContentType.FloatSlider, line, contentWidth, ref AI.evasionErraticness, nameof(AI.evasionErraticness), "EvasionErraticness", $"{AI.evasionErraticness:0.00}");
line = ContentEntry(ContentType.SemiLogSlider, line, contentWidth, ref AI.evasionMinRangeThreshold, nameof(AI.evasionMinRangeThreshold), "EvasionMinRangeThreshold", AI.evasionMinRangeThreshold < 1000 ? $"{AI.evasionMinRangeThreshold:0}m" : $"{AI.evasionMinRangeThreshold / 1000:0}km");
- AI.evasionRCS = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.evasionRCS,
+ if (AI.evasionRCS != (AI.evasionRCS = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.evasionRCS,
StringUtils.Localize("#LOC_BDArmory_AIWindow_EvasionRCS") + " : " + (AI.evasionRCS ? StringUtils.Localize("#LOC_BDArmory_Enabled") : StringUtils.Localize("#LOC_BDArmory_Disabled")),
- AI.evasionRCS ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);
+ AI.evasionRCS ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))
+ AI.UpdateToggle(AI.Fields[nameof(AI.evasionRCS)]);
line += 1.25f;
if (contextTipsEnabled)
{
GUI.Label(ContextLabelRect(line++), StringUtils.Localize("#LOC_BDArmory_AIWindow_EvasionRCS_Context"), contextLabel);
}
- AI.evasionEngines = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.evasionEngines,
+ if (AI.evasionEngines != (AI.evasionEngines = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.evasionEngines,
StringUtils.Localize("#LOC_BDArmory_AIWindow_EvasionEngines") + " : " + (AI.evasionEngines ? StringUtils.Localize("#LOC_BDArmory_Enabled") : StringUtils.Localize("#LOC_BDArmory_Disabled")),
- AI.evasionEngines ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);
+ AI.evasionEngines ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))
+ AI.UpdateToggle(AI.Fields[nameof(AI.evasionEngines)]);
line += 1.25f;
if (contextTipsEnabled)
{
GUI.Label(ContextLabelRect(line++), StringUtils.Localize("#LOC_BDArmory_AIWindow_EvasionEngines_Context"), contextLabel);
}
- AI.evasionIgnoreMyTargetTargetingMe = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.evasionIgnoreMyTargetTargetingMe, StringUtils.Localize("#LOC_BDArmory_AI_EvasionIgnoreMyTargetTargetingMe"), AI.evasionIgnoreMyTargetTargetingMe ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle);
+ if (AI.evasionIgnoreMyTargetTargetingMe != (AI.evasionIgnoreMyTargetTargetingMe = GUI.Toggle(ToggleButtonRect(line, contentWidth), AI.evasionIgnoreMyTargetTargetingMe, StringUtils.Localize("#LOC_BDArmory_AI_EvasionIgnoreMyTargetTargetingMe"), AI.evasionIgnoreMyTargetTargetingMe ? BDArmorySetup.SelectedButtonStyle : BDArmorySetup.ButtonStyle)))
+ AI.UpdateToggle(AI.Fields[nameof(AI.evasionIgnoreMyTargetTargetingMe)]);
line += 1.25f;
#region Craft Avoidance
diff --git a/BDArmory/UI/BDStagingAreaGauge.cs b/BDArmory/UI/BDStagingAreaGauge.cs
index 6f830b34c..9ed3bd752 100644
--- a/BDArmory/UI/BDStagingAreaGauge.cs
+++ b/BDArmory/UI/BDStagingAreaGauge.cs
@@ -7,7 +7,7 @@
namespace BDArmory.UI
{
- public class BDStagingAreaGauge : PartModule
+ public class BDStagingAreaGauge : BDAPartModule
{
public string AmmoName = "";
diff --git a/BDArmory/Utils/BDAcTools.cs b/BDArmory/Utils/BDAcTools.cs
index f1bf34a0c..715ab72df 100644
--- a/BDArmory/Utils/BDAcTools.cs
+++ b/BDArmory/Utils/BDAcTools.cs
@@ -134,7 +134,7 @@ public static List<string> ParseNames(string names, bool replaceBackslashErrors,
List<string> source = names.Split(';').ToList<string>();
for (int i = source.Count - 1; i >= 0; i--)
{
- if (source[i] == string.Empty)
+ if ((trimWhiteSpace ? source[i].Trim() : source[i]) == string.Empty)
{
source.RemoveAt(i);
}
diff --git a/BDArmory/Utils/GUIUtils.cs b/BDArmory/Utils/GUIUtils.cs
index 532f2c363..1bb40e5cb 100644
--- a/BDArmory/Utils/GUIUtils.cs
+++ b/BDArmory/Utils/GUIUtils.cs
@@ -1,7 +1,7 @@
using System.Runtime.CompilerServices;
using System.Collections.Generic;
-using System.Collections;
using System.Linq;
+using System;
using UnityEngine;
using BDArmory.Control;
@@ -502,6 +502,8 @@ public static bool MouseIsInRect(Rect rect, Vector2 inverseMousePos)
//Thanks FlowerChild
//refreshes part action window
+ // Note: This was just calling "part.PartActionWindow.UpdateWindow()", which is done every frame by KSP anyway, making this redundant.
+ // Also, setting "part.PartActionWindow.displayDirty = true" causes a full rebuild of the PAW, which breaks continuous interaction with sliders, so avoid it unless absolutely necessary.
//public static void RefreshAssociatedWindows(Part part)
//{
//if (part == null || part.PartActionWindow == null) return;
@@ -519,6 +521,7 @@ public static bool MouseIsInRect(Rect rect, Vector2 inverseMousePos)
// window.Dispose();
//}
+ #region PAW
/// <summary>
/// Refresh the UI for the given resource in the PAW.
/// </summary>
@@ -549,30 +552,202 @@ public static void RefreshPAWResource(Part part, PartResource resource, bool all
}
}
+ /// <summary>
+ /// Helper method to avoid having to specify the PartModule type.
+ /// </summary>
+ /// <typeparam name="T">The subclass Type of the PartModule.</typeparam>
+ /// <param name="partModule">The PartModule for the field.</param>
+ /// <param name="field">The field being updated.</param>
+ /// <param name="obj">The old value.</param>
+ public static void UpdateChooseOptionPAW<T>(this T _, BaseField field, object obj = null) where T : PartModule => UpdateChooseOptionPAW<T>(field, obj);
+
/// <summary>
/// Update a UI_ChooseOption PAW slider when the field value is changed.
/// KSP updates most sliders automatically, but not these apparently.
/// </summary>
- /// <param name="field">The field to update. If field is null, then all UI_ChooseOption fields are updated.</param>
- /// <param name="obj">The partmodule object.</param>
- public static void UpdateChooseOptionPAW(BaseField field, PartModule obj)
+ /// <typeparam name="T">The type of PartModule.</typeparam>
+ /// <param name="field">The field to update. If field is null, then all UI_ChooseOption fields are updated if obj is a PartModule.</param>
+ /// <param name="obj">The value of the control.</param>
+ /// <param name="updateSymmetric">Update the symmetric parts too.</param>
+ public static void UpdateChooseOptionPAW<T>(BaseField field, object obj = null, bool updateSymmetric = true) where T : PartModule
{
- if (obj is null) return;
if (field is null)
{
- foreach (var f in obj.Fields)
+ if (obj is not PartModule pm) return;
+ foreach (var f in pm.Fields)
{
if ((HighLogic.LoadedSceneIsFlight ? f.uiControlFlight : f.uiControlEditor) is UI_ChooseOption)
- UpdateChooseOptionPAW(f, obj);
+ UpdateChooseOptionPAW<T>(f, null);
}
return;
}
- UI_ChooseOption uiControl = (HighLogic.LoadedSceneIsFlight ? field.uiControlFlight : field.uiControlEditor) as UI_ChooseOption;
- var pawChooseOption = uiControl.partActionItem as UIPartActionChooseOption;
- if (pawChooseOption is null) return; // Not shown.
- int newIndex = uiControl.options.IndexOf(field.GetValue(obj));
- if (newIndex != -1) pawChooseOption.slider.value = newIndex;
+ if (field.host is not PartModule partModule) return; // Not a field of a PartModule
+ if ((HighLogic.LoadedSceneIsFlight ? field.uiControlFlight : field.uiControlEditor) is not UI_ChooseOption uiControl) return; // Wrong UI_Control type
+ if (uiControl.partActionItem is not UIPartActionChooseOption pawChooseOption) return; // Not shown
+ var value = (string)field.GetValue(partModule);
+ int newIndex = uiControl.options.IndexOf(value);
+ if (newIndex == -1)
+ {
+ Debug.LogWarning($"[BDArmory.GUIUtils]: Invalid value {value} for {field.guiName} ({field.name}) on {partModule.part}");
+ return;
+ }
+
+ // Debug.Log($"DEBUG Updating ChooseOptionPAW of {field.guiName} ({field.name}) on {partModule.part.persistentId} of type {typeof(T).Name} to {value}, index {pawChooseOption.slider.value}→{newIndex}");
+ bool changed = pawChooseOption.slider.value != newIndex;
+ pawChooseOption.slider.value = newIndex; // Set the value even if it hasn't changed to trigger the slider callback.
+
+ // When set externally (e.g., from symmetry or the AI GUI) UI_ChooseOption sets the field value (but not the slider) without triggering onFieldChanged!
+ // Thus we have to invoke it here in order for it to trigger the onFieldChanged handlers.
+ // Invoking it here may lead to an extra loop or two of this function, but shouldn't recurse further unless handlers on symmetric parts are behaving asymmetricallyn.
+ // It shouldn't trigger onFieldChanged more than once per part module.
+ if (changed && !updateSymmetric && uiControl.onFieldChanged != null) uiControl.onFieldChanged.Invoke(field, obj);
+
+ if (updateSymmetric) foreach (Part sym in partModule.part.symmetryCounterparts)
+ {
+ // Debug.Log($"DEBUG Updating symmetric part {sym.persistentId} of {partModule.part.persistentId}");
+ Type fieldHostType = field.host.GetType();
+ foreach (T pm in sym.GetComponents<T>())
+ {
+ if (pm.GetType() != fieldHostType) continue; // Wrong PartModule.
+ List<string> debugString = [];
+ foreach (var f in pm.Fields) debugString.Add(f.name);
+ UpdateChooseOptionPAW<T>(pm.Fields[field.name], obj, false); // We need to use the field on the symmetric PartModule, otherwise the wrong UI_Control is grabbed.
+ break;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Helper method to avoid having to specify the PartModule type.
+ /// </summary>
+ /// <typeparam name="T">The subclass Type of the PartModule.</typeparam>
+ /// <param name="partModule">The PartModule for the field.</param>
+ /// <param name="field">The field being updated.</param>
+ /// <param name="obj">The old value.</param>
+ public static void UpdateToggle<T>(this T _, BaseField field, object obj = null) where T : PartModule => UpdateToggle<T>(field, obj);
+
+ /// <summary>
+ /// Setting a UI_Toggle value externally (e.g., from symmetry or the AI GUI) doesn't trigger the onFieldChanged or onToggle handlers.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="field"></param>
+ /// <param name="partModule"></param>
+ /// <param name="updateSymmetric"></param>
+ public static void UpdateToggle<T>(BaseField field, object obj, bool updateSymmetric = true) where T : PartModule
+ {
+ if (field is null || field.host is not PartModule partModule) return;
+ if ((HighLogic.LoadedSceneIsFlight ? field.uiControlFlight : field.uiControlEditor) is not UI_Toggle uiControl) return;
+ if (uiControl.partActionItem is not UIPartActionToggle pawToggle) return;
+ var value = (bool)field.GetValue(partModule);
+ if (pawToggle.toggle.state != value)
+ {
+ // Debug.Log($"DEBUG Updating Toggle of {field.guiName} ({field.name}) on {partModule.part.persistentId} of type {typeof(T).Name}, {pawToggle.toggle.state}→{value}");
+ pawToggle.toggle.SetState(value);
+ pawToggle.toggle.onToggle.Invoke();
+ if (value) pawToggle.toggle.onToggleOn.Invoke();
+ else pawToggle.toggle.onToggleOff.Invoke();
+ if (!updateSymmetric && uiControl.onFieldChanged != null) uiControl.onFieldChanged.Invoke(field, obj);
+ }
+ if (updateSymmetric) foreach (Part sym in partModule.part.symmetryCounterparts)
+ {
+ Type fieldHostType = field.host.GetType();
+ foreach (T pm in sym.GetComponents<T>())
+ {
+ if (pm.GetType() != fieldHostType) continue;
+ UpdateToggle<T>(pm.Fields[field.name], obj, false);
+ break;
}
+ }
+ }
+
+ /// <summary>
+ /// Add the default symmetry-propagating handler for other UI_ChooseOption fields.
+ ///
+ /// Note: UI_ChooseOption only affects symmetry parts by default in the editor.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="partModule"></param>
+ public static void SetDefaultChooseOptionHandlers<T>(this T partModule) where T : PartModule
+ {
+ foreach (var field in partModule.Fields)
+ {
+ if ((HighLogic.LoadedSceneIsFlight ? field.uiControlFlight : field.uiControlEditor) is not UI_ChooseOption uiControl) continue;
+ // if (uiControl.onFieldChanged == null) Debug.Log($"DEBUG Setting onFieldChanged handler for UI_ChooseOption {field.guiName}");
+ if (uiControl.affectSymCounterparts switch
+ {
+ UI_Scene.All => true,
+ UI_Scene.Editor when HighLogic.LoadedSceneIsEditor => true,
+ UI_Scene.Flight when HighLogic.LoadedSceneIsFlight => true,
+ _ => false
+ })
+ uiControl.onFieldChanged ??= DefaultChooseOptionHandler<T>;
+ }
+ }
+ static void DefaultChooseOptionHandler<T>(BaseField field, object obj) where T : PartModule
+ {
+ if (field is null || obj is null) return;
+ if (field.host is not PartModule pm) return;
+ // Debug.Log($"DEBUG Handling onFieldChanged for {field.guiName} on {field.host} ({pm.part.persistentId}) with obj: {obj}");
+ UpdateChooseOptionPAW<T>(field, obj);
+ if (pm is BDGenericAIBase && BDArmoryAIGUI.Instance != null && BDArmoryAIGUI.Instance.ActiveAI == pm)
+ {
+ BDArmoryAIGUI.Instance.SetChooseOptionSliders();
+ }
+ }
+ /// <summary>
+ /// Helper method to avoid having to specify the PartModule type.
+ /// </summary>
+ /// <typeparam name="T">The subclass Type of the PartModule.</typeparam>
+ /// <param name="partModule">The PartModule for the field.</param>
+ /// <param name="field">The field being updated.</param>
+ /// <param name="obj">The old value.</param>
+ public static void DefaultChooseOptionHandler<T>(this T _, BaseField field, object obj = null) where T : PartModule => DefaultChooseOptionHandler<T>(field, obj);
+
+ /// <summary>
+ /// Set any unhandled UI_Toggle to sync with symmetric PAWs.
+ /// Custom handlers should make sure to end by calling GUIUtils.UpdateToggle(field, obj);
+ ///
+ /// Note: UI_Toggle only affects symmetry parts by default in the editor.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="partModule"></param>
+ public static void SetDefaultToggleHanders<T>(this T partModule) where T : PartModule
+ {
+ foreach (var field in partModule.Fields)
+ {
+ if ((HighLogic.LoadedSceneIsFlight ? field.uiControlFlight : field.uiControlEditor) is not UI_Toggle uiControl) continue;
+ // Debug.Log($"DEBUG Setting onFieldChanged handler for UI_Toggle {field.guiName}");
+ if (uiControl.affectSymCounterparts switch
+ {
+ UI_Scene.All => true,
+ UI_Scene.Editor when HighLogic.LoadedSceneIsEditor => true,
+ UI_Scene.Flight when HighLogic.LoadedSceneIsFlight => true,
+ _ => false
+ })
+ uiControl.onFieldChanged ??= DefaultToggleHandler<T>;
+ }
+ }
+ /// <summary>
+ /// Handle a PartModule toggle being toggled.
+ /// </summary>
+ /// <typeparam name="T">The type of PartModule.</typeparam>
+ /// <param name="field">The field for the toggle.</param>
+ /// <param name="obj">The old value.</param>
+ static void DefaultToggleHandler<T>(BaseField field, object obj) where T : PartModule
+ {
+ if (field.host is not PartModule pm) return;
+ // Debug.Log($"DEBUG Handling onFieldChanged for {field.guiName} on {field.host} ({pm.part.persistentId}) with obj: {obj}");
+ UpdateToggle<T>(field, obj);
+ }
+ /// <summary>
+ /// Helper method to avoid having to specify the PartModule type.
+ /// </summary>
+ /// <typeparam name="T">The subclass Type of the PartModule.</typeparam>
+ /// <param name="partModule">The PartModule for the field.</param>
+ /// <param name="field">The field being updated.</param>
+ /// <param name="obj">The old value.</param>
+ public static void DefaultToggleHandler<T>(this T _, BaseField field, object obj = null) where T : PartModule => DefaultToggleHandler<T>(field, obj);
+ #endregion PAW
/// <summary>
/// Disable zooming with the scroll wheel if the mouse is over a registered GUI window.
diff --git a/BDArmory/WeaponMounts/BDAdjustableRail.cs b/BDArmory/WeaponMounts/BDAdjustableRail.cs
index 7e3c36a00..d9af788ec 100644
--- a/BDArmory/WeaponMounts/BDAdjustableRail.cs
+++ b/BDArmory/WeaponMounts/BDAdjustableRail.cs
@@ -5,7 +5,7 @@
namespace BDArmory.WeaponMounts
{
- public class BDAdjustableRail : PartModule
+ public class BDAdjustableRail : BDAPartModule
{
[KSPField(isPersistant = true)] public float railHeight;
diff --git a/BDArmory/WeaponMounts/BDDeployableRail.cs b/BDArmory/WeaponMounts/BDDeployableRail.cs
index 184a59d72..83fd85798 100644
--- a/BDArmory/WeaponMounts/BDDeployableRail.cs
+++ b/BDArmory/WeaponMounts/BDDeployableRail.cs
@@ -10,7 +10,7 @@
namespace BDArmory.WeaponMounts
{
- public class BDDeployableRail : PartModule
+ public class BDDeployableRail : BDAPartModule
{
[KSPField]
public string deployAnimName = "deployAnim";
diff --git a/BDArmory/WeaponMounts/BDRotaryRail.cs b/BDArmory/WeaponMounts/BDRotaryRail.cs
index 9ab348354..44bc15bd4 100644
--- a/BDArmory/WeaponMounts/BDRotaryRail.cs
+++ b/BDArmory/WeaponMounts/BDRotaryRail.cs
@@ -10,7 +10,7 @@
namespace BDArmory.WeaponMounts
{
- public class BDRotaryRail : PartModule
+ public class BDRotaryRail : BDAPartModule
{
[KSPField] public float maxLength;
diff --git a/BDArmory/WeaponMounts/MissileTurret.cs b/BDArmory/WeaponMounts/MissileTurret.cs
index 0f29d2e9a..d9832ef9d 100644
--- a/BDArmory/WeaponMounts/MissileTurret.cs
+++ b/BDArmory/WeaponMounts/MissileTurret.cs
@@ -14,7 +14,7 @@
namespace BDArmory.WeaponMounts
{
- public class MissileTurret : PartModule
+ public class MissileTurret : BDAPartModule
{
[KSPField] public string finalTransformName;
public Transform finalTransform;
diff --git a/BDArmory/WeaponMounts/ModuleCustomTurret.cs b/BDArmory/WeaponMounts/ModuleCustomTurret.cs
index 0c6b5983f..2ca112825 100644
--- a/BDArmory/WeaponMounts/ModuleCustomTurret.cs
+++ b/BDArmory/WeaponMounts/ModuleCustomTurret.cs
@@ -14,7 +14,7 @@
namespace BDArmory.WeaponMounts
{
- public class ModuleCustomTurret : PartModule
+ public class ModuleCustomTurret : BDAPartModule
{
[KSPField(isPersistant = true, guiActive = false, guiActiveEditor = true, guiName = "#LOC_BDArmory_TurretID"),//Max Pitch
UI_FloatRange(minValue = 0f, maxValue = 20f, stepIncrement = 1f, scene = UI_Scene.All)]
diff --git a/BDArmory/WeaponMounts/ModuleTurret.cs b/BDArmory/WeaponMounts/ModuleTurret.cs
index 54d951894..089a237ba 100644
--- a/BDArmory/WeaponMounts/ModuleTurret.cs
+++ b/BDArmory/WeaponMounts/ModuleTurret.cs
@@ -9,7 +9,7 @@
namespace BDArmory.WeaponMounts
{
- public class ModuleTurret : PartModule
+ public class ModuleTurret : BDAPartModule
{
[KSPField] public int turretID = 0;
@@ -659,7 +659,7 @@ public bool turretEnabled()
return false;
}
}
- public class BDAScaleByDistance : PartModule
+ public class BDAScaleByDistance : BDAPartModule
{
/// <summary>
/// Sibling Module to FXModuleLookAtConstraint, causes indicated mesh object to scale based on distance to target transform
diff --git a/BDArmory/Weapons/BDModuleNuke.cs b/BDArmory/Weapons/BDModuleNuke.cs
index 0610e09d1..a5ca51677 100644
--- a/BDArmory/Weapons/BDModuleNuke.cs
+++ b/BDArmory/Weapons/BDModuleNuke.cs
@@ -16,7 +16,7 @@
namespace BDArmory.Weapons
{
- class BDModuleNuke : PartModule
+ class BDModuleNuke : BDAPartModule
{
//[KSPField(isPersistant = true, guiActive = true, guiName = "WARNING: Reactor Safeties:", guiActiveEditor = false), UI_Label(affectSymCounterparts = UI_Scene.All, scene = UI_Scene.All)]//Weapon Name
//public string status = "OFFLINE";
diff --git a/BDArmory/Weapons/BDWarheadBase.cs b/BDArmory/Weapons/BDWarheadBase.cs
index 1abbc3a33..6947eef0a 100644
--- a/BDArmory/Weapons/BDWarheadBase.cs
+++ b/BDArmory/Weapons/BDWarheadBase.cs
@@ -12,7 +12,7 @@
namespace BDArmory.Weapons
{
- public abstract class BDWarheadBase : PartModule
+ public abstract class BDWarheadBase : BDAPartModule
{
protected float distanceFromStart = 500;
@@ -41,18 +41,23 @@ public Vessel sourcevessel
//PartWindow buttons
[KSPEvent(guiActive = false, guiActiveEditor = false, guiName = "Disarm Warhead")]//Toggle
- public void Toggle()
+ public void ToggleArmed() => ToggleArmed(HighLogic.LoadedSceneIsEditor);
+ public void ToggleArmed(bool updateSymmetric)
{
Armed = !Armed;
if (Armed)
{
guiStatusString = "ARMED";
- Events[nameof(Toggle)].guiName = StringUtils.Localize("Disarm Warhead");//"Enable Engage Options"
+ Events[nameof(ToggleArmed)].guiName = StringUtils.Localize("Disarm Warhead");//"Enable Engage Options"
}
else
{
guiStatusString = "Safe";
- Events[nameof(Toggle)].guiName = StringUtils.Localize("Arm Warhead");//"Disable Engage Options"
+ Events[nameof(ToggleArmed)].guiName = StringUtils.Localize("Arm Warhead");//"Disable Engage Options"
+ }
+ if (updateSymmetric) foreach (Part p in part.symmetryCounterparts)
+ {
+ p.GetComponent<BDWarheadBase>().ToggleArmed(false);
}
}
@@ -61,7 +66,8 @@ public void Toggle()
//PartWindow buttons
[KSPEvent(guiActive = false, guiActiveEditor = false, guiName = "Disable IFF")]//Toggle
- public void ToggleIFF()
+ public void ToggleIFF() => ToggleIFF(true);
+ public void ToggleIFF(bool updateSymmetric)
{
IFF_On = !IFF_On;
if (IFF_On)
@@ -74,12 +80,17 @@ public void ToggleIFF()
guiIFFString = "Indescriminate";
Events[nameof(ToggleIFF)].guiName = StringUtils.Localize("Enable IFF");//"Disable Engage Options"
}
+ if (updateSymmetric) foreach (Part p in part.symmetryCounterparts)
+ {
+ p.GetComponent<BDWarheadBase>().ToggleIFF(false);
+ }
}
public string IFFID = null;
[KSPEvent(guiActive = false, guiActiveEditor = false, guiName = "#LOC_BDArmory_DetonationDistanceOverride")]//Toggle
- public void ToggleProx()
+ public void ToggleProx() => ToggleProx(true);
+ public void ToggleProx(bool updateSymmetric)
{
manualOverride = !manualOverride;
if (manualOverride)
@@ -92,7 +103,10 @@ public void ToggleProx()
Fields[nameof(detonationRange)].guiActiveEditor = false;
Fields[nameof(detonationRange)].guiActive = false;
}
- GUIUtils.RefreshAssociatedWindows(part);
+ if (updateSymmetric) foreach (Part p in part.symmetryCounterparts)
+ {
+ p.GetComponent<BDWarheadBase>().ToggleProx(false);
+ }
}
[KSPAction("Arm")]
@@ -100,7 +114,7 @@ public void ArmAG(KSPActionParam param)
{
Armed = true;
guiStatusString = "ARMED"; // Future me, this needs localization at some point
- Events[nameof(Toggle)].guiName = StringUtils.Localize("Disarm Warhead");//"Enable Engage Options"
+ Events[nameof(ToggleArmed)].guiName = StringUtils.Localize("Disarm Warhead");//"Enable Engage Options"
}
[KSPAction("Detonate")]
@@ -179,8 +193,8 @@ public void GuiSetup()
{
if (!isMissile)
{
- Events[nameof(Toggle)].guiActiveEditor = true;
- Events[nameof(Toggle)].guiActive = true;
+ Events[nameof(ToggleArmed)].guiActiveEditor = true;
+ Events[nameof(ToggleArmed)].guiActive = true;
Events[nameof(ToggleIFF)].guiActiveEditor = true;
Events[nameof(ToggleIFF)].guiActive = true;
Events[nameof(ToggleProx)].guiActiveEditor = true;
@@ -192,12 +206,12 @@ public void GuiSetup()
if (Armed)
{
guiStatusString = "ARMED";
- Events[nameof(Toggle)].guiName = StringUtils.Localize("Disarm Warhead");
+ Events[nameof(ToggleArmed)].guiName = StringUtils.Localize("Disarm Warhead");
}
else
{
guiStatusString = "Safe";
- Events[nameof(Toggle)].guiName = StringUtils.Localize("Arm Warhead");
+ Events[nameof(ToggleArmed)].guiName = StringUtils.Localize("Arm Warhead");
}
if (IFF_On)
{
@@ -223,8 +237,8 @@ public void GuiSetup()
}
else
{
- Events[nameof(Toggle)].guiActiveEditor = false;
- Events[nameof(Toggle)].guiActive = false;
+ Events[nameof(ToggleArmed)].guiActiveEditor = false;
+ Events[nameof(ToggleArmed)].guiActive = false;
Events[nameof(ToggleIFF)].guiActiveEditor = false;
Events[nameof(ToggleIFF)].guiActive = false;
Events[nameof(ToggleProx)].guiActiveEditor = false;
@@ -238,7 +252,6 @@ public void GuiSetup()
Fields[nameof(detonateAtMinimumDistance)].guiActiveEditor = false;
Fields[nameof(detonateAtMinimumDistance)].guiActive = false;
}
- GUIUtils.RefreshAssociatedWindows(part);
}
protected abstract void WarheadSpecificUISetup();
diff --git a/BDArmory/Weapons/ClusterBomb.cs b/BDArmory/Weapons/ClusterBomb.cs
index 474ea88a7..f49ec93a5 100644
--- a/BDArmory/Weapons/ClusterBomb.cs
+++ b/BDArmory/Weapons/ClusterBomb.cs
@@ -10,7 +10,7 @@
namespace BDArmory.Weapons
{
- public class ClusterBomb : PartModule
+ public class ClusterBomb : BDAPartModule
{
public List<GameObject> submunitions;
List<GameObject> fairings;
diff --git a/BDArmory/Weapons/EngageableWeapon.cs b/BDArmory/Weapons/EngageableWeapon.cs
index 9b45c6934..7b191f4ea 100644
--- a/BDArmory/Weapons/EngageableWeapon.cs
+++ b/BDArmory/Weapons/EngageableWeapon.cs
@@ -5,7 +5,7 @@
namespace BDArmory.Weapons
{
- public abstract class EngageableWeapon : PartModule, IEngageService
+ public abstract class EngageableWeapon : BDAPartModule, IEngageService
{
[KSPField(isPersistant = true)]
public bool engageEnabled = true;
@@ -70,7 +70,6 @@ public void ToggleEngageOptionsImpl(bool setEnabled, bool applyToSymmetric = tru
Fields[nameof(engageSLW)].guiActive = engageEnabled;
Fields[nameof(engageSLW)].guiActiveEditor = engageEnabled;
- GUIUtils.RefreshAssociatedWindows(part);
if (applyToSymmetric)
{
foreach (var sympart in part.symmetryCounterparts)
@@ -94,7 +93,6 @@ public void HideEngageOptions()
Fields[nameof(engageSLW)].guiActive = false;
Fields[nameof(engageSLW)].guiActiveEditor = false;
- GUIUtils.RefreshAssociatedWindows(part);
}
public void OnRangeUpdated(BaseField field, object obj)
{
diff --git a/BDArmory/Weapons/Missiles/BDMMLauncher.cs b/BDArmory/Weapons/Missiles/BDMMLauncher.cs
index 50f12842a..5c7123c91 100644
--- a/BDArmory/Weapons/Missiles/BDMMLauncher.cs
+++ b/BDArmory/Weapons/Missiles/BDMMLauncher.cs
@@ -4,7 +4,7 @@
namespace BDArmory.Weapons.Missiles
{
- public class BDMMLauncher : PartModule
+ public class BDMMLauncher : BDAPartModule
{
public override void OnStart(StartState state)
{
diff --git a/BDArmory/Weapons/Missiles/BDModularGuidance.cs b/BDArmory/Weapons/Missiles/BDModularGuidance.cs
index fd48ba0c0..a792d3dc1 100644
--- a/BDArmory/Weapons/Missiles/BDModularGuidance.cs
+++ b/BDArmory/Weapons/Missiles/BDModularGuidance.cs
@@ -360,7 +360,6 @@ private void RefreshGuidanceMode()
Fields[nameof(RollCorrection)].guiActiveEditor = false;
}
- GUIUtils.RefreshAssociatedWindows(part);
}
public override void OnFixedUpdate()
@@ -881,7 +880,6 @@ private void UpdateTargetingMode(TargetingModes newTargetingMode)
TargetingMode = newTargetingMode;
_targetingLabel = newTargetingMode.ToString();
- GUIUtils.RefreshAssociatedWindows(part);
}
void OnEditorPartPlaced(Part p)
@@ -1686,7 +1684,6 @@ public override void FireMissile()
guidanceActive = true;
MissileState = MissileStates.Drop;
- GUIUtils.RefreshAssociatedWindows(part);
HasFired = true;
DetonationDistanceState = DetonationDistanceStates.NotSafe;
diff --git a/BDArmory/Weapons/Missiles/MissileLauncher.cs b/BDArmory/Weapons/Missiles/MissileLauncher.cs
index 6d36dd1e8..443092579 100644
--- a/BDArmory/Weapons/Missiles/MissileLauncher.cs
+++ b/BDArmory/Weapons/Missiles/MissileLauncher.cs
@@ -1394,7 +1394,6 @@ public void SetFields(bool checkBaseConfig = true)
}
ParseAntiRadTargetTypes();
- GUIUtils.RefreshAssociatedWindows(part);
}
/// <summary>
diff --git a/BDArmory/Weapons/Missiles/ModuleMissileMagazine.cs b/BDArmory/Weapons/Missiles/ModuleMissileMagazine.cs
index 200ef22e0..de3a1d3ca 100644
--- a/BDArmory/Weapons/Missiles/ModuleMissileMagazine.cs
+++ b/BDArmory/Weapons/Missiles/ModuleMissileMagazine.cs
@@ -7,7 +7,7 @@
namespace BDArmory.Weapons.Missiles
{
- public class ModuleMissileMagazine : PartModule, IPartMassModifier, IPartCostModifier
+ public class ModuleMissileMagazine : BDAPartModule, IPartMassModifier, IPartCostModifier
{
public float GetModuleMass(float baseMass, ModifierStagingSituation situation) => Mathf.Max(ammoCount, 0) * missileMass;
@@ -99,7 +99,6 @@ public void Start()
ordnance.maxValue = ammoCount;
ammoRemaining = ammoCount;
}
- GUIUtils.RefreshAssociatedWindows(part);
StartCoroutine(DelayedStart());
}
@@ -226,7 +225,6 @@ public void ShipModified(ShipConstruct data)
Fields[nameof(loadedMissileName)].guiActive = true;
Fields[nameof(loadedMissileName)].guiActiveEditor = true;
loadedMissileName = MLConfig.GetShortName();
- GUIUtils.RefreshAssociatedWindows(part);
missileMass = AccountForAmmo ? missile.partInfo.partPrefab.mass : 0;
missileCost = AccountForAmmo ? missile.partInfo.cost : 0;
EditorLogic.DeletePart(missile);
diff --git a/BDArmory/Weapons/Missiles/ModuleMissileRearm.cs b/BDArmory/Weapons/Missiles/ModuleMissileRearm.cs
index 5971fa3f7..a72c51599 100644
--- a/BDArmory/Weapons/Missiles/ModuleMissileRearm.cs
+++ b/BDArmory/Weapons/Missiles/ModuleMissileRearm.cs
@@ -13,7 +13,7 @@
namespace BDArmory.Weapons.Missiles
{
- public class ModuleMissileRearm : PartModule, IPartMassModifier, IPartCostModifier
+ public class ModuleMissileRearm : BDAPartModule, IPartMassModifier, IPartCostModifier
{
public float GetModuleMass(float baseMass, ModifierStagingSituation situation) => Mathf.Max((isMultiLauncher ? (int)railAmmo : (int)railAmmo - 1), 0) * missileMass;
diff --git a/BDArmory/Weapons/Missiles/MultiMissileLauncher.cs b/BDArmory/Weapons/Missiles/MultiMissileLauncher.cs
index ab550d6ef..0ce135c69 100644
--- a/BDArmory/Weapons/Missiles/MultiMissileLauncher.cs
+++ b/BDArmory/Weapons/Missiles/MultiMissileLauncher.cs
@@ -21,7 +21,7 @@ namespace BDArmory.Weapons.Missiles
/// Add-on Module to MissileLauncher to extend Launcher functionality to include cluster missiles and multi-missile pods
/// </summary>
- public class MultiMissileLauncher : PartModule
+ public class MultiMissileLauncher : BDAPartModule
{
public static Dictionary<string, ObjectPool> mslDummyPool = new Dictionary<string, ObjectPool>();
[KSPField(isPersistant = true)]
@@ -313,7 +313,6 @@ IEnumerator DelayedStart()
}
}
- GUIUtils.RefreshAssociatedWindows(part);
}
missileSpawner.UpdateMissileValues();
@@ -527,7 +526,6 @@ public void ShipModified(ShipConstruct data)
Fields[nameof(loadedMissileName)].guiActive = true;
Fields[nameof(loadedMissileName)].guiActiveEditor = true;
loadedMissileName = MLConfig.GetShortName();
- GUIUtils.RefreshAssociatedWindows(part);
if (missileSpawner)
{
missileSpawner.MissileName = subMunitionName;
@@ -550,7 +548,6 @@ public void ShipModified(ShipConstruct data)
mml.PopulateMissileDummies(true);
mml.LoadoutModified = true;
mml.loadedMissileName = MLConfig.GetShortName();
- GUIUtils.RefreshAssociatedWindows(sym.Current);
if (mml.missileSpawner)
{
mml.missileSpawner.MissileName = subMunitionName;
@@ -730,7 +727,6 @@ void UpdateFields(MissileLauncher MLConfig, bool configurableSettings)
missileLauncher.blastRadius = MLConfig.blastRadius;
}
missileLauncher.GetBlastRadius();
- GUIUtils.RefreshAssociatedWindows(missileLauncher.part);
missileLauncher.ParseLiftDragSteerTorque();
missileLauncher.ParseManeuvergLim();
// Because we already set the values from the true base config, we do **not** check the base config in SetFields
diff --git a/BDArmory/Weapons/ModuleAmmoMagazine.cs b/BDArmory/Weapons/ModuleAmmoMagazine.cs
index 2c3795870..622b728a1 100644
--- a/BDArmory/Weapons/ModuleAmmoMagazine.cs
+++ b/BDArmory/Weapons/ModuleAmmoMagazine.cs
@@ -8,7 +8,7 @@
namespace BDArmory.Weapons.Missiles
{
- public class ModuleAmmoMagazine : PartModule, IPartMassModifier//, IPartCostModifier
+ public class ModuleAmmoMagazine : BDAPartModule, IPartMassModifier//, IPartCostModifier
{
public float GetModuleMass(float baseMass, ModifierStagingSituation situation) => binMass;//need to have this scale by some amount
diff --git a/BDArmory/Weapons/ModuleEMP.cs b/BDArmory/Weapons/ModuleEMP.cs
index 1b6d237d6..d3ee9123c 100644
--- a/BDArmory/Weapons/ModuleEMP.cs
+++ b/BDArmory/Weapons/ModuleEMP.cs
@@ -6,7 +6,7 @@
namespace BDArmory.Weapons
{
- public class ModuleEMP : PartModule
+ public class ModuleEMP : BDAPartModule
{
[KSPField(isPersistant = true, guiActive = true, guiActiveEditor = false, guiName = "#LOC_BDArmory_EMPBlastRadius"),//EMP Blast Radius
UI_Label(affectSymCounterparts = UI_Scene.All, controlEnabled = true, scene = UI_Scene.All)]
diff --git a/BDArmory/Weapons/ModuleWeapon.cs b/BDArmory/Weapons/ModuleWeapon.cs
index 575b5c7d6..961d2c76f 100644
--- a/BDArmory/Weapons/ModuleWeapon.cs
+++ b/BDArmory/Weapons/ModuleWeapon.cs
@@ -897,7 +897,18 @@ public void ToggleAmmoConfig()
Fields[nameof(AmmoTypeNum)].guiActiveEditor = true;
useCustomBelt = false;
}
- GUIUtils.RefreshAssociatedWindows(part);
+ foreach (var sym in part.symmetryCounterparts)
+ {
+ if (sym == null) continue;
+ var wep = sym.GetComponent<ModuleWeapon>();
+ wep.advancedAmmoOption = advancedAmmoOption;
+ wep.Events[nameof(ToggleAmmoConfig)].guiName = Events[nameof(ToggleAmmoConfig)].guiName;
+ wep.Events[nameof(ConfigAmmo)].guiActive = Events[nameof(ConfigAmmo)].guiActive;
+ wep.Events[nameof(ConfigAmmo)].guiActiveEditor = Events[nameof(ConfigAmmo)].guiActiveEditor;
+ wep.Fields[nameof(AmmoTypeNum)].guiActive = Fields[nameof(AmmoTypeNum)].guiActive;
+ wep.Fields[nameof(AmmoTypeNum)].guiActiveEditor = Fields[nameof(AmmoTypeNum)].guiActiveEditor;
+ wep.useCustomBelt = useCustomBelt;
+ }
}
[KSPField(advancedTweakable = true, isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "#LOC_BDArmory_useBelt")]//Using Custom Loadout
public bool useCustomBelt = false;
@@ -1039,7 +1050,6 @@ public void setAimOverride()
{
weapon.Current.useThisWeaponForAim = false;
weapon.Current.Events[nameof(setAimOverride)].guiName = StringUtils.Localize("#LOC_BDArmory_AimOverrideFalse");//"Aim With This Weapon"
- GUIUtils.RefreshAssociatedWindows(weapon.Current.part);
}
}
}
@@ -1853,7 +1863,7 @@ public void Start()
}*/
if (eWeaponType != WeaponTypes.Laser)
{
- SetupAmmo(null, null);
+ SetupAmmo(null, null, false);
if (eWeaponType == WeaponTypes.Rocket)
{
@@ -2038,45 +2048,42 @@ public void PAWRefresh()
Events[nameof(setAimOverride)].guiName = StringUtils.Localize("#LOC_BDArmory_AimOverrideTrue");//"Revert Aim Override"
else
Events[nameof(setAimOverride)].guiName = StringUtils.Localize("#LOC_BDArmory_AimOverrideFalse");//"Aim With This Weapon"
-
- GUIUtils.RefreshAssociatedWindows(part);
}
[KSPEvent(advancedTweakable = true, guiActive = true, guiActiveEditor = true, guiName = "#LOC_BDArmory_FireAngleOverride_Enable", active = true)]//Disable fire angle override
public void ToggleOverrideAngle()
{
FireAngleOverride = !FireAngleOverride;
- if (!FireAngleOverride)
- {
- Events[nameof(ToggleOverrideAngle)].guiName = StringUtils.Localize("#LOC_BDArmory_FireAngleOverride_Enable");// Enable Firing Angle Override
- }
- else
- {
- Events[nameof(ToggleOverrideAngle)].guiName = StringUtils.Localize("#LOC_BDArmory_FireAngleOverride_Disable");// Disable Firing Angle Override
- }
-
+ Events[nameof(ToggleOverrideAngle)].guiName = StringUtils.Localize(FireAngleOverride ? "#LOC_BDArmory_FireAngleOverride_Disable" : "#LOC_BDArmory_FireAngleOverride_Enable");// Enable/Disable Firing Angle Override
Fields[nameof(FiringTolerance)].guiActive = FireAngleOverride;
Fields[nameof(FiringTolerance)].guiActiveEditor = FireAngleOverride;
+ foreach (var sym in part.symmetryCounterparts)
+ {
+ if (sym == null) continue;
+ var wep = sym.GetComponent<ModuleWeapon>();
+ wep.FireAngleOverride = FireAngleOverride;
+ wep.Events[nameof(ToggleOverrideAngle)].guiName = StringUtils.Localize(FireAngleOverride ? "#LOC_BDArmory_BurstLengthOverride_Disable" : "#LOC_BDArmory_BurstLengthOverride_Enable");
+ wep.Fields[nameof(FiringTolerance)].guiActive = FireAngleOverride;
+ wep.Fields[nameof(FiringTolerance)].guiActiveEditor = FireAngleOverride;
+ }
- GUIUtils.RefreshAssociatedWindows(part);
}
[KSPEvent(advancedTweakable = true, guiActive = true, guiActiveEditor = true, guiName = "#LOC_BDArmory_BurstLengthOverride_Enable", active = true)]//Burst length override
public void ToggleBurstLengthOverride()
{
BurstOverride = !BurstOverride;
- if (!BurstOverride)
- {
- Events[nameof(ToggleBurstLengthOverride)].guiName = StringUtils.Localize("#LOC_BDArmory_BurstLengthOverride_Enable");// Enable Firing Angle Override
- }
- else
- {
- Events[nameof(ToggleBurstLengthOverride)].guiName = StringUtils.Localize("#LOC_BDArmory_BurstLengthOverride_Disable");// Disable Firing Angle Override
- }
-
+ Events[nameof(ToggleBurstLengthOverride)].guiName = StringUtils.Localize(BurstOverride ? "#LOC_BDArmory_BurstLengthOverride_Disable" : "#LOC_BDArmory_BurstLengthOverride_Enable");// Enable Firing Angle Override
Fields[nameof(fireBurstLength)].guiActive = BurstOverride;
Fields[nameof(fireBurstLength)].guiActiveEditor = BurstOverride;
-
- GUIUtils.RefreshAssociatedWindows(part);
+ foreach (var sym in part.symmetryCounterparts)
+ {
+ if (sym == null) continue;
+ var wep = sym.GetComponent<ModuleWeapon>();
+ wep.BurstOverride = BurstOverride;
+ wep.Events[nameof(ToggleBurstLengthOverride)].guiName = StringUtils.Localize(BurstOverride ? "#LOC_BDArmory_BurstLengthOverride_Disable" : "#LOC_BDArmory_BurstLengthOverride_Enable");
+ wep.Fields[nameof(fireBurstLength)].guiActive = BurstOverride;
+ wep.Fields[nameof(fireBurstLength)].guiActiveEditor = BurstOverride;
+ }
}
public bool toggleDeployState = true;
@@ -2084,29 +2091,15 @@ public void ToggleBurstLengthOverride()
public void ToggleDeploy()
{
toggleDeployState = !toggleDeployState;
-
- if (toggleDeployState == false)
+ Events[nameof(ToggleDeploy)].guiName = StringUtils.Localize(toggleDeployState ? "#autoLOC_6001339" : "#autoLOC_6001080");//"Retract" : "Extended"
+ if (deployState != null) deployState.normalizedTime = HighLogic.LoadedSceneIsFlight ? 0 : toggleDeployState ? 1 : 0;
+ foreach (var sym in part.symmetryCounterparts)
{
- Events[nameof(ToggleDeploy)].guiName = StringUtils.Localize("#autoLOC_6001080");//"Deploy"
- }
- else
- {
- Events[nameof(ToggleDeploy)].guiName = StringUtils.Localize("#autoLOC_6001339");//""Retract"
- }
- if (deployState != null)
- {
- deployState.normalizedTime = HighLogic.LoadedSceneIsFlight ? 0 : toggleDeployState ? 1 : 0;
- using (List<Part>.Enumerator pSym = part.symmetryCounterparts.GetEnumerator())
- while (pSym.MoveNext())
- {
- if (pSym.Current == null) continue;
- if (pSym.Current != part && pSym.Current.vessel == vessel)
- {
- var wep = pSym.Current.FindModuleImplementing<ModuleWeapon>();
- if (wep == null) continue;
- wep.deployState.normalizedTime = toggleDeployState ? 1 : 0;
- }
- }
+ if (sym == null) continue;
+ var wep = sym.FindModuleImplementing<ModuleWeapon>();
+ wep.toggleDeployState = toggleDeployState;
+ wep.Events[nameof(ToggleDeploy)].guiName = StringUtils.Localize(toggleDeployState ? "#autoLOC_6001339" : "#autoLOC_6001080");//"Retract" : "Extended"
+ if (wep.deployState != null) wep.deployState.normalizedTime = toggleDeployState ? 1 : 0;
}
}
@@ -3975,7 +3968,7 @@ private void CheckLoadedAmmo()
if (customAmmoBelt.Count < 1) return;
if (AmmoIntervalCounter == 0 || (AmmoIntervalCounter > 0 && customAmmoBeltIndexes[AmmoIntervalCounter] != customAmmoBeltIndexes[AmmoIntervalCounter - 1]))
{
- SetupAmmo(null, null);
+ SetupAmmo(null, null, false);
}
AmmoIntervalCounter++;
if (AmmoIntervalCounter == customAmmoBelt.Count)
@@ -6738,7 +6731,8 @@ public void SetupRocketPool(string name, string modelpath)
}
}
- public void SetupAmmo(BaseField field, object obj)
+ public void SetupAmmo(BaseField field, object obj) => SetupAmmo(field, obj, true);
+ public void SetupAmmo(BaseField field, object obj, bool updateSymmetric)
{
if (useCustomBelt && customAmmoBelt.Count > 0)
{
@@ -6758,6 +6752,13 @@ public void SetupAmmo(BaseField field, object obj)
currentTypeIndex = ammoTypeIndex;
}
ParseAmmoStats();
+
+ if (updateSymmetric) foreach (var sym in part.symmetryCounterparts)
+ {
+ if (sym is null) continue;
+ var wep = sym.GetComponent<ModuleWeapon>();
+ wep.SetupAmmo(field != null ? wep.Fields[field.name] : null, obj, false);
+ }
}
public void ParseAmmoStats()
{
-new modular ammo bin support
-Hitpointtracker HP and hull material mass fixes
-customTurret aim assist
-rework staleTarget tracking