1. This forum is obsolete and read-only. Feel free to contact us at support.keenswh.com

Depressurisation

Discussion in 'Programming (In-game)' started by erik9631, Apr 3, 2015.

Thread Status:
This last post in this thread was made more than 31 days old.
  1. erik9631

    erik9631 Trainee Engineer

    Messages:
    60
    I am desperate.

    I am trying to make a SIMPLE depresurisation sytem. Here is how it works:
    I have door 1 and door 2.
    Door 1 is open door 2 is closed.
    You go in, press the button, door 1 closes, vent sucks the air into the tank and door 2 opens.
    Really simple to do with the timer block.
    NOW THE ISSUE:
    If you want to go from outside inside or simply when door 2 is open and door 1 is closed this happens:
    You go inside, press the button, door 1 opens (Now both are open and all the air in the ship is sucked outside)
    you wait 5 seconds while the room is being pressurized (All the air is getting sucked out) and the door 2 closes.
    There are thousands of solutions how to make this work including checking door states, checking air pressure, checking timers, or simply making 3 timer blocks with one master executing the 2 slaves in an OR sequence, but thanks to the unbelievable limited API I am unable to do that.
    Now tell me how am I supposed to make a system such as this which actually works?
    What is even the point of adding oxygen if I am totally and completely unable to keep it in my ship?
    "Screw it do it manualy" you say?
    Oh and what if I decide to go outside and one of my friends is inside and later decides to go outside? He is forced to open one of the doors keeping the air inside.
    So far, the system is only one way.
    I would appreciate if you helped me to solve this. I do not care if it requires 200 timer blocks.
    Just tell me how can I make this work.
    Thank you!
     
  2. Sibz

    Sibz Apprentice Engineer

    Messages:
    361
    I have automatic airlocks based on a sensor covering exit doors.

    Instructions atop of the code:
    https://pastebin.com/X2YzCiX4

    EDIT: updated minor bugs
     
    Last edited: Apr 4, 2015
  3. irinia

    irinia Trainee Engineer

    Messages:
    27
    Here is how my (slightly complicated and large interior) airlock system works:
    I have 3 button panels,1 "trigger" light, 2 sensors, 2 doors. I have not yet worked in the air vent, but that doesn't seem to be your issue...
    The sensors are set to automatically open and close the appropriate door
    The button panels change the on/off state of the trigger light:The inside panel sets it on, the outside panel sets it off, and the inside panel has both options

    Steady state:
    The light on/off state reflects the pressurization state
    The appropriate door is on
    The other door is off
    The door sensors are on
    Every cycle, the script insures that the other door is off

    Cycle is activated by the trigger light state not matching the pressurization state:
    Step 1:
    Door sensors are off
    Doors are on
    Doors told to close
    Step 2:
    Doors are off
    Door sensors are on
    Depressurization timer
    Step 3:
    The new door is on
    If the door sensor for that door is active, open it (because any event while it was off is apparently ignored)

    I have found that this system works without trouble. Hope this helps.

    Code:
    void AirlockSM(int iIdx,string sName){
      if(!AirlockIsOperable(sName)){
        return;
      }
      if(afAirlockState[iIdx]>=1.0f){
        //Air
        if(afAirlockState[iIdx]>=2.0f){
          Do("Door "+sName+" Airlock Inside","OnOff_Off");
          Do("Door "+sName+" Airlock Space","OnOff_Off");
    
          Do("Sensor "+sName+" Airlock Inside Door","OnOff_On");
          Do("Sensor "+sName+" Airlock Space Door","OnOff_On");
          SetLightColor("Light "+sName+" Airlock Status",255,255,0);
          afAirlockState[iIdx]=1.0f-fAirlockIncrement;
          WritePanel("LCD "+sName+" Airlock Status","\n Depressurizing\n "+afAirlockState[iIdx].ToString()+" ATM");
        }else if(!IsEnabled("Trigger "+sName+" Airlock")){
          WritePanel("LCD "+sName+" Airlock Status","\n Pressurized\n Preparing");
          SetLightColor("Light "+sName+" Airlock Status",255,255,255);
          Do("Sensor "+sName+" Airlock Inside Door","OnOff_Off");
          Do("Sensor "+sName+" Airlock Space Door","OnOff_Off");
    
          Do("Door "+sName+" Airlock Inside","OnOff_On");
          Do("Door "+sName+" Airlock Inside","Open_Off");
          Do("Door "+sName+" Airlock Space","OnOff_On");
          Do("Door "+sName+" Airlock Space","Open_Off");
          afAirlockState[iIdx]=2.1f;
        }else{
          WritePanel("LCD "+sName+" Airlock Status","\n Pressurized");
          SetLightColor("Light "+sName+" Airlock Status",0,255,0);
          AirlockLockdown("Door "+sName+" Airlock Space");
        }
      }else if(afAirlockState[iIdx]<=0.0f){
        //Vacuum
        if(afAirlockState[iIdx]<=-1.0f){
          Do("Door "+sName+" Airlock Inside","OnOff_Off");
          Do("Door "+sName+" Airlock Space","OnOff_Off");
    
          Do("Sensor "+sName+" Airlock Inside Door","OnOff_On");
          Do("Sensor "+sName+" Airlock Space Door","OnOff_On");
          SetLightColor("Light "+sName+" Airlock Status",255,255,0);
          afAirlockState[iIdx]=0.0f+fAirlockIncrement;
          WritePanel("LCD "+sName+" Airlock Status","\n Pressurizing\n "+afAirlockState[iIdx].ToString()+" ATM");
        }else if(IsEnabled("Trigger "+sName+" Airlock")){
          WritePanel("LCD "+sName+" Airlock Status","\n Depressurized\n Preparing");
          SetLightColor("Light "+sName+" Airlock Status",255,255,255);
          Do("Sensor "+sName+" Airlock Inside Door","OnOff_Off");
          Do("Sensor "+sName+" Airlock Space Door","OnOff_Off");
    
          Do("Door "+sName+" Airlock Inside","OnOff_On");
          Do("Door "+sName+" Airlock Inside","Open_Off");
          Do("Door "+sName+" Airlock Space","OnOff_On");
          Do("Door "+sName+" Airlock Space","Open_Off");
          afAirlockState[iIdx]=-1.1f;
        }else{
          WritePanel("LCD "+sName+" Airlock Status","\n Depressurized");
          SetLightColor("Light "+sName+" Airlock Status",255,0,0);
          AirlockLockdown("Door "+sName+" Airlock Inside");
        }
      }else if(IsEnabled("Trigger "+sName+" Airlock")){
        //Filling
        SetLightColor("Light "+sName+" Airlock Status",255,255,0);
        AirlockLockdown("Door "+sName+" Airlock Inside");
        AirlockLockdown("Door "+sName+" Airlock Space");
        afAirlockState[iIdx]+=fAirlockIncrement;
        if(afAirlockState[iIdx]>=1.0f){
          WritePanel("LCD "+sName+" Airlock Status","\n Pressurized");
          SetLightColor("Light "+sName+" Airlock Status",0,255,0);
          Do("Door "+sName+" Airlock Inside","OnOff_On");
          if(IsDetecting("Sensor "+sName+" Airlock Inside Door")){
            Do("Door "+sName+" Airlock Inside","Open_On");
          }
        }else{
          WritePanel("LCD "+sName+" Airlock Status","\n Pressurizing\n "+afAirlockState[iIdx].ToString()+" ATM");
        }
      }else{
        //Emptying
        //Filling
        SetLightColor("Light "+sName+" Airlock Status",255,255,0);
        AirlockLockdown("Door "+sName+" Airlock Inside");
        AirlockLockdown("Door "+sName+" Airlock Space");
        afAirlockState[iIdx]-=fAirlockIncrement;
        if(afAirlockState[iIdx]<=0.01f){
          afAirlockState[iIdx]=0.0f;
          WritePanel("LCD "+sName+" Airlock Status","\n Depressurized");
          SetLightColor("Light "+sName+" Airlock Status",255,0,0);
          Do("Door "+sName+" Airlock Space","OnOff_On");
          if(IsDetecting("Sensor "+sName+" Airlock Space Door")){
            Do("Door "+sName+" Airlock Space","Open_On");
          }
        }else{
          WritePanel("LCD "+sName+" Airlock Status","\n Depressurizing\n "+afAirlockState[iIdx].ToString()+" ATM");
        }
      }
    }
     
  4. erik9631

    erik9631 Trainee Engineer

    Messages:
    60
    Wait you can actually... use sensors to check if the door is open or closed?
    I tried that and the sensor always returned that there is nothing in front of it...unless it is not part of the ship it is welded to.

    Also I am not even sure if we are speaking the same language.

    How can you simply change states with functions that are not featured in the programmable api?
    You don't even use GridTerminalSystem, you are not using any methods.

    The whole thing is throwing exceptions.
     
    Last edited: Apr 4, 2015
  5. Phoera

    Phoera Senior Engineer

    Messages:
    1,713
    he using own methods, Do method need block name and action name.
    and etc.

    also don't forget you can use new API to know oxygen level.
     
  6. Sibz

    Sibz Apprentice Engineer

    Messages:
    361
    No, I just use sensors (covering external doors) to detect someone wants to exit, then it closes internal door, de-pressurises, opens external door. Then when nobody is at exit door, closes it, re-pressurises and and opens internal door.

    Yeah will throw exceptions if not set-up correctly. Also only tested in Vanilla SE, so cannot guarantee will work with mods.

    Go through the instructions one by one, read carefully, if any you don't understand or still having problems, message me on here and I will try to help.
    1)
    Have a sensor that covers the exit doors but the the internal doors
    Name this sensor 'Airlock Sensor XXX 1'
    - XXX is the unique name of your airlock, eg engineering
    - You can have multiple sensors covering multiple exit doors

    2)
    Name your interior door(s) 'Airlock Door XXX In'
    - XXX is the unique name of your airlock, eg engineering

    3)
    Name your exterior door(s) 'Airlock Door XXX Ex'
    - XXX is the unique name of your airlock, eg engineering

    4)
    Name you air vent for the airlock 'Airlock Vent XXX'
    - XXX is the unique name of your airlock, eg engineering
    - You can have mutple vents

    5)
    Have an LCD for storing airlock state info, name it 'LCDVarStore 1'
    - You can call it anything and update the code below, but it must have 1 after the name

    6)
    Have a block with a unique name, update the code with that name - on the first line of Main()
    -Or you can just call your programmable block, 'PB Door Control'

    7)
    Run this script from a 1 or 2 second timer
    -Have the timer start itself after running the programmable block.

    There's been a couple of updates, try the new code here:
    https://pastebin.com/X2YzCiX4
     
    Last edited: Apr 4, 2015
  7. mhalpern

    mhalpern Senior Engineer

    Messages:
    2,119
    you also don't need to use the sensor to tell if it's open or closed, that's terminal accessible information.
     
  8. shimonu

    shimonu Apprentice Engineer

    Messages:
    396
    For mine (with timers) its something like that (for hangar)
    for opening
    trigger timer 1 close door1, depresurise room
    start timer 2 open door2, turn off door1 (so no accidently opening)

    for closing
    trigger timer 1 close door2
    start timer 2 presurize room, turn on door1
    start timer 3 open door1, turn off door2

    First timer is set to trigger, next ones are delayed to make sure door is close, room presurized/depresurized
    Outside doors are buttons to trigger opening/closing. Iv added some blinking lights if its working (so no trying to open and close at the same time).

    Now I am trying to make it work with script (should be safer)
    Can someone tell me what stupid mistake I am making with this?
    Code:
    string name_air_vent(string vent) 
    { 
        var air_vent = GridTerminalSystem.GetBlockWithName(vent) as IMyAirVent;   
        return air_vent.CustomName;
    }
    Any other block type work except vents and tanks
     
  9. erik9631

    erik9631 Trainee Engineer

    Messages:
    60

    I found the code to be pointlessly complicated so I made my own which is working as well.
    I have been digging in the api the whole day so I eventually found out how it works.

    Only downside might be that I need two timers for it to work correctly, but it is accurate, works with any door, and it can not be broken with people pressing random buttons.

    Still thanks for the help.
     
  10. plaYer2k

    plaYer2k Master Engineer

    Messages:
    3,160
    Not checking for air_vent == null when giving a wrong name in vent.
    Furthermore only the first block with a matching name gets returned by the GetBlockWithName method. So when you got multiple different blocks with the same name, like a spotlight and a programmable block, it might return the wrong type of block than the one you wish to. The result with an as cast would then be null again even if there is a correctly named block per type.
     
  11. shimonu

    shimonu Apprentice Engineer

    Messages:
    396
    Yeah I know it will get first one on list (I am using specific names for this). Ill try putting in check if name is correct.
    Mistake found. Made new progr block in creative. Yup permissions set to none >_<
    Is there a way to check if block has permission in script?
     
  12. plaYer2k

    plaYer2k Master Engineer

    Messages:
    3,160
    Not that i am aware of through ingame programming. Maybe checking the owner of a block aswell as the relation of that owner to another is helpful here. Thus that is the ModAPI and not the ingame programming API
    Code:
    // Sandbox.ModAPI.IMyCubeBlock
    /// <summary>
    ///
    /// </summary>
    /// <param name="playerId">Id of player to check relation with (not steam id!)</param>
    /// <returns>Relation of defined player to the block</returns>
    MyRelationsBetweenPlayerAndBlock GetUserRelationToOwner(long playerId);
     
  13. Xentor

    Xentor Junior Engineer

    Messages:
    869
    I actually posted a script last week that might do what you need... Apparently about six minutes after you created this thread... That's just weird... Heh...

    https://steamcommunity.com/sharedfiles/filedetails/?id=418962899

    Basically, it all works with a state machine. I modeled the airlock process as a state variable, and the script ticks every second and just moves through the process based on what state it's in. So it needs one programming block and one timer block, and you have to follow a naming convention for the doors/vents and optional sound blocks and LCD.
     
  14. shimonu

    shimonu Apprentice Engineer

    Messages:
    396
    Thank you.
    Last question (I hope). How to check if air vent is set to depressurize? (I am making some stupid misstype again probably).
    Can't check scripts on steam (not loading for me ingame).
     
  15. Mosseman

    Mosseman Apprentice Engineer

    Messages:
    195
    I'd like to know this, too.
     
  16. mexmer

    mexmer Senior Engineer

    Messages:
    1,977
    On Local/MP game you can use code bellow, on DS this code doesn't work due missing strings
    Code:
    IMyAirvent vent = (IMyAirVent)GridTerminalSystem.GetBlockWithName("Air Vent Exisiting"); // replace name with correct
    StringBuilder temp = new StringBuilder();
    vent.GetActionwithName("Depressurize").WriteValue(vent, temp);
    if (temp.ToString() == "On")
    LCD.WritePublicString("Decompressing");
    else
    LCD.WritePublicString("Pressuring");
    
     
  17. Morphik

    Morphik Apprentice Engineer

    Messages:
    186
    I made a extremely simple script, for one airlock with only 2 doors. a outer door and a inner with a LCD to show the rooms Oxygen level, the vents depressurization state and the outer doors open/close status.

    The whole thing is controlled by changing the set Air vent depressurize button to On or Off.

    I am currently trying to get this to work with door groups and maybe even multiple airlocks like a master control.
    Code:
    void Main()
    {
    // Name a LCD or Text Panel to "Vent Output: ..." Where ... is the name of the vent that
    // de-pressurizes your airlock. Keep in mind the space after : is needed!
    
    // Name your Interior and Exterior Door.
    string intDoor = "Airlock Interior";
    string extDoor = "Airlock Exterior";
    
    List<IMyTerminalBlock> screens = new List<IMyTerminalBlock>();
    List<IMyTerminalBlock> doors = new List<IMyTerminalBlock>();
    
    GridTerminalSystem.GetBlocksOfType<IMyDoor>(doors);
    GridTerminalSystem.GetBlocksOfType<IMyTextPanel>(screens);
    
        for (int i = 0; i < screens.Count; i++)
        {
        IMyTextPanel screen = (IMyTextPanel)screens[i];
        var door1 = GridTerminalSystem.GetBlockWithName(intDoor) as IMyDoor;
        var door2 =  GridTerminalSystem.GetBlockWithName (extDoor) as IMyDoor;
            if (screen.CustomName.IndexOf("Vent Output: ") == 0)
            {
            IMyAirVent vent = (IMyAirVent)GridTerminalSystem.GetBlockWithName(screen.CustomName.Substring(13));
    
            float airLevel;                    
            airLevel = vent.GetOxygenLevel();
    
            StringBuilder depressurize = new StringBuilder();
            vent.GetActionWithName("Depressurize").WriteValue(vent, depressurize);
    
            StringBuilder seal = new StringBuilder();  
            door2.GetActionWithName("Open").WriteValue(door2, seal);
    
            screen.SetValue("FontSize", 3f);
            screen.ShowTextureOnScreen();
            screen.WritePublicText("\r\n  Oxygen:\r\n  "
                + String.Format("{0:P2}", airLevel)
                + "\r\n  Depres: " + depressurize
                + "\r\n  Seal: " + seal);
            screen.ShowPublicTextOnScreen();
    
            // Close Interior and Turn On Exterior
            if (depressurize.ToString() == "On" && airLevel > 0 && vent.IsPressurized() == true)  
            {  
                door1.GetActionWithName("Open_Off").Apply(door1);
                door2.GetActionWithName("OnOff_On").Apply(door2);  
            }
    
            // Open Exterior and Turn Off Interior
            if (depressurize.ToString() == "On" && airLevel == 0 && vent.IsPressurized() == true)
            {
                door2.GetActionWithName("Open_On").Apply(door2);
                door1.GetActionWithName("OnOff_Off").Apply(door1);
            }
    
            // Close Exterior and Turn On Interior
            if (depressurize.ToString() == "Off" && airLevel == 0 && vent.IsPressurized() == false)
            {
                door2.GetActionWithName("Open_Off").Apply(door2);
                door1.GetActionWithName("OnOff_On").Apply(door1);
            }
    
            // Open Interior and Turn Off Exterior
            if (depressurize.ToString() == "Off" && airLevel > 0 && vent.IsPressurized() == true)
            {
            door1.GetActionWithName("Open_On").Apply(door1);
            door2.GetActionWithName("OnOff_Off").Apply(door2);
            }
            }
        }
    }
     
  18. mexmer

    mexmer Senior Engineer

    Messages:
    1,977
    As stated elsewhere
    <IMyAirvent>.IsPressurized() is missnamed method - it returns state of room eg. if room is sealed (can be pressurized) or not. it has nothing with current oxy level in room, or with mode of AirVent.
    Obviously if IsPressurized() is false, room will have 0% oxygen, not only that, you will not able to raise it's oxygen level at all.

    Method <IMyAirvent>.IsPressurized() is still usefull, can be used for example for detecting room breaches - eg. if your outerwall to sealed room is broken, room not only loose pressure (oxygenlevel=0) but also can no longer be pressurized (IsPressurized = false)
     
  19. Morphik

    Morphik Apprentice Engineer

    Messages:
    186
    I know my script doesn't need the IsPressurized parameters, but it doesn't hurt to have it check.
     
  20. mexmer

    mexmer Senior Engineer

    Messages:
    1,977
    Well, check might be good, if you for example don't want to allow open door to section, that is not pressurized and cannot be pressurized (eg. is breached), to prevent airloss, but you should use this check with it's meaning in mind, that's all. It might have adversary effects on your scripts otherwise.
     
Thread Status:
This last post in this thread was made more than 31 days old.