Jump to content

ACS: simulated door gotcha.


Recommended Posts

I thought I'd share this as I struggled with this for ages until it clicked as to what was going on...

 

I have a map in progress, where I have a number of 3D platforms used to simulate doors. I have a script to handle these and I noticed that if I activated it again, the door script would re-run without completing the first one. The end result was that the door came to rest 1 door height too low (64). So I tried to set a map global variable to prevent this. The logic seems sound:

 

1: have a global var defaulting to all doors are inactive

2: the script only does stuff if this global indicates that door cycling is complete (=1)

3: if so, the script sets it =0 - i.e. the door cycle is not complete (which should prevent re-triggering of the door by re-activating the switch or quickly moving to the other switch in the save of the main door...)

4: at this point, it should not be possible to retrigger the contents of the if() statement...

/*
prevent retriggering of the door if it is cycling:
*/
int doorCyclingComplete = 1;
script 2 (int sectorTag){
    if(doorCyclingComplete == 1){    //no door is cycling
        doorCyclingComplete = 0;
      
        while(doorCyclingComplete != 1){
            FloorAndCeiling_RaiseByValue (sectorTag, 12, 64);
            Delay(144);
            FloorAndCeiling_LowerByValue (sectorTag, 12, 64);
            doorCyclingComplete = 1;
        }    
    }
}

If I activate the switch/door 'normally' it all works as it should, however, if I repeatedly re-trigger, I can get the 'door' to come to rest too low (by 64). The problem seemed to be that the re-trigger happened while the door was lowering. 

 

It suddenly occurred to me that `doorCyclingComplete` being reset to 1 happened while the door was still moving down

 

Adding another delay solved this:

int doorCyclingComplete = 1;
script 2 (int sectorTag){
    if(doorCyclingComplete == 1){    //no door is cycling
        doorCyclingComplete = 0;
        while(doorCyclingComplete != 1){
            FloorAndCeiling_RaiseByValue (sectorTag, 12, 64);
            Delay(144);
            FloorAndCeiling_LowerByValue (sectorTag, 12, 64);
            log(s:"delaying before enabling");
            Delay(72);
            log(s:"releasing door flag");
            doorCyclingComplete = 1;
        }    
    }
}

 

To do this properly would require the final delay to be specific for the distance moved and the speed of movement.


This prompted the thought - do these line special ACS functions return something on completion? Or provide a onCompletion type callback? If so, it would be more elegant to do something like:

...
while(!FloorAndCeiling_LowerByValue (sectorTag, 12, 64)){  }
//do end stuff after while, on completion

 

or (a bit AJAX'y):

...
FloorAndCeiling_LowerByValue (sectorTag, 12, 64).finished(function(){
    //do stuff on 'finished' callback
})

Just a thought...

 

Share this post


Link to post

There's TagWait that lets the script wait until a sector stopped moving.

 

So as I understand it you just want to let a 3D floor act like a door, right? Then you're overthinking it. Check out the attached map, it simulates a 3D floor door by using the Platform Raise Wait Lower action and Sector Set Link.

3ddoor.zip

Edited by boris

Share this post


Link to post

Ahhh! Yes, thank you that is exactly what I need. I have a crap-ton to learn... So the TagWait function could be considered a 'moveCompeted' callback then. Cool.

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...