Well, this looked like it would be a rather interesting problem, so I slapped together a quick map for the problem:
Mediafire download
If you just want the script:
/* OverView:
We have 2 cranks. These are used to crank the door open. The door is dynamically attached to the remaining crank
after the first one has undergone a full revolution. This is handled by crankStateChanged().
These cranks, however, state off de-activated until the player puts the cranks in.
*/
void OnStart() {
//Intitate the crank enabling (using) part:
//If you had a lot of cranks, you could easily set this up as a for loop.
SetEntityActive("crank_base_1",false);
SetEntityActive("crank_base_2",false);
AddUseItemCallback("CBcrank", "crank_wood_1", "base_1", "attachCrankToBase", false);
AddUseItemCallback("CBcrank", "crank_wood_2", "base_1", "attachCrankToBase", false);
AddUseItemCallback("CBcrank", "crank_wood_1", "base_2", "attachCrankToBase", false);
AddUseItemCallback("CBcrank", "crank_wood_2", "base_2", "attachCrankToBase", false);
//Intiate the crank spinning part:
//Say we have two cranks in total.
SetLocalVarInt("CrankCount",2);
//Say how many cranks are already in their finished state. This is currently 0.
SetLocalVarInt("CranksDone",0);
}
void OnEnter() {}
void OnLeave() {}
/////////////////////////////////////////////////////////////
//CONSTANTS //
/////////////////////////////////////////////////////////////
const string _crankSignature = "crank_base_"; //Constant so you can change the naming of your cranks.
const string _doorName = "vertical_door_1"; //Place the name of your door here
/////////////////////////////////////////////////////////////
//Called when one of the item cranks is used on a mount //
/////////////////////////////////////////////////////////////
void attachCrankToBase(string &in asItem, string &in asEntity)
{
if(GetLocalVarInt("ActivatedCrank"+asEntity) == 1)
{ //Person tried to use crank on crank!
//Tell them they can't do this (May want to make custom message)?
SetMessage("Inventory","UseItemDoesNotWork",0);
}
else
{ //As the names of the base are substrings of the crank's name, this part is really trivial.
//Base names are done_1 and done_2. Crank names are crank_done_1 and crank_done_2.
SetEntityActive("crank_"+asEntity,true);
SetWheelStuckState("crank_"+asEntity,0,false); //This fixes random spinning when activate is called after attach.
//Prevent more than one attach to this attach point by flagging this attach as done.
SetLocalVarInt("ActivatedCrank"+asEntity,1);
//Remove the item from the inventory
RemoveItem(asItem);
}
}
/////////////////////////////////////////////////////////////
//Called when one of the activated cranks is used and //
//changes from one state to another (min -1 , max 1) //
//this routine is called by BOTH CRANKS! //
/////////////////////////////////////////////////////////////
void crankStateChanged(string &in entity, int state) {
AddDebugMessage("StateChanged for crank "+ entity + " to " + state,false);
//Stores the entities state for future reference
SetLocalVarInt("state_"+entity,state);
//If the crank is uncranked, decrease cranksDone count, else increase it...
//State is either +1 or -1. We make use of this to increase or decrease.
AddLocalVarInt("CranksDone",state);
//If we have only one crank left, then that crank needs to be attached to the door.
int crankCount = GetLocalVarInt("CrankCount");
if(GetLocalVarInt("CranksDone") == crankCount-1)
{ //Find the crank that isn't attached yet so we can attach it.
for(int i=1; i<=crankCount; i++)
{
if(GetLocalVarInt("state_"+_crankSignature+i) != 1)
{ //Found it? Attach it! Don't need to loop further now.
InteractConnectPropWithMoveObject("MoveDoor",_crankSignature+i,_doorName,true,false,1);
i=crankCount;
}
}
}
//If this crank is not the last crank, and it was moved to it's maximum.
//We can safely lock this crank in place, then forget about it.
if( (crankCount > GetLocalVarInt("CranksDone")) && (state == 1) ) SetWheelStuckState(entity,1,true);
}
An overview of the solution is as follows:
Entites:
- base_1, base_2 - These are the "mounts" for the cranks
- crank_base_1, crank_base_2 - the cranks you actually spin at the respective bases. Initially de-activated.
- crank_wood_1, crank_wood_2 - the cranks you pick up
- vertical_door_1 - the door that moves up/down with the cranks
Callbacks:
- attachCrankToBase - Called when a crank_wood is used on a base
- crankStateChanged - when a crank_base is turned
Intially the cank_base objects are de-activated, and item callbacks added for the crank_wood objects with each base. When a wood object is attached to a base, the crank_base at that base is activated - which can then be spun. When all the crank_bases are spun the door will lift (the door is attached to the last crank_base).
The callback routines are as loosely coupled as i could make them, so if you have different objects and different names you should just be able to change the constants and the onStart() routine and it will work. It will also work for any number of cranks.