Secret Doors Configuration and Implementation

Discussion in 'Tech Guides and Help Threads' started by anatoliy, Jun 2, 2021.

Remove all ads!
  1. anatoliy

    anatoliy Established Member

    Joined:
    Feb 18, 2017
    Messages:
    438
    Likes Received:
    118
    Secret Door and actually any object at map can be configured to be detected.

    There are two different ways of detection:
    1. Automatic
    2. Manual (Concentrated)
    Key factors:
    • Target obj_f_secretdoor_flags
    • Target obj_f_secretdoor_dc (lower: DC, higher: minimum search ranks for automatic detection)
    upload_2021-6-2_21-8-23.png
    In WorldEd in Object Properties there are Secret Door DC value and Is Secret Door flag.

    Interestingly Secret Door DC is actually two values: actual detect DC in first 7 bits and minRanksDC.

    When Automatic detection is being performed it first will check how many search skill ranks has. If it is greater than minRanksDC then hidden roll vs Secret Door DC will be rolled.

    Now each time when PC ranks are qualified, and PC did not rolled secret door DC detection, secret door's minRanksDC will increase. Meaning that automatic detection will work again only when the PC would increase Search Ranks.

    See Automatic Detection Code:
    Code:
            static int(__cdecl* orgSearchEventSecretDoorDetect)(objHndl, objHndl) = replaceFunction<int(objHndl, objHndl)>(0x10046CE0, [](objHndl sd, objHndl seeker)
            {
                if (sd) {
                    if (secretdoorSys.isSecretDoor(sd)) {
                        auto static HasLineOfAttack = temple::GetRef<BOOL(objHndl obj, objHndl targetObj, int* hasCover)>(0x100570C0);
                        if (HasLineOfAttack(seeker, sd, 0)) {
                            auto static SecretDoorGetDC = temple::GetRef<BOOL(objHndl)>(0x100465B0);
                            auto minRanksDCminus1 = SecretDoorGetDC(sd);
                            auto skillRanksSearch = critterSys.SkillBaseGet(seeker, SkillEnum::skill_search);
                            if (skillRanksSearch > minRanksDCminus1) {
                                auto dc = secretdoorSys.getSecretDoorDC(sd);
                                auto result = skillSys.SkillRoll(seeker, SkillEnum::skill_search, dc, 0, 4);
                                if (result) {
                                    auto static SecretDoorDetect = temple::GetRef<BOOL(objHndl sd, objHndl seeker)>(0x10046920);
                                    return SecretDoorDetect(sd, seeker);
                                }
    
                                auto v5 = (((uint16_t)skillRanksSearch + 1) << 7) & 0x3F80;
                                auto sdFlags = objects.getInt32(sd, obj_f_secretdoor_flags);
                                sdFlags = sdFlags & 0xFFFFC07F | v5;
                                objects.setInt32(sd, obj_f_secretdoor_flags, sdFlags);
                            }
                        }
                    }
                }
                return 0;
            });
    When Concentrated Search (manual) is made, there will be no roll. In fact it is Take 20 without passing time.
    So if PC has +4 in Search Skill, roll result will be 24=20+4.

    Also useful function to configure secret object programmatically:
    Code:
    def obj_setup_secret(obj, secret_door_dc, automatic_detect_allowed_from_ranks = 0):
        assert isinstance(obj, toee.PyObjHandle)
        assert isinstance(secret_door_dc, int)
        assert isinstance(automatic_detect_allowed_from_ranks, int)
    
        OSDF_SECRET_DOOR = 0x10000
        obj.obj_set_int(toee.obj_f_secretdoor_flags, OSDF_SECRET_DOOR)
    
        dc_value = (automatic_detect_allowed_from_ranks << 7) + secret_door_dc
        obj.obj_set_int(toee.obj_f_secretdoor_dc, dc_value)
        return
     
    Last edited: Jun 3, 2021
  2. Sitra Achara

    Sitra Achara Senior Member

    Joined:
    Sep 1, 2003
    Messages:
    3,152
    Likes Received:
    273
    I sense a pull request coming :)

    On that note, another factor is the "Seen scenery" list maintained by the game. This list was meant to only allow you to search for a SD once. It was buggy however in the sense that loading a game and then quitting to menu did not reset the memory where it's held, so if you started a new game you would be unable to detect those secret doors. If you're turning attention towards SD you may want to fix this at the root (I just worked around it by disabling the lookup on the Seen scenery list).
     
    anatoliy likes this.
  3. Shiningted

    Shiningted I want my goat back Global Moderator

    Joined:
    Oct 23, 2004
    Messages:
    12,359
    Likes Received:
    237
    Was that the root of the secret door bug?

    @anatoliy - can't remember if I mentioned this but there are some hidden items sprinkled around KotB (treasures like bolts of silk) that were hidden using that technique.
     
    anatoliy likes this.
  4. Sitra Achara

    Sitra Achara Senior Member

    Joined:
    Sep 1, 2003
    Messages:
    3,152
    Likes Received:
    273
    Yes. IIRC there's a few other bugs of that sort, where buffers aren't reset when quitting to main menu / starting new game.
     
  5. anatoliy

    anatoliy Established Member

    Joined:
    Feb 18, 2017
    Messages:
    438
    Likes Received:
    118
    I forgot to add Concentrated Search.

    When Concentrated Search is made, there will be no roll. In fact it is Take 20 without passing time.
    So if PC has +4 in Search Skill, roll result will be 24=20+4.
     
  6. Shiningted

    Shiningted I want my goat back Global Moderator

    Joined:
    Oct 23, 2004
    Messages:
    12,359
    Likes Received:
    237
    Correct. Hence the DCs tend to be in the 20s (or 30s if it is for something late game). Pick Lock is the same (take 20), but Disarm Traps rolls, since you could fail and set off the trap.
     
    anatoliy likes this.
  7. anatoliy

    anatoliy Established Member

    Joined:
    Feb 18, 2017
    Messages:
    438
    Likes Received:
    118
    The funny thing - in vanilla that Take 20 roll produces history item, but does not print it. I just enabled the print and instead of Search it says Spellcraft))

    upload_2021-6-3_15-31-10.png
     
Our Host!