Four lever door puzzle
From NWNWiki
Contents |
[edit] Four lever door puzzle
[edit] What it does
The PC may only open a door by activating 4 levers in correct sequence. If they get the sequence wrong then they receive a small punishment in the form of a lightning bolt (or effect of your choice) from each of the levers. Damage is applied dependant on the players level. For any lever in the sequence the player may activate or deactivate it safely.
[edit] Notes
In this example each of the scripts should be placed in the OnUsed slot of the levers. The lever tags should all be the same differentiated by a final integer - lever_01, lever_02 etc. Compile the INCLUDE file first, and I've found that if you change the INCLUDE file then you need to re-compile all of it's calling scripts for the change to take effect. The scripts for the levers are all basically the same, just the LocalInt on the PC changing for the position in the sequence. Thus the scripts are scalable for any number of levers.
[edit] The Script, part 1
#INCLUDE script
///////////////////////////
// reset_chst_lever
///////////////////////////
void ResetChestLevers(object oPC)
{
string sLeverTag = "ChestLever_0";
string sLTag;
object oChest, oLever;
int i;
int iLevel = 0;
oChest = GetObjectByTag("KeyChest"); // chest or door to open
// Calculate oPC's total level
for(i=1; i<4; i++)
{
iLevel += GetLevelByPosition(i, oPC);
}
// Set the level of Damage dependent on oPC's total level
effect oOuch = EffectDamage(2 * iLevel);
// loop to set all levers to off and fire a beam at oPC - Also resets the levers on/off LocalInt
for(i=1; i < 5; i++)
{
sLTag = sLeverTag + IntToString(i);
oLever = GetObjectByTag(sLTag);
AssignCommand(oLever, ActionPlayAnimation( ANIMATION_PLACEABLE_DEACTIVATE ));
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectBeam(VFX_BEAM_LIGHTNING, oLever, BODY_NODE_CHEST), oPC, 2.0);
SetLocalInt(oLever, "Tripped", 0);
}
// set oPC LocalInt - so they have to restart - Apply dammage for getting it wrong
SetLocalInt(oPC, "ChestLever", 0);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, oOuch, oPC);
// Area LocalInt to indicate state of chest/door
SetLocalInt(GetArea(oPC), "ChestOpen", 0);
// Finally - close the chest/door if its open
if(GetIsOpen(oChest))
{
AssignCommand(oChest, ActionPlayAnimation(ANIMATION_PLACEABLE_CLOSE));
SetLocked(oChest, TRUE);
}
}
[edit] The Script, Part 2
[edit] Lever 1
///////////////////////////
// use_chestlever1
///////////////////////////
#include "reset_chst_lever"
void main()
{
object oPC = GetLastUsedBy();
if (GetLocalInt(OBJECT_SELF,"Tripped") != 1)
{
AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 1.0, 1.0));
AssignCommand(OBJECT_SELF, ActionPlayAnimation(ANIMATION_PLACEABLE_ACTIVATE));
if (GetLocalInt(oPC, "ChestLever") > 0)
{
ResetChestLevers(oPC);
return;
}
SetLocalInt(OBJECT_SELF, "Tripped", 1);
SetLocalInt(oPC, "ChestLever", 1);
}
else
{
AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 1.0, 1.0));
AssignCommand(OBJECT_SELF, ActionPlayAnimation( ANIMATION_PLACEABLE_DEACTIVATE ));
if (GetLocalInt(oPC, "ChestLever") != 1)
{
ResetChestLevers(oPC);
return;
}
SetLocalInt(OBJECT_SELF, "Tripped", 0);
SetLocalInt(oPC, "ChestLever", 0);
}
}
[edit] Lever 2
/////////////////////////////
// use_chestlever2
/////////////////////////////
#include "reset_chst_lever"
void main()
{
object oPC = GetLastUsedBy();
if (GetLocalInt(OBJECT_SELF,"Tripped") != 1)
{
AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 1.0, 1.0));
AssignCommand(OBJECT_SELF, ActionPlayAnimation(ANIMATION_PLACEABLE_ACTIVATE));
if (GetLocalInt(oPC, "ChestLever") != 1)
{
ResetChestLevers(oPC);
return;
}
SetLocalInt(OBJECT_SELF, "Tripped", 1);
SetLocalInt(oPC, "ChestLever", 2);
}
else
{
AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 1.0, 1.0));
AssignCommand(OBJECT_SELF, ActionPlayAnimation( ANIMATION_PLACEABLE_DEACTIVATE ));
if (GetLocalInt(oPC, "ChestLever") != 2)
{
ResetChestLevers(oPC);
return;
}
SetLocalInt(OBJECT_SELF, "Tripped", 0);
SetLocalInt(oPC, "ChestLever", 1);
}
}
[edit] Lever 3
/////////////////////////////
// use_chestlever3
/////////////////////////////
#include "reset_chst_lever"
void main()
{
object oPC = GetLastUsedBy();
if (GetLocalInt(OBJECT_SELF,"Tripped") != 1)
{
AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 1.0, 1.0));
AssignCommand(OBJECT_SELF, ActionPlayAnimation(ANIMATION_PLACEABLE_ACTIVATE));
if (GetLocalInt(oPC, "ChestLever") != 2)
{
ResetChestLevers(oPC);
return;
}
SetLocalInt(OBJECT_SELF, "Tripped", 1);
SetLocalInt(oPC, "ChestLever", 3);
}
else
{
AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 1.0, 1.0));
AssignCommand(OBJECT_SELF, ActionPlayAnimation( ANIMATION_PLACEABLE_DEACTIVATE ));
if (GetLocalInt(oPC, "ChestLever") != 3)
{
ResetChestLevers(oPC);
return;
}
SetLocalInt(OBJECT_SELF, "Tripped", 0);
SetLocalInt(oPC, "ChestLever", 2);
}
}
[edit] Lever 4
//////////////////////////
// use_chestlever 4
//////////////////////////
#include "reset_chst_lever"
void main()
{
object oPC = GetLastUsedBy();
object oChest = GetObjectByTag("KeyChest");
if (GetLocalInt(OBJECT_SELF,"Tripped") != 1)
{
AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 1.0, 1.0));
AssignCommand(OBJECT_SELF, ActionPlayAnimation(ANIMATION_PLACEABLE_ACTIVATE));
if (GetLocalInt(oPC, "ChestLever") != 3)
{
ResetChestLevers(oPC);
return;
}
SetLocalInt(OBJECT_SELF, "Tripped", 1);
SetLocalInt(oPC, "ChestLever", 4);
// OPEN The Chest/Door Here
SetLocked(oChest, FALSE);
AssignCommand(oChest, ActionPlayAnimation(ANIMATION_PLACEABLE_OPEN));
// Let the Area know the chest/door state
SetLocalInt(GetArea(OBJECT_SELF), "ChestOpen", 1);
}
else
{
AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 1.0, 1.0));
AssignCommand(OBJECT_SELF, ActionPlayAnimation( ANIMATION_PLACEABLE_DEACTIVATE ));
if (GetLocalInt(oPC, "ChestLever") != 4)
{
ResetChestLevers(oPC);
return;
}
SetLocalInt(OBJECT_SELF, "Tripped", 0);
SetLocalInt(oPC, "ChestLever", 3);
// Close The Chest Here
if(GetIsOpen(oChest))
{
AssignCommand(oChest, ActionPlayAnimation(ANIMATION_PLACEABLE_CLOSE));
SetLocked(oChest, TRUE);
// Let the Area know the chest/door state
SetLocalInt(GetArea(OBJECT_SELF), "ChestOpen", 0);
}
}
}
[edit] Foot Note
The chest or door should be set to locked & require key to open. All objects should be set to plot. Oh, and the levers should NOT use the default initial setting but should be set to 'Deactivated'.
Feel free to cut, hack, plagarise or ignore at will.
Enjoy,
Mighty Blob
