Author Topic: Hidden doors in my module.  (Read 545 times)

Legacy_whirlwind2001

  • Newbie
  • *
  • Posts: 4
  • Karma: +0/-0
Hidden doors in my module.
« on: April 22, 2011, 10:22:13 am »


                Hello all,
I have started working on my own world.  I want to add hidden doors in some of my shops and dungeons so that if you click on an ordinary bit of wall it reveals a door that takes you somewhere.  Now I am not sure how it would work in NWN like instead of clicking on the wall maybe it it some kind of 'spot' check.  I don't mind how, I just want to know how to do it lol.  I found a 'secret door' in the toolset and the 'secret door' trigger.  I placed the door on/next to a wall and then painted the trigger.  But when I test the module the door is visable lol.  Please can somebody assist me and excuse my dubious termanology, I am really learning a lot and quickly here '<img'>
Thanks,
               
               

               
            

Legacy_Tassle_Hof

  • Newbie
  • *
  • Posts: 43
  • Karma: +0/-0
Hidden doors in my module.
« Reply #1 on: April 22, 2011, 01:51:37 pm »


               Use the Secret Object Triggers under triggers. You paint the trigger on the ground, make it as big or small as you want depending on how hard you want it to be to find the secret door, then in the properties of the trigger change the tag to a name you want ie SecretDoor1. Then put a waypoint were you want the door to appear, give it the tag LOC_SecretDoor1 (Or whatever your tag is just make sure you have the LOC_ in front of it.) Then put a waypoint where you want the secret door to take the PC and tag is DST_SecretDoor1 (Or whatever your tag is just, once again, make sure you have the DST_ in front.)
If you want the door easy to find change the number on the advanced page of the trigger, it is usually a 15 by default, the lower the number the easier it is to find.
Make sure the pointy end of the waypoint where you want the door to appear is facing towards you or your door will appear backwards and the PC won't be able to open it.
Hope this helps. Good luck.
               
               

               
            

Legacy_TSMDude

  • Hero Member
  • *****
  • Posts: 1515
  • Karma: +0/-0
Hidden doors in my module.
« Reply #2 on: April 22, 2011, 03:36:57 pm »


               Placeable Doors:
Placeable doors are easy. You cannot use a "Hidden Wall Door" or "Hidden Trapdoor" from the miscelaneous interior standard pallet. Instead go to "Secret Object" and select a door from there. Now give the door a unique tag (For example "DoorPlaceableTag"). Under most circumstances you may want to remove the word "Secret" from the name so only the word "Door" will come up in-game if the player mouses over it.

Finally you need to place the waypoint. This waypoint will be the door's destination. Place the waypoint at the point where you want the door users to teleport to when thy go through the door and give it the same tag as your placeable door with the prefix "DST_" (for example "DST_DoorPlaceableTag").

Optionally you can use any door placeable and a waypoint using the naming conventions above and simply change the OnUsed script to x0_o2_use_wdoor.

If you open the OnUsed script you will see that the comments tell you to use a "LOC_" prefix. This is wrong. It is nothing shy of sadistic that this has never been corrected in any of the patches.


Secret Doors
How it works:
A secret door is simulated by putting an "OnHeartbeat" script on an invisible "trigger placeable" object. Every heartbeat (about once every six seconds) this script checks the skills of nearby players and rolls to see if the most skilled searcher has spotted the secret door.

When one of the players spots the door the trigger placeable destroys itself, spawns in a door at it's location, and sets it's Tag name as a string variable on it.

The door has an OnUsed script that uses the string variable to teleport anyone who uses it (along with henchmen and pets) to a waypoint with the same name.

How to set it up:
Place a "Hidden Trapdoor Trigger" or a "Hidden Wall Door Trigger" where you want the door to appear and give it a unique tag (for example "SecretDoorTag"). You will find the "Hidden Wall Door Trigger" and "Hidden Trapdoor Trigger" in the standard pallet under "Miscellaneous Interior". Place the trigger object in the center of the desired detection radius.

Next you need to place the waypoint that will act as the door's destination. Place the waypoint at the point where you want the door users to teleport when they go through the door to and give it the same tag as the Hidden Door Trigger object with the prefix "DST_" (for example "DST_SecretDoorTag").

I am referring to the "Hidden Trapdoor Trigger" and the "Hidden Wall Door Trigger" as "trigger objects" to avoid confusion, as they are not technically "triggers". In other words... they are not painted from the "trigger" pallet. They are placed from the "placeable" pallet. They're just called "triggers" in the placeable menu.

Hidden door trigger objects use the "invisible object" appearance. When the door appears it will be facing the same direction as the placeable.

To set the secret door's properties change the following fields:


•Reflex Save: Determines the distance at which a PC can search for this door in meters.
•Will Save: Determines the DC of finding this door.

Wall Door Placement Guidelines:
When placing wall doors be careful to place the trigger so when the door spawns it will be flush against the wall. Place the "hidden wall door trigger" so the arrow faces away from the wall and the back edge of the invisible object placeable is flush with the wall.

Wall Doors must be placed where they can be accessed by the players in-game. This can be problematic sometimes. For example, when using the city interior tileset the walkmesh often does not extend all the way to the wall, especially in the alcoves. If you spawn your doors so they appear flush against these walls they will be too far off the walkmesh for the players to fire the "OnUsed" event. A few placeable walls can go a long way towards solving this problem. There's a great selection of placeable walls in the Community Expansion Pack. Also... Door Placables set as "static" objects and placed backwards, with the doors facing the wall, can make a reasonable looking wall placable. As a rule if you cannot click-select the door in the toolset's graphic window it's too far off the walkmesh to be usable by the players.


Changing the Door Spawned by Hidden Door Triggers:
You will need to create a new door blueprint and modify the OnHeartbeat script if you want a door other than the default door to spawn.

Before you ask... No... You cannot use the secret doors under "secret object" in the standard pallet. The OnUsed script is wrong. The door placeables in the "secret object" pallet are for use with the Secret Object Triggers in the standard "Triggers" pallet. Use of these triggers is beyond the scope of this post.


1.First... create a new blueprint for the door appearance that you want to spawn. For example... the default wall door has a wooden appearance. To create a stone door select the Hidden Wall Door and "Edit Copy". Change the appearance, for example, to "Wall Door Stone". I also like to change the name to "Secret Door" (it just looks cooler than the default name). Make a note of the new placeable resref for the next step, modifying the hidden trigger's OnHeartbeat script.
2.Now place a Hidden Wall Door Trigger or Hidden Trapdoor Trigger placeable object where you want your custom secret door to spawn.
3.Copy and Paste the below script into the script editor. Change the area highlighted in red (around line 116) to the resref (not tag) of the placable object that you created in step one. Give your new script a unique name. Now go into the properties of your hidden door trigger and replace the OnHeartbeat script with your new script.
4.Set the destination waypoint the same way you would if you were using a default door. Just place a waypoint at the point where you want the door users to teleport to and give it the same tag with the prefix "DST_" (for example "DST_SecretDoorTag").
The OnHeartbeat script for your Hidden Door Trigger object:
Copy and paste everything in black. The red font you will replace with the resref of your custom door placeable.


Code:
//::///////////////////////////////////////////////
//:: nw_o2_dtwalldoor.nss
//:: Copyright © 2001-2 Bioware Corp.
//:://////////////////////////////////////////////
//
// This script runs on either the Hidden Trap Door
// or Hidden Wall Door Trigger invisible objects.
// This script will do a check and see
// if any PC comes within a radius of this Trigger.

// If the PC has the search skill or is an Elf then
// a search check will be made.

// It will create a Trap or Wall door that will have
// its Destination set to a waypoint that has
// a tag of DST_

// The radius is determined by the Reflex saving
// throw of the invisible object

// The DC of the search stored by the Willpower
// saving throw.

//
//:://////////////////////////////////////////////
//:: Created By : Robert Babiak
//:: Created On : June 25, 2002
//::---------------------------------------------
//:: Modifyed By : Robert, Andrew, Derek
//:: Modifyed On : July - September
//:://////////////////////////////////////////////

void main()
{
// get the radius and DC of the secret door.
float fSearchDist = IntToFloat(GetReflexSavingThrow(OBJECT_SELF));
int nDiffaculty = GetWillSavingThrow(OBJECT_SELF);

// what is the tag of this object used in setting the destination
string sTag = GetTag(OBJECT_SELF);

// has it been found?
int nDone = GetLocalInt(OBJECT_SELF,"D_"+sTag);
int nReset = GetLocalInt(OBJECT_SELF,"Reset");

// ok reset the door is destroyed, and the done and reset flas are made 0 again
if (nReset == 1)
{
nDone = 0;
nReset = 0;

SetLocalInt(OBJECT_SELF,"D_"+sTag,nDone);
SetLocalInt(OBJECT_SELF,"Reset",nReset);

object oidDoor= GetLocalObject(OBJECT_SELF,"Door");
if (oidDoor != OBJECT_INVALID)
{
SetPlotFlag(oidDoor,0);
DestroyObject(oidDoor,GetLocalFloat(OBJECT_SELF,"ResetDelay"));
}

}


int nBestSkill = -50;
object oidBestSearcher = OBJECT_INVALID;
int nCount = 1;

// Find the best searcher within the search radius.
object oidNearestCreature = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC);
int nDoneSearch = 0;
int nFoundPCs = 0;

while ((nDone == 0) &&
(nDoneSearch == 0) &&
(oidNearestCreature != OBJECT_INVALID)
)
{
// what is the distance of the PC to the door location
float fDist = GetDistanceBetween(OBJECT_SELF,oidNearestCreature);

if (fDist <= fSearchDist) { int nSkill = GetSkillRank(SKILL_SEARCH,oidNearestCreature); if (nSkill > nBestSkill)
{
nBestSkill = nSkill;
oidBestSearcher = oidNearestCreature;
}
nFoundPCs = nFoundPCs +1;
}
else
{
// If there is no one in the search radius, don't continue to search
// for the best skill.
nDoneSearch = 1;
}
nCount = nCount +1;
oidNearestCreature = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, OBJECT_SELF ,nCount);
}

if ((nDone == 0) &&
(nFoundPCs != 0) &&
(GetIsObjectValid(oidBestSearcher))
)
{
int nMod = d20();

// did we find it.
if ((nBestSkill +nMod > nDiffaculty))
{
location locLoc = GetLocation (OBJECT_SELF);
object oidDoor;
// yes we found it, now create the appropriate door, EDIT THE LINE BELOW TO CHANGE RESREF OF SPAWNED DOOR
oidDoor = CreateObject(OBJECT_TYPE_PLACEABLE,"NW_PL_HIDDENDR01",locLoc,TRUE);

SetLocalString( oidDoor, "Destination" , "DST_"+sTag );
// make this door as found.
SetLocalInt(OBJECT_SELF,"D_"+sTag,1);
SetPlotFlag(oidDoor,1);
SetLocalObject(OBJECT_SELF,"Door",oidDoor);

} // if skill search found
} // if Object is valid
}
               
               

               
            

Legacy_whirlwind2001

  • Newbie
  • *
  • Posts: 4
  • Karma: +0/-0
Hidden doors in my module.
« Reply #3 on: April 22, 2011, 03:43:04 pm »


               Thanks to both of you.  And, is there a way to make these secret doors class restricted?  Or am I pushing it now '<img'>
Thank you,
               
               

               
            

Legacy_datamaster

  • Jr. Member
  • **
  • Posts: 94
  • Karma: +0/-0
Hidden doors in my module.
« Reply #4 on: May 08, 2011, 07:33:47 pm »


               This is something I have wondered about sometimes myself. '<img'> I will be making use of this.
               
               

               
            

Legacy_Ralthis

  • Jr. Member
  • **
  • Posts: 90
  • Karma: +0/-0
Hidden doors in my module.
« Reply #5 on: May 18, 2011, 03:25:57 pm »


               It is definitely possible to make the secret doors class restricted, but will require some script editing.

1. If you look at the trigger you have placed for the secret door, there is a script in the OnEnter drop down menu called "x0_o2_sec_tdoor2". Use the Edit button beside it to enter the script attached to the trigger. Before you do anything else, SAVE the script under a new name. If you change anything in the default script it will apply to all future secret doors you make in your module (unless you want that, then by all means don't change a thing).

2. Replace the default script by this:
//:://////////////////////////////////////////////////
//:: X0_O2_SEC_TDOOR2
//::    This is an OnEntered script for a generic trigger.
//::    When a PC enters the trigger area, it will perform
//::    a check to determine if the secret item is revealed,
//::    then make it appear if so.
//::
//::    Secret item to be revealed: Secret Stone Trap Door
//::    Checking for: SKILL_SEARCH
//::
//:: Copyright © 2002 Floodgate Entertainment
//:: Created By: Naomi Novik
//:: Created On: 12/08/2002
//:://////////////////////////////////////////////////

#include "x0_i0_secret"


void main()
{
    object oEntered = GetEnteringObject();

    if (GetIsSecretItemRevealed()) {return;}

       // * This checks oEntered to see whether they are of the correct class
       if (GetclassByPosition(1, oEntered) == class_TYPE_* | GetclassByPosition(2, oEntered) == class_TYPE_*
               | GetclassByPosition(3, oEntered) == class_TYPE_*)
           {
               if ( DetectSecretItem(oEntered)) {
                       if (!GetIsPC(oEntered)) {
                                // If a henchman, alert the PC if we make the detect check
                               object oMaster = GetMaster(oEntered);
                               if (GetIsObjectValid(oMaster)
                                       && oEntered == GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oMaster))
                               {
                                       AssignCommand(oEntered, PlayVoiceChat(VOICE_CHAT_SEARCH));
                               }
                       } else {
                               // It's a PC, reveal the item
                               AssignCommand(oEntered, PlayVoiceChat(VOICE_CHAT_LOOKHERE));
                               RevealSecretItem("x0_sec_tdoor2");
                       }
               }
       }
}

3. Replace every class_TYPE_* in the script (there are only 3) with the class type of your choice. You can find the class type choices in the Constants tab in the Script Editor (you can find them easier by typing class_type in the search option). Remember to replace ALL 3 of the class_TYPE_* options with THE SAME class option (this checks all three of oEntered's class positions, in case they decided to multi-class).

4. As you probably guessed from the above, this will only check for one kind of class. If you want to check for more, you will need edit the if() statement containing the GetclassByPosition() functions. All you have to do is place a | (that's a bar found on the right of your keyboard, not the capital letter i) after the last GetclassByPosition() statement, then copy all of the GetclassByPosition() functions I've written for you, and paste them after the |. Then, change the class_TYPE_ constant to whatever new class type you want. Repeat ad nauseum until you've covered all the classes you want to check for.

5. Enjoy the fruits of your labour!
               
               

               


                     Modifié par Ralthis, 18 mai 2011 - 02:30 .