Ok so, while building my module, I realized that there was a bit of an issue with how secret doors function, and not a whole lot of answers out there to clearly address the subject. Well, after long hours of tinkering, and asking for help within the community, we’ve finally managed to put together a working system for secret doors, that functions much better than the original. Ok so, I realized that the original system for secret doors, while it functioned, would only send one, maybe two henchmen through the door with you, and any others would get stuck behind the wall. This was sort of an issue for me, as I’m building a module designed for a full party of up to six. Anyway, here is the full solution I’ve put together along with the help of our awesome community.
Ok so, I’m using the invisible object method, not the built in floor trigger method. I believe I got the hiddenwalldoor and the hiddenwalldoortrigger from the hakpak that the original bioware tutorials suggest. However, this hakpak ripped out alot of cool placeables I was using from my module, so I had to get rid of it. Incredibly though, the secret doors and their triggers remained, allowing me to still use this system. And actually, You probably wouldn’t even need to download the hakpak at all, because it’s the scripts that count. And you could probably create an invisible object of your own to spawn your own custom doors as well.
So, with that being said, here are the scripts I used to make all of this happen.
Here is the script that is placed within the OnHeartbeat of the invisible object to spawn the door of your choice once detected. Keep in mind, this script requires the resref of the door you want to spawn, not the tag.
//::///////////////////////////////////////////////
//:: nw_o2_dtwalldoor.nss
//:: Copyright (c) 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_<tag of this object>
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
oidDoor = CreateObject(OBJECT_TYPE_PLACEABLE,"hiddendoorresref",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
}
And here is the script to place in the OnUsed of your chosen door.
This script uses the tag of your waypoint destination.
//::///////////////////////////////////////////////
//:: Secret door that takes you to a waypoint that
//:: is stored into the Destination local string.
//:: FileName x2_use_secrtdoor
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
*/
//:://////////////////////////////////////////////
//:: Created By: Robert Babiak
//:: Created On: June 25, 2002
//:://////////////////////////////////////////////
//:: Modified By: Andrew Nobbs
//:: Modified On: September 23, 2002
//:: Modification: Removed unnecessary spaces.
//:://////////////////////////////////////////////
void MoveFollowers(object oPC, location lTarget)
{
int nType, nCount;
object oNPC;
for(nType = 1; nType <= 5; nType++)
{
// More than one
if(nType == ASSOCIATE_TYPE_SUMMONED ||
nType == ASSOCIATE_TYPE_HENCHMAN)
{
nCount = 1;
oNPC = GetAssociate(nType, oPC, nCount);
while(GetIsObjectValid(oNPC))
{
SendMessageToPC(oPC, "Moving your associate: " + GetName(oNPC));
AssignCommand(oNPC, ClearAllActions());
AssignCommand(oNPC, JumpToLocation(lTarget));
MoveFollowers(oNPC, lTarget);
nCount++;
oNPC = GetAssociate(nType, oPC, nCount);
}
}
// Just one
else
{
oNPC = GetAssociate(nType, oPC);
if(GetIsObjectValid(oNPC))
{
SendMessageToPC(oPC, "Moving your associate: " + GetName(oNPC));
AssignCommand(oNPC, ClearAllActions());
AssignCommand(oNPC, JumpToLocation(lTarget));
}
}
}
}
void main()
{
object oidUser;
object oidDest;
string sDest;
if(!GetLocked(OBJECT_SELF))
{
if(GetIsOpen(OBJECT_SELF))
{
sDest = GetLocalString(OBJECT_SELF,"Destination");
oidUser = GetLastUsedBy();
oidDest = GetObjectByTag("DST_TagofWaypoint");
SendMessageToPC(oidUser, "Moving you: " + GetName(oidUser) + " to destination " + GetName(oidDest));
SignalEvent(oidDest, EventUserDefined(101)); // reveal the secret door on the other side
AssignCommand(oidDest, ActionOpenDoor(oidDest));
AssignCommand(oidUser,ActionJumpToObject(oidDest,FALSE));
MoveFollowers(oidUser, GetLocation(oidDest));
}
else
{
PlayAnimation(ANIMATION_PLACEABLE_OPEN);
}
}
}
So basically, what helps me to remember this method is thinking “Trigger spawns door, door jumps player”.
And I think that’s about it! Hopefully this clears up any confusion anyone is having with secret doors, cause I know it was a doozy for me. Anyway, good luck. And happy modding!
-Aura