User Tag List

Results 1 to 2 of 2

Thread: Scripting quesitons: Functional NES-style doors in Interior type DMaps

  1. #1
    Octorok CaRmAgE's Avatar
    Join Date
    Oct 2008
    Location
    Historia
    Age
    35
    Posts
    494
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    vBActivity - Stats
    Points
    1,331
    Level
    12
    vBActivity - Bars
    Lv. Percent
    41.27%

    Question Scripting quesitons: Functional NES-style doors in Interior type DMaps

    I remember an issue that was brought up about NES doors in Interior type rooms in 2015 (I think? I can't find the thread.), where even though the doors are technically only supposed to work in NES dungeons, they still worked in some Interior DMaps, but not others? I'm not trying to bring the topic back up, but rather, I'd like to script the doors as a workaround. My goal is to have full control of walkability and layering on these screens (which is not possible in NES dungeons), but still have the possibility of using the doors. This is why I'm using the Interior DMap type instead. Anyway, this is less a script request and more a general "is it possible", as I'm sure I can script most of it myself; I'm just stuck on a few things.

    1) Is there a general pattern to which Interior DMaps will have working doors and which won't, so I can detect it? The plan is to create a global script to mimic the behavior, so I'm not copy/pasting FFCs everywhere.
    2) For locked doors, if I change the door type for a particular direction on a screen, is the change permanent?
    3) For shutters, how would I detect if Link is coming from a shutter side only during the first moment he enters the screen, and then subsequently, make him walk inward before shutting the door? Use a variable to keep track of the frames remaining, I guess, but can I make him look like he's walking?

  2. #2
    Is this the end?
    ZC Developer
    Saffith's Avatar
    Join Date
    Jan 2001
    Age
    41
    Posts
    3,389
    Mentioned
    178 Post(s)
    Tagged
    6 Thread(s)
    vBActivity - Stats
    Points
    6,429
    Level
    24
    vBActivity - Bars
    Lv. Percent
    69.42%
    I've actually done this already, though I did it as an FFC script. It's not too big a deal to set up if you don't have many doors. Even if it's just for reference, here it is:

    Code:
    const int BD_SHUTTER=1;
    const int BD_1WAYSHUTTER=2;
    const int BD_LOCKED=3;
    const int BD_BOSSLOCKED=4;
    const int BD_BOMBABLE=5;
    
    ffc script BasicDoors
    {
        // D0-D3: Door type (BD_* constant)
        // D4: Combo number of switch. If the combo at this position changes,
        //     any 1-way shutters will open.
        // D5: If nonzero, the switch is permanent.
        void run(int north, int south, int west, int east, int switchPos, int switchPermanent)
        {
            bool playSound=false;
            int switchStart=Screen->ComboD[switchPos];
            bool switched=false;
            bool checkNorth=north>0;
            bool checkSouth=south>0;
            bool checkWest=west>0;
            bool checkEast=east>0;
            
            InitDoor(DIR_UP, north, ST_DOORUP);
            InitDoor(DIR_DOWN, south, ST_DOORDOWN);
            InitDoor(DIR_LEFT, west, ST_DOORLEFT);
            InitDoor(DIR_RIGHT, east, ST_DOORRIGHT);
            
            // North or south
            if(Link->X==120)
            {
                // Coming through north door
                
                // The way positions are handled has changed since this was written, but it still seems to work well enough.
                if((Game->GetCurDMap()==prevDMap && Link->Y>=160) || (Game->GetCurDMap()!=prevDMap && Link->Y<=0))
                {
                    // Shutter - walk all the way into the room, then close the door
                    if(north==BD_SHUTTER || north==BD_1WAYSHUTTER)
                    {
                        while(Link->Y<32 || Link->Y>=160)
                        {
                            NoAction();
                            Link->InputDown=true;
                            Waitframe();
                        }
                        enterX=Clamp(Link->X, 0, 240);
                        enterY=Clamp(Link->Y, 0, 160);
                    }
                    // Locked- must have been unlocked, so open it up and be sure it's set properly
                    else if(north==BD_LOCKED)
                    {
                        Screen->Door[DIR_UP]=D_UNLOCKED;
                        Screen->State[ST_DOORUP]=true;
                        checkNorth=false;
                    }
                    else if(north==BD_BOSSLOCKED)
                    {
                        Screen->Door[DIR_UP]=D_BOSSUNLOCKED;
                        Screen->State[ST_DOORUP]=true;
                        checkNorth=false;
                    }
                }
                // Coming through south door
                else if((Game->GetCurDMap()==prevDMap && Link->Y<=0) || (Game->GetCurDMap()!=prevDMap && Link->Y>=160))
                {
                    if(south==BD_SHUTTER || south==BD_1WAYSHUTTER)
                    {
                        while(Link->Y>128 || Link->Y<=0)
                        {
                            NoAction();
                            Link->InputUp=true;
                            Waitframe();
                        }
                        enterX=Clamp(Link->X, 0, 240);
                        enterY=Clamp(Link->Y, 0, 160);
                    }
                    else if(south==BD_LOCKED)
                    {
                        Screen->Door[DIR_DOWN]=D_UNLOCKED;
                        Screen->State[ST_DOORDOWN]=true;
                        checkSouth=false;
                    }
                    else if(south==BD_BOSSLOCKED)
                    {
                        Screen->Door[DIR_DOWN]=D_BOSSUNLOCKED;
                        Screen->State[ST_DOORDOWN]=true;
                        checkSouth=false;
                    }
                }
            }
            // East or west
            else if(Link->Y==80)
            {
                // Coming through west door
                if((Game->GetCurDMap()==prevDMap && Link->X>=240) || (Game->GetCurDMap()!=prevDMap && Link->X<=0))
                {
                    if(west==BD_SHUTTER || west==BD_1WAYSHUTTER)
                    {
                        while(Link->X<32 || Link->X>=240)
                        {
                            NoAction();
                            Link->InputRight=true;
                            Waitframe();
                        }
                        enterX=Clamp(Link->X, 0, 240);
                        enterY=Clamp(Link->Y, 0, 160);
                    }
                    else if(west==BD_LOCKED)
                    {
                        Screen->Door[DIR_LEFT]=D_UNLOCKED;
                        Screen->State[ST_DOORLEFT]=true;
                        checkWest=false;
                    }
                    else if(west==BD_BOSSLOCKED)
                    {
                        Screen->Door[DIR_LEFT]=D_BOSSUNLOCKED;
                        Screen->State[ST_DOORLEFT]=true;
                        checkWest=false;
                    }
                }
                // Coming through east door
                else if((Game->GetCurDMap()==prevDMap && Link->X<=0) || (Game->GetCurDMap()!=prevDMap && Link->X>=240))
                {
                    if(east==BD_SHUTTER || east==BD_1WAYSHUTTER)
                    {
                        while(Link->X>208 || Link->X<=0)
                        {
                            NoAction();
                            Link->InputLeft=true;
                            Waitframe();
                        }
                        enterX=Clamp(Link->X, 0, 240);
                        enterY=Clamp(Link->Y, 0, 160);
                    }
                    else if(east==BD_LOCKED)
                    {
                        Screen->Door[DIR_RIGHT]=D_UNLOCKED;
                        Screen->State[ST_DOORRIGHT]=true;
                        checkEast=false;
                    }
                    else if(east==BD_BOSSLOCKED)
                    {
                        Screen->Door[DIR_RIGHT]=D_BOSSUNLOCKED;
                        Screen->State[ST_DOORRIGHT]=true;
                        checkEast=false;
                    }
                }
            }
            
            Waitframe();
            
            if(north==BD_SHUTTER)
            {
                Screen->Door[DIR_UP]=D_SHUTTER;
                playSound=true;
            }
            else if(north==BD_1WAYSHUTTER)
            {
                Screen->Door[DIR_UP]=D_1WAYSHUTTER;
                playSound=true;
            }
            
            if(south==BD_SHUTTER)
            {
                Screen->Door[DIR_DOWN]=D_SHUTTER;
                playSound=true;
            }
            else if(south==BD_1WAYSHUTTER)
            {
                Screen->Door[DIR_DOWN]=D_1WAYSHUTTER;
                playSound=true;
            }
            
            if(west==BD_SHUTTER)
            {
                Screen->Door[DIR_LEFT]=D_SHUTTER;
                playSound=true;
            }
            else if(west==BD_1WAYSHUTTER)
            {
                Screen->Door[DIR_LEFT]=D_1WAYSHUTTER;
                playSound=true;
            }
            
            if(east==BD_SHUTTER)
            {
                Screen->Door[DIR_RIGHT]=D_SHUTTER;
                playSound=true;
            }
            else if(east==BD_1WAYSHUTTER)
            {
                Screen->Door[DIR_RIGHT]=D_1WAYSHUTTER;
                playSound=true;
            }
            
            if(playSound)
                Game->PlaySound(SFX_DOORCLOSE);
            
            Waitframes(8);
            
            while(true)
            {
                if(checkNorth)
                {
                    if((north==BD_LOCKED || north==BD_BOSSLOCKED || north==BD_BOMBABLE) && Screen->ComboS[23]!=15)
                    {
                        Screen->State[ST_DOORUP]=true;
                        Game->SetScreenState(Game->GetCurMap(), Game->GetCurScreen()-16, ST_DOORDOWN, true);
                        checkNorth=false;
                        if(north==BD_BOMBABLE)
                            Screen->Door[DIR_UP]=D_BOMBED;
                    }
                    else if(north==BD_1WAYSHUTTER && Screen->State[ST_DOORUP])
                    {
                        Screen->Door[DIR_UP]=D_OPENSHUTTER;
                        Game->PlaySound(SFX_DOOROPEN);
                        checkNorth=false;
                    }
                }
                
                if(checkSouth)
                {
                    if((south==BD_LOCKED || south==BD_BOSSLOCKED || south==BD_BOMBABLE) && Screen->ComboS[151]!=15)
                    {
                        Screen->State[ST_DOORDOWN]=true;
                        Game->SetScreenState(Game->GetCurMap(), Game->GetCurScreen()+16, ST_DOORUP, true);
                        checkSouth=false;
                        if(south==BD_BOMBABLE)
                            Screen->Door[DIR_DOWN]=D_BOMBED;
                    }
                    else if(south==BD_1WAYSHUTTER && Screen->State[ST_DOORDOWN])
                    {
                        Screen->Door[DIR_DOWN]=D_OPENSHUTTER;
                        Game->PlaySound(SFX_DOOROPEN);
                        checkSouth=false;
                    }
                }
                
                if(checkWest)
                {
                    if((west==BD_LOCKED || west==BD_BOSSLOCKED || west==BD_BOMBABLE) && Screen->ComboS[81]!=15)
                    {
                        Screen->State[ST_DOORLEFT]=true;
                        Game->SetScreenState(Game->GetCurMap(), Game->GetCurScreen()-1, ST_DOORRIGHT, true);
                        checkWest=false;
                        if(west==BD_BOMBABLE)
                            Screen->Door[DIR_LEFT]=D_BOMBED;
                    }
                    else if(west==BD_1WAYSHUTTER && Screen->State[ST_DOORLEFT])
                    {
                        Screen->Door[DIR_LEFT]=D_OPENSHUTTER;
                        Game->PlaySound(SFX_DOOROPEN);
                        checkWest=false;
                    }
                }
                
                if(checkEast)
                {
                    if((east==BD_LOCKED || east==BD_BOSSLOCKED || east==BD_BOMBABLE) && Screen->ComboS[94]!=15)
                    {
                        Screen->State[ST_DOORRIGHT]=true;
                        Game->SetScreenState(Game->GetCurMap(), Game->GetCurScreen()+1, ST_DOORLEFT, true);
                        checkEast=false;
                        if(east==BD_BOMBABLE)
                            Screen->Door[DIR_RIGHT]=D_BOMBED;
                    }
                    else if(east==BD_1WAYSHUTTER && Screen->State[ST_DOORRIGHT])
                    {
                        Screen->Door[DIR_RIGHT]=D_OPENSHUTTER;
                        Game->PlaySound(SFX_DOOROPEN);
                        checkEast=false;
                    }
                }
                
                if(switchPos>0 && !switched && Screen->ComboD[switchPos] != switchStart)
                {
                    switched=true;
                    
                    if(north==BD_1WAYSHUTTER)
                        OpenDoor(DIR_UP, BD_1WAYSHUTTER, switchPermanent>0);
                    if(south==BD_1WAYSHUTTER)
                        OpenDoor(DIR_DOWN, BD_1WAYSHUTTER, switchPermanent>0);
                    if(west==BD_1WAYSHUTTER)
                        OpenDoor(DIR_LEFT, BD_1WAYSHUTTER, switchPermanent>0);
                    if(east==BD_1WAYSHUTTER)
                        OpenDoor(DIR_RIGHT, BD_1WAYSHUTTER, switchPermanent>0);
                    
                    Game->PlaySound(SFX_DOOROPEN);
                    
                    checkNorth=false;
                    checkSouth=false;
                    checkWest=false;
                    checkEast=false;
                }
                
                Waitframe();
            }
        }
        
        void InitDoor(int dir, int type, int state)
        {
            if(Screen->State[state])
            {
                if(type==BD_LOCKED)
                    Screen->Door[dir]=D_UNLOCKED;
                else if(type==BD_BOSSLOCKED)
                    Screen->Door[dir]=D_BOSSUNLOCKED;
                else if(type==BD_BOMBABLE)
                    Screen->Door[dir]=D_BOMBED;
            }
            else if(type==BD_BOMBABLE)
                Screen->Door[dir]=D_BOMB;
        }
        
        void OpenDoor(int dir, int startState, bool permanent)
        {
            if(startState==0)
                return;
            
            if(startState==BD_LOCKED)
            {
                Screen->Door[dir]=D_UNLOCKED;
                Screen->State[dir]=true;
                Game->SetScreenState(Game->GetCurMap(), NextScreen(dir), Opposite(dir), true);
            }
            else if(startState==BD_BOSSLOCKED)
            {
                Screen->Door[dir]=D_BOSSUNLOCKED;
                Screen->State[dir]=true;
                Game->SetScreenState(Game->GetCurMap(), NextScreen(dir), Opposite(dir), true);
            }
            else if(startState==BD_BOMBABLE)
            {
                Screen->Door[dir]=D_BOMBED;
                Screen->State[dir]=true;
                Game->SetScreenState(Game->GetCurMap(), NextScreen(dir), Opposite(dir), true);
            }
            else // BD_SHUTTER
            {
                Screen->Door[dir]=D_OPENSHUTTER;
                if(permanent)
                    Screen->State[dir]=true;
            }
        }
        
        int NextScreen(int dir)
        {
            if(dir==DIR_UP)
                return Game->GetCurScreen()-16;
            else if(dir==DIR_DOWN)
                return Game->GetCurScreen()+16;
            else if(dir==DIR_LEFT)
                return Game->GetCurScreen()-1;
            else
                return Game->GetCurScreen()+1;
        }
    }
    1) Is there a general pattern to which Interior DMaps will have working doors and which won't, so I can detect it? The plan is to create a global script to mimic the behavior, so I'm not copy/pasting FFCs everywhere.
    It's been a while, but if I remember correctly, doors only work in dungeon DMaps. It's probably a DMap flag in 2.55, though.

    2) For locked doors, if I change the door type for a particular direction on a screen, is the change permanent?
    If you also set the appropriate item in Screen->State[] to true, e.g. Screen->State[ST_DOORLEFT]. The ST_DOOR* constants are actually the same as the corresponding DIR_ constants, so you can just use the same value for each if it's easier.

    3) For shutters, how would I detect if Link is coming from a shutter side only during the first moment he enters the screen, and then subsequently, make him walk inward before shutting the door? Use a variable to keep track of the frames remaining, I guess, but can I make him look like he's walking?
    Again, I may not remember correctly, but... If the screen scrolls, Link's X or Y position will be beyond the edge of the screen when he first enters a room. From a non-scrolling warp, he'll appear right at the edge. In any case, if you try tracing his position, you should be able to work it out pretty easily.
    Making him walk in is simple: press the appropriate direction key and unpress everything else until he's far enough into the room.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
About us
Armageddon Games is a game development group founded in 1997. We are extremely passionate about our work and our inspirations are mostly drawn from games of the 8-bit and 16-bit era.
Social