-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathExampleAirlock.txt
2199 lines (1871 loc) · 76.2 KB
/
ExampleAirlock.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* v:0.92 (1.091 compatible)
In-Game script by MMaster & Morphologis
Last update: Airlocks can be controlled by using Programmable Block argument
* Automatically figure out when doors are fully closed
* Improve detection of depressurize/pressurize of airvent
Previous update: Make colors configurable in script config & made it smarter when pressure changes
* Closing time per door & Airvents in inner and outer groups
* (look at extra features section below)
Intelligent airlock system. Automatically controls any number of airlocks on ships and stations.
Any number of airlocks using single programmable block & timer
Any number of doors per airlock (can be used with Hangar Doors)
Any number of airvents per airlock (so you can use it for large airlocks)
Automatic pressurization / depressurization
Doors automatically closed & locked / unlocked & opened
Lights changing colors based on state of airlock
Play sound blocks when airlock is pressurized, depressurized or in both cases
LCD display support to display state of any number of airlocks on any LCD
Unlocks doors without opening when airlock can't be depressurized / pressurized
3 button actions support: transfer to inner doors, outer doors or switch between them
Airlock can be also controlled by switching 'Depressurize' on airvents
NO PROGRAMMING NEEDED.
VIDEO GUIDE BY MORPHOLOGIS:
* https://www.youtube.com/watch?v=viWsqLvqkAM
QUICK GUIDE:
* Load script to programmable block
* Setup timer actions: 1. run programmable block, 2. start timer
* Set timer delay to 1 second
* Start timer
Setup 3 groups per airlock like this:
Group named "Airlock Control: Airlock name" should contain:
- airvents inside airlock
- lcds that should show this airlock state [optional]
- [optional] one hidden interior light (can be turned off) (used to control airlock with buttons)
Group named "Airlock Inner: Airlock name" should contain:
- inner doors (opened when airlock is pressurized)
- lights for showing inner door status [optional]
- sound block played when airlock is being pressurized [optional]
Group named "Airlock Outer: Airlock name" should contain:
- outer doors (opened when airlock is depressurized)
- lights for showing outer door status [optional]
- sound block played when airlock is being depressurized [optional]
HINT:
You can build single sound block and add it to both Inner and Outer group
to play sound each time airlock changes state (e.g. hissing sound).
Setup buttons to switch Depressurize on airvents you added to Control group.
NOTE: this is much less effective than using the control light, but it works
OR
Setup buttons to Run Programmable block with argument (without quotes!):
"Airlock name in" - transfer to inner doors (pressurize)
"Airlock name out" - transfer to outer doors (depressurize)
"Airlock name toggle" - switch between inner doors / outer doors
OR
Setup buttons to control the hidden interior light which you added to Control group:
"Increase Blink Length" - transfer to inner doors (pressurize)
"Decrease Blink Length" - transfer to outer doors (depressurize)
"Increase Blink Offset" - switch between inner doors / outer doors
* Done.
EXTRA FEATURES
Change color of lights in script LIGHT COLOR SETTINGS right below this description.
Place airvent behind inner doors to Airlock Inner group and/or airvent outside of outer doors to Airlock Outer group
to let airlock automatically figure out what should be the pressure when opening inner and/or outer doors.
Add closing time to doors name to make sure doors are closed before locking them by adding "CT:seconds":
* if your doors are named "Hangar Door 3" rename them to "Hangar Door 3 CT:10" to set closing time to 10 seconds
* if your doors are named "Door 3" rename them to "Door 3 CT:5" to set closing time to 5 seconds
RECOMMENDED sound pack made by Tartaross
Tartaross Inc. A.I. Soundpack #2: Community Wishlist
http://steamcommunity.com/sharedfiles/filedetails/?id=431231192
VERY SPECIAL THANKS
Morphologis for this idea, his help with debugging this script and for his support of community & awesome videos!
Make sure to check out his YouTube channel:
https://www.youtube.com/user/Morphologis
Also look at Deep Space Nation reddit page:
https://www.reddit.com/r/DeepSpaceNation
Watch MMaster's Steam group: http://steamcommunity.com/groups/mmnews
Youtube Channel: https://www.youtube.com/user/MattsPlayCorner1080p
Twitter: https://twitter.com/MattsPlayCorner
and Facebook: https://www.facebook.com/MattsPlayCorner1080p
for more crazy stuff in the future :)
*/
void Configuration()
{
/* LIGHT COLOR SETTINGS
*
* 1. number is red color from 0.0 (black) to 1.0 (red)
* 2. number is green color from 0.0 (black) to 1.0 (green)
* 3. number is blue color from 0.0 (black) to 1.0 (blue)
*
* Examples:
* Color(0.5f, 0.0f, 0.0f) is dark red
* Color(0.0f, 0.5f, 0.0f) is dark green
* Color(1.0f, 1.0f, 1.0f) is white color
* Color(1.0f, 1.0f, 0.0f) is yellow
* Color(1.0f, 0.5f, 0.0f) is orange
* Color(0.0f, 1.0f, 1.0f) is cyan
*
* change only the numbers (leave f at the end of each number) */
// color when doors are locked
MMConfig.LOCK_COLOR = new Color(1.0f, 0.0f, 0.0f);
// color when pressure is wrong but doors are unlocked
MMConfig.WARN_COLOR = new Color(1.0f, 0.5f, 0.0f);
// color when doors are open
MMConfig.OPEN_COLOR = new Color(0.0f, 1.0f, 0.0f);
// Group name must start with this to be considered by this script
MMConfig.GROUP_TAG = "airlock";
// Colon needs to stay at the end
MMConfig.INNER_TAG = "inner:";
MMConfig.OUTER_TAG = "outer:";
MMConfig.CONTROL_TAG = "control:";
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// DO NOT MODIFY ANYTHING BELOW THIS
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// (for developer) Enable debug to antenna or LCD marked with [DEBUG]
public static bool EnableDebug = false;
void Main(string argument)
{
Configuration();
// Init MMAPI and debug panels marked with [DEBUG]
MM.Init(GridTerminalSystem, EnableDebug);
AirlockControlProgram prog = new AirlockControlProgram();
prog.Run(argument);
}
}
public static class MMConfig
{
public static string GROUP_TAG = "airlock";
public static string INNER_TAG = "inner:";
public static string OUTER_TAG = "outer:";
public static string CONTROL_TAG = "control:";
public static Color LOCK_COLOR;
public static Color WARN_COLOR;
public static Color OPEN_COLOR;
}
public class MMAirlock
{
public List<IMyAirVent> airVents = new List<IMyAirVent>();
public List<IMyDoor> innerDoors = new List<IMyDoor>();
public List<IMySoundBlock> innerSound = new List<IMySoundBlock>();
public List<IMyLightingBlock> innerLights = new List<IMyLightingBlock>();
public List<IMyDoor> outerDoors = new List<IMyDoor>();
public List<IMySoundBlock> outerSound = new List<IMySoundBlock>();
public List<IMyLightingBlock> outerLights = new List<IMyLightingBlock>();
public MMList<MMPanel> lcds = new MMList<MMPanel>();
public IMyLightingBlock control = null;
public string command = "";
public const int ClosingTimeDefault = 3;
public const int FullTimeThreshold = 3;
public const int EmptyTimeThreshold = 3;
public const int DepressurizeMaxTime = 20;
public const int PressurizeMaxTime = 20;
public float OuterPressure = 0f;
public float InnerPressure = 0.99f;
public int WantedState = 0;
public int CurrentState = 0;
public bool WasDepressurizing = false;
public int ClosingTimer = -1;
public int FullTime = 0;
public int EmptyTime = 0;
public int ChangingTime = 0;
public int TimeSinceChange = 0;
public bool OuterOpen = false;
public bool InnerOpen = false;
public double lowestPressure = 100.0f;
public string name = "Airlock";
public void Reset()
{
airVents.Clear();
innerDoors.Clear();
innerLights.Clear();
outerDoors.Clear();
outerLights.Clear();
lcds.ClearItems();
control = null;
InnerOpen = false;
OuterOpen = false;
lowestPressure = 100.0f;
OuterPressure = 0f;
InnerPressure = 0.99f;
command = "";
}
private void SetLight(List<IMyLightingBlock> lights, Color c, float BlinkInt = 0f, float BlinkLen = 100f, float BlinkOff = 0f)
{
for (int i = 0; i < lights.Count; i++)
{
if (lights[i].GetProperty("Color").AsColor().GetValue(lights[i]) != c
|| BlinkInt != lights[i].BlinkIntervalSeconds
|| !lights[i].IsWorking)
{
if (!lights[i].IsWorking)
{
lights[i].SetValue("Blink Interval", BlinkInt);
lights[i].SetValue("Blink Lenght", BlinkLen);
lights[i].SetValue("Blink Offset", BlinkOff);
lights[i].SetValue("Color", c);
lights[i].ApplyAction("OnOff_On");
} else
lights[i].ApplyAction("OnOff_Off");
}
}
}
private void SetClose(List<IMyDoor> doors, bool closed)
{
for (int i = 0; i < doors.Count; i++)
{
if (closed == !doors[i].Open && closed == !doors[i].IsWorking)
continue;
if (!doors[i].IsWorking)
{
doors[i].ApplyAction("OnOff_On");
continue;
}
if (closed && doors[i].Open)
{
SetupClosingTimer(doors[i]);
doors[i].ApplyAction("Open_Off");
continue;
}
if (!closed && !doors[i].Open)
{
SetupClosingTimer(doors[i]);
doors[i].ApplyAction("Open_On");
continue;
}
if (closed)
{
if (doors[i].OpenRatio <= 0)
{
doors[i].ApplyAction("OnOff_Off");
}
else
{
if (!doors[i].CustomName.Contains(" CT:"))
ClosingTimer = (int)Math.Ceiling(ClosingTimeDefault*doors[i].OpenRatio) + 1;
}
}
}
}
private void SetupClosingTimer(IMyTerminalBlock doors)
{
int default_time = (int)Math.Ceiling(ClosingTimeDefault * (doors as IMyDoor).OpenRatio) + 1;
string ct = doors.CustomName;
int idx = ct.IndexOf(" CT:");
if (idx >= 0)
{
int val = -1;
ct = ct.Substring(idx + 4).TrimStart(' ');
idx = ct.IndexOf(' ');
if (idx >= 0)
ct = ct.Substring(0, idx);
if (int.TryParse(ct, out val))
{
if (val > ClosingTimer)
ClosingTimer = val;
}
else
if (default_time > ClosingTimer)
ClosingTimer = default_time;
}
else
if (default_time > ClosingTimer)
ClosingTimer = default_time;
}
private void PlaySound(List<IMySoundBlock> sounds)
{
for (int i = 0; i < sounds.Count; i++)
{
sounds[i].ApplyAction("PlaySound");
}
}
private void SetLock(List<IMyDoor> doors, bool locked)
{
string action = (locked ? "OnOff_Off" : "OnOff_On");
for (int i = 0; i < doors.Count; i++)
doors[i].ApplyAction(action);
}
private bool IsPressureOk(float wantedPressure)
{
if (wantedPressure <= 0.01f)
return (EmptyTime >= EmptyTimeThreshold);
else
return (FullTime >= FullTimeThreshold);
}
private void SetLights(int state)
{
if ((Opening && !Stuck) || state == 0)
{
if (WantedState == 1)
SetLight(innerLights, MMConfig.LOCK_COLOR, 2f, 50f);
else
SetLight(innerLights, MMConfig.LOCK_COLOR);
if (WantedState == 2)
SetLight(outerLights, MMConfig.LOCK_COLOR, 2f, 50f);
else
SetLight(outerLights, MMConfig.LOCK_COLOR);
return;
}
switch (state)
{
case 1:
if (!IsPressureOk(InnerPressure) && !InnerOpen)
SetLight(innerLights, MMConfig.WARN_COLOR);
else
SetLight(innerLights, MMConfig.OPEN_COLOR);
SetLight(outerLights, MMConfig.LOCK_COLOR);
break;
case 2:
SetLight(innerLights, MMConfig.LOCK_COLOR);
if (!IsPressureOk(OuterPressure) && !OuterOpen)
SetLight(outerLights, MMConfig.WARN_COLOR);
else
SetLight(outerLights, MMConfig.OPEN_COLOR);
break;
}
}
private bool IsAVDepressurizing(IMyAirVent airvent)
{
return airvent.IsDepressurizing;
}
private bool IsDepressurizing()
{
for (int i = 0; i < airVents.Count; i++)
if (IsAVDepressurizing(airVents[i]))
return true;
return false;
}
private void Depressurize(bool on)
{
for (int i = 0; i < airVents.Count; i++)
{
if (on)
airVents[i].ApplyAction("Depressurize_On");
else
airVents[i].ApplyAction("Depressurize_Off");
}
}
private bool Opening = false;
private bool Stuck = false;
public void Process()
{
MM.Debug("Executing " + name);
bool IsDep = IsDepressurizing();
MM.Debug("Airlock: " + name + " IsDep: " + IsDep.ToString() + " WasDep: " + WasDepressurizing.ToString());
MM.Debug("InnerOpen: " + InnerOpen.ToString() + " OuterOpen: " + OuterOpen.ToString());
if (IsDep != WasDepressurizing
|| (TimeSinceChange > 40 && !Stuck &&
((InnerOpen && !IsPressureOk(InnerPressure)) ||
(OuterOpen && !IsPressureOk(OuterPressure))) ))
{
if (!IsDep)
{
if (InnerPressure > 0.01f)
WantedState = 1;
else
WantedState = 2;
}
else
{
if (OuterPressure <= 0.01f)
WantedState = 2;
else
WantedState = 1;
}
if (CurrentState == WantedState && IsDep != WasDepressurizing)
WantedState = (CurrentState == 1 ? 2 : 1);
CurrentState = 0;
}
if (control != null)
{
// buttons
if (control.BlinkLenght > 50f)
WantedState = 1;
else
if (control.BlinkLenght < 50f)
WantedState = 2;
control.SetValueFloat("Blink Lenght", 50f);
// switch
if (control.BlinkOffset > 50f)
WantedState = (WantedState == 2 ? 1 : 2);
control.SetValueFloat("Blink Offset", 50f);
}
if (command != "")
{
switch (command)
{
case "in":
WantedState = 1;
break;
case "out":
WantedState = 2;
break;
case "toggle":
WantedState = (WantedState == 2 ? 1 : 2);
break;
}
}
if (WantedState == 0)
WantedState = (IsDep ? 2 : 1);
if (WantedState != CurrentState)
{
CurrentState = 0;
TimeSinceChange = 0;
}
if (ClosingTimer >= 0)
ClosingTimer--;
MM.Debug("WantSt: " + WantedState.ToString() + " CurSt: " + CurrentState.ToString());
MM.Debug("Closing Timer: " + ClosingTimer.ToString());
MM.Debug("FullTime: " + FullTime + " EmptyTime: " + EmptyTime);
MM.Debug("ChangingTime: " + ChangingTime);
MM.Debug("Inner: " + InnerPressure.ToString("F2") + " Outer: " + OuterPressure.ToString("F2"));
MM.Debug("Opening: " + Opening.ToString() + " Stuck: " + Stuck.ToString());
MM.Debug("LastChange: " + TimeSinceChange.ToString());
if (CurrentState == 0 && ChangingTime > 0)
{
if (WantedState == 1 && IsPressureOk(InnerPressure))
{
CurrentState = 1;
Opening = true;
Stuck = false;
}
else
if (WantedState == 2 && IsPressureOk(OuterPressure))
{
CurrentState = 2;
Opening = true;
Stuck = false;
}
else
if (WantedState == 2 && ChangingTime >= DepressurizeMaxTime)
{
CurrentState = 2;
Opening = true;
Stuck = true;
}
else
if (WantedState == 1 && ChangingTime >= PressurizeMaxTime)
{
CurrentState = 1;
Opening = true;
Stuck = true;
}
}
switch (CurrentState)
{
case 0:
ChangingTime++;
TimeSinceChange = 0;
SetClose(innerDoors, true);
SetClose(outerDoors, true);
SetLights(0);
break;
case 1:
ChangingTime = 0;
SetClose(outerDoors, true);
if (!InnerOpen && Opening)
{
if (IsPressureOk(InnerPressure))
SetClose(innerDoors, false);
else
SetLock(innerDoors, false);
}
else
{
SetLock(innerDoors, false);
if (Stuck && IsPressureOk(InnerPressure))
Stuck = false;
Opening = false;
}
SetLights(1);
break;
case 2:
ChangingTime = 0;
SetClose(innerDoors, true);
if (!OuterOpen && Opening)
{
if (IsPressureOk(OuterPressure))
SetClose(outerDoors, false);
else
SetLock(outerDoors, false);
}
else
{
SetLock(outerDoors, false);
if (Stuck && IsPressureOk(OuterPressure))
Stuck = false;
Opening = false;
}
SetLights(2);
break;
}
for (int lid = 0; lid < lcds.Count; lid++)
MMLCDTextManager.Add(lcds[lid], name);
if (lowestPressure >= 100f)
lowestPressure = -1f;
string pressure = (lowestPressure < 0 ? "[N/A]" : "[" + (lowestPressure * 100f).ToString("F0") + "%]");
switch (WantedState)
{
case 0: // no change
for (int lid = 0; lid < lcds.Count; lid++)
MMLCDTextManager.AddRightAlign(lcds[lid], "!! " + pressure, MMPanel.LCD_LINE_WIDTH);
break;
case 1: // in (pressurize)
if (ClosingTimer <= 0)
{
if (InnerPressure > 0.01f)
{
MM.Debug("Pressurize");
Depressurize(false);
IsDep = false;
}
else
{
MM.Debug("Depressurize");
Depressurize(true);
IsDep = true;
}
}
if (ClosingTimer > 0 || CurrentState == 0 || Opening)
if (Stuck)
for (int lid = 0; lid < lcds.Count; lid++)
MMLCDTextManager.AddRightAlign(lcds[lid], "!! IN " + pressure, MMPanel.LCD_LINE_WIDTH);
else
for (int lid = 0; lid < lcds.Count; lid++)
MMLCDTextManager.AddRightAlign(lcds[lid], ">> IN " + pressure, MMPanel.LCD_LINE_WIDTH);
else
for (int lid = 0; lid < lcds.Count; lid++)
MMLCDTextManager.AddRightAlign(lcds[lid], "IN " + pressure, MMPanel.LCD_LINE_WIDTH);
break;
case 2: // out (decompress)
if (ClosingTimer <= 0)
{
if (OuterPressure > 0.01f)
{
Depressurize(false);
MM.Debug("Pressurize");
IsDep = false;
}
else
{
Depressurize(true);
MM.Debug("Depressurize");
IsDep = true;
}
}
if (ClosingTimer > 0 || CurrentState == 0 || Opening)
if (Stuck)
for (int lid = 0; lid < lcds.Count; lid++)
MMLCDTextManager.AddRightAlign(lcds[lid], "!! OUT " + pressure, MMPanel.LCD_LINE_WIDTH);
else
for (int lid = 0; lid < lcds.Count; lid++)
MMLCDTextManager.AddRightAlign(lcds[lid], ">> OUT " + pressure, MMPanel.LCD_LINE_WIDTH);
else
for (int lid = 0; lid < lcds.Count; lid++)
MMLCDTextManager.AddRightAlign(lcds[lid], "OUT " + pressure, MMPanel.LCD_LINE_WIDTH);
break;
}
for (int lid = 0; lid < lcds.Count; lid++)
{
MMLCDTextManager.AddLine(lcds[lid], "");
MMLCDTextManager.AddProgressBar(lcds[lid], Math.Max(0f, lowestPressure * 100f), lcds[lid].FULL_PROGRESS_CHARS);
MMLCDTextManager.AddLine(lcds[lid], "");
}
if (ClosingTimer == 0)
{
ChangingTime = 0;
if (CurrentState == 0)
switch (WantedState)
{
case 1:
PlaySound(innerSound);
break;
case 2:
PlaySound(outerSound);
break;
}
}
if (!Stuck)
TimeSinceChange++;
WasDepressurizing = IsDep;
}
}
public class AirlockControlProgram
{
public static MMDict<string, MMAirlock> airlocks = new MMDict<string, MMAirlock>();
public static Dictionary<string, MMPanel> panels = new Dictionary<string, MMPanel>();
public MMList<MMPanel> panelList = new MMList<MMPanel>();
public MMAirlock GetAirlock(string name)
{
MMAirlock airlock = null;
if (airlocks.ContainsKey(name))
airlock = airlocks.GetItem(name);
else
{
airlock = new MMAirlock();
airlock.name = name;
airlocks.AddItem(name, airlock);
}
return airlock;
}
public MMPanel GetPanel(IMyTextPanel lcd)
{
MMPanel panel = null;
string key = lcd.CustomName + lcd.GetPosition().ToString("F0") + lcd.NumberInGrid.ToString();
if (panels.ContainsKey(key))
panel = panels[key];
else
{
panel = new MMPanel();
panels.Add(key, panel);
}
if (!panel.panels.ContainsKey(key))
panel.panels.AddItem(key, lcd);
if (!panelList.ContainsItem(panel))
panelList.Add(panel);
return panel;
}
public void AddGroup(IMyBlockGroup group)
{
MM.Debug("Group: '" + group.Name + "'");
int seppos = group.Name.IndexOf(':');
if (seppos < 0)
return;
string tag = group.Name.Substring(0, seppos + 1).ToLower();
string name = (group.Name.Length > seppos + 1 ? group.Name.Substring(seppos + 1).Trim() : "");
if (tag == MMConfig.GROUP_TAG + ' ' + MMConfig.CONTROL_TAG)
{
MMAirlock airlock = GetAirlock(name);
for (int i = 0; i < group.Blocks.Count; i++)
{
IMyTerminalBlock block = group.Blocks[i];
IMyAirVent airvent = block as IMyAirVent;
if (airvent != null)
{
airlock.airVents.Add(airvent);
if (airvent.CanPressurize)
{
double oxyLevel = airvent.GetOxygenLevel();
if (oxyLevel < airlock.lowestPressure)
airlock.lowestPressure = oxyLevel;
}
else
airlock.lowestPressure = -1f;
continue;
}
IMyLightingBlock light = block as IMyLightingBlock;
if (light != null)
airlock.control = light;
IMyTextPanel lcd = block as IMyTextPanel;
if (lcd != null)
{
MMPanel panel = GetPanel(lcd);
airlock.lcds.Add(panel);
}
}
MM.Debug("LowestPressure: " + airlock.lowestPressure.ToString("F0"));
if (airlock.lowestPressure > 0.01f && airlock.lowestPressure >= Math.Max(airlock.InnerPressure, airlock.OuterPressure))
{
if (airlock.FullTime < MMAirlock.FullTimeThreshold)
airlock.FullTime++;
airlock.EmptyTime = 0;
}
else
{
airlock.FullTime = 0;
if (airlock.lowestPressure <= 0.01f)
{
if (airlock.EmptyTime < MMAirlock.EmptyTimeThreshold)
airlock.EmptyTime++;
}
else
airlock.EmptyTime = 0;
}
return;
}
if (tag == MMConfig.GROUP_TAG + ' ' + MMConfig.INNER_TAG)
{
MMAirlock airlock = GetAirlock(name);
for (int i = 0; i < group.Blocks.Count; i++)
{
IMyDoor door = group.Blocks[i] as IMyDoor;
if (door != null)
{
if (door.Open)
airlock.InnerOpen = true;
airlock.innerDoors.Add(door);
continue;
}
IMyLightingBlock light = group.Blocks[i] as IMyLightingBlock;
if (light != null)
{
airlock.innerLights.Add(light);
continue;
}
IMySoundBlock sound = group.Blocks[i] as IMySoundBlock;
if (sound != null)
{
airlock.innerSound.Add(sound);
continue;
}
IMyAirVent airvent = group.Blocks[i] as IMyAirVent;
if (airvent != null)
{
float pres = (airvent.IsPressurized() ? airvent.GetOxygenLevel() : -1f);
if (pres < airlock.InnerPressure)
airlock.InnerPressure = pres;
continue;
}
}
return;
}
if (tag == MMConfig.GROUP_TAG + ' ' + MMConfig.OUTER_TAG)
{
MMAirlock airlock = GetAirlock(name);
for (int i = 0; i < group.Blocks.Count; i++)
{
IMyDoor door = group.Blocks[i] as IMyDoor;
if (door != null)
{
if (door.Open)
airlock.OuterOpen = true;
airlock.outerDoors.Add(door);
continue;
}
IMyLightingBlock light = group.Blocks[i] as IMyLightingBlock;
if (light != null)
{
airlock.outerLights.Add(light);
continue;
}
IMySoundBlock sound = group.Blocks[i] as IMySoundBlock;
if (sound != null)
{
airlock.outerSound.Add(sound);
}
IMyAirVent airvent = group.Blocks[i] as IMyAirVent;
if (airvent != null)
{
float pres = (airvent.IsPressurized() ? airvent.GetOxygenLevel() : -1f);
if (pres > airlock.OuterPressure)
airlock.OuterPressure = pres;
continue;
}
}
return;
}
}
public void Run(string argument)
{
int tmpIdx = argument.Trim().LastIndexOf(" ");
string cmd_airlock;
string cmd_command;
if (tmpIdx >= 0)
{
cmd_airlock = argument.Substring(0, tmpIdx);
cmd_command = (tmpIdx + 1 < argument.Length ? argument.Substring(tmpIdx + 1) : "toggle");
}
else
{
cmd_airlock = argument;
cmd_command = "toggle";
}
for (int i = 0; i < airlocks.CountAll(); i++)
airlocks.GetItemAt(i).Reset();
List<IMyBlockGroup> controlGroups = new List<IMyBlockGroup>();
MM.Debug("Processing inner and outer groups");
List<IMyBlockGroup> BlockGroups = new List<IMyBlockGroup>();
MM._GridTerminalSystem.GetBlockGroups(BlockGroups);
for (int gid = 0; gid < BlockGroups.Count; gid++)
{
IMyBlockGroup group = BlockGroups[gid];
string name = group.Name.ToLower();
if (!name.StartsWith(MMConfig.GROUP_TAG))
continue;
if (name.StartsWith(MMConfig.GROUP_TAG + ' ' + MMConfig.CONTROL_TAG))
{
controlGroups.Add(group);
continue;
}
AddGroup(group);
}
MM.Debug("Processing control group");
for (int gid = 0; gid < controlGroups.Count; gid++)
{
AddGroup(controlGroups[gid]);
}
MM.Debug("Processing LCD panels");
for (int i = 0; i < panelList.Count; i++)
{
panelList[i].SortPanels();
MMLCDTextManager.SetupLCDText(panelList[i]);
MMLCDTextManager.ClearText(panelList[i]);
}
for (int i = 0; i < airlocks.CountAll(); i++)
{
MMAirlock airlock = airlocks.GetItemAt(i);
if (cmd_airlock == airlock.name)
airlock.command = cmd_command;
airlock.Process();
}
MM.Debug("Updating panels");
for (int i = 0; i < panelList.Count; i++)
panelList[i].Update();
}
}
// MMAPI below (do not modify)
// IMyTerminalBlock collection with useful methods
public class MMBlockCollection
{
public List<IMyTerminalBlock> Blocks = new List<IMyTerminalBlock>();
// add Blocks with name containing nameLike
public void AddBlocksOfNameLike(string nameLike)
{
if (nameLike == "" || nameLike == "*")
{
List<IMyTerminalBlock> lBlocks = new List<IMyTerminalBlock>();
MM._GridTerminalSystem.GetBlocks(lBlocks);
Blocks.AddList(lBlocks);
return;
}
string group = (nameLike.StartsWith("G:") ? nameLike.Substring(2).Trim().ToLower() : "");
if (group != "")
{
List<IMyBlockGroup> BlockGroups = new List<IMyBlockGroup>();
MM._GridTerminalSystem.GetBlockGroups(BlockGroups);
for (int i = 0; i < BlockGroups.Count; i++)
{
IMyBlockGroup g = BlockGroups[i];
if (g.Name.ToLower() == group)
Blocks.AddList(g.Blocks);
}
return;
}
MM._GridTerminalSystem.SearchBlocksOfName(nameLike, Blocks);
}
// add Blocks of type (optional: with name containing nameLike)
public void AddBlocksOfType(string type, string nameLike = "")
{
if (nameLike == "" || nameLike == "*")
{
List<IMyTerminalBlock> blocksOfType = new List<IMyTerminalBlock>();
MM.GetBlocksOfType(ref blocksOfType, type);
Blocks.AddList(blocksOfType);
}
else
{
string group = (nameLike.StartsWith("G:") ? nameLike.Substring(2).Trim().ToLower() : "");
if (group != "")
{
List<IMyBlockGroup> BlockGroups = new List<IMyBlockGroup>();
MM._GridTerminalSystem.GetBlockGroups(BlockGroups);
for (int i = 0; i < BlockGroups.Count; i++)
{
IMyBlockGroup g = BlockGroups[i];
if (g.Name.ToLower() == group)
{
for (int j = 0; j < g.Blocks.Count; j++)
if (MM.IsBlockOfType(g.Blocks[j], type))
Blocks.Add(g.Blocks[j]);
return;
}
}
return;