4 Scalable Building Simulator - Elevator Subsystem Class
5 The Skyscraper Project - Version 1.8 Alpha
6 Copyright (C)20042012 Ryan Thoryk
7 http://www.skyscrapersim.com
8 http://sourceforge.net/projects/skyscraper
9 Contact - ryan@tliquest.net
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 as published by the Free Software Foundation; either version 2
14 of the License, or (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 #include <OgreBulletCollisionsRay.h>
37 extern SBS *sbs; //external pointer to the SBS engine
39 Elevator::Elevator(int number)
42 object = new Object();
43 object->SetValues(this, sbs->object, "Elevator", "", false);
52 QueuePositionDirection = 0;
53 LastQueueDirection = 0;
54 LastQueueFloor[0] = 0;
55 LastQueueFloor[1] = 0;
61 AccelJerk = sbs->GetConfigFloat("Skyscraper.SBS.Elevator.AccelJerk", 1);
62 DecelJerk = sbs->GetConfigFloat("Skyscraper.SBS.Elevator.DecelJerk", 1);
70 CalculateStoppingDistance = false;
72 EmergencyStop = false;
80 ElevatorIsRunning = false;
85 CarStartSound = sbs->GetConfigString("Skyscraper.SBS.Elevator.CarStartSound", "");
86 CarMoveSound = sbs->GetConfigString("Skyscraper.SBS.Elevator.CarMoveSound", "");
87 CarStopSound = sbs->GetConfigString("Skyscraper.SBS.Elevator.CarStopSound", "");
88 CarIdleSound = sbs->GetConfigString("Skyscraper.SBS.Elevator.CarIdleSound", "elevidle.wav");
89 MotorStartSound = sbs->GetConfigString("Skyscraper.SBS.Elevator.MotorStartSound", "motor_start.wav");
90 MotorRunSound = sbs->GetConfigString("Skyscraper.SBS.Elevator.MotorRunSound", "motor_running.wav");
91 MotorStopSound = sbs->GetConfigString("Skyscraper.SBS.Elevator.MotorStopSound", "motor_stop.wav");
92 MotorIdleSound = sbs->GetConfigString("Skyscraper.SBS.Elevator.MotorIdleSound", "");
93 AlarmSound = sbs->GetConfigString("Skyscraper.SBS.Elevator.AlarmSound", "bell1.wav");
94 AlarmSoundStop = sbs->GetConfigString("Skyscraper.SBS.Elevator.AlarmSoundStop", "bell1-stop.wav");
95 UseFloorSkipText = false;
96 ACP = sbs->GetConfigBool("Skyscraper.SBS.Elevator.ACP", false);
97 ACPFloor = sbs->GetConfigInt("Skyscraper.SBS.Elevator.ACPFloor", 0);
98 UpPeak = sbs->GetConfigBool("Skyscraper.SBS.Elevator.UpPeak", false);
99 DownPeak = sbs->GetConfigBool("Skyscraper.SBS.Elevator.DownPeak", false);
100 IndependentService = sbs->GetConfigBool("Skyscraper.SBS.Elevator.IndependentService", false);
101 InspectionService = sbs->GetConfigBool("Skyscraper.SBS.Elevator.InspectionService", false);
102 FireServicePhase1 = sbs->GetConfigInt("Skyscraper.SBS.Elevator.FireService1", 0);
103 FireServicePhase2 = sbs->GetConfigInt("Skyscraper.SBS.Elevator.FireService2", 0);
105 RecallFloorAlternate = 0;
108 RecallAltSet = false;
110 RecallUnavailable = false;
115 lastcheckresult = false;
116 checkfirstrun = true;
117 UseFloorBeeps = false;
118 UseFloorSounds = false;
119 UseMessageSounds = false;
122 ActiveCallDirection = 0;
125 QueueResets = sbs->GetConfigBool("Skyscraper.SBS.Elevator.QueueResets", false);
131 LevelingSpeed = sbs->GetConfigFloat("Skyscraper.SBS.Elevator.LevelingSpeed", 0.2);
132 LevelingOffset = sbs->GetConfigFloat("Skyscraper.SBS.Elevator.LevelingOffset", 0.5);
133 LevelingOpen = sbs->GetConfigFloat("Skyscraper.SBS.Elevator.LevelingOpen", 0);
135 FinishedMove = false;
136 WaitForDoors = false;
138 RandomActivity = sbs->GetConfigBool("Skyscraper.SBS.Elevator.RandomActivity", false);
139 RandomProbability = sbs->GetConfigInt("Skyscraper.SBS.Elevator.RandomProbability", 10);
140 RandomFrequency = sbs->GetConfigFloat("Skyscraper.SBS.Elevator.RandomFrequency", 3);
142 RandomLobbySet = false;
151 NotifyEarly = sbs->GetConfigInt("Skyscraper.SBS.Elevator.NotifyEarly", 0);
152 Running = sbs->GetConfigBool("Skyscraper.SBS.Elevator.Run", true);
156 Music = sbs->GetConfigString("Skyscraper.SBS.Elevator.Music", "");
157 MusicOn = sbs->GetConfigBool("Skyscraper.SBS.Elevator.MusicOn", true);;
158 MusicOnMove = sbs->GetConfigBool("Skyscraper.SBS.Elevator.MusicOnMove", false);;
159 DepartureDelay = sbs->GetConfigFloat("Skyscraper.SBS.Elevator.DepartureDelay", 0.0);
160 ArrivalDelay = sbs->GetConfigFloat("Skyscraper.SBS.Elevator.ArrivalDelay", 0.0);
161 WaitForTimer = false;
162 SoundsQueued = false;
168 timer = new Timer(this, 0);
169 random_timer = new Timer(this, 1);
170 arrival_delay = new Timer(this, 2);
171 departure_delay = new Timer(this,3);
173 //create object meshes
174 buffer = Ogre::StringConverter::toString(Number);
175 buffer.insert(0, "Elevator ");
177 object->SetName(buffer.c_str());
178 ElevatorMesh = new MeshObject(object, buffer.c_str(), true);
181 Report("elevator object created");
184 Elevator::~Elevator()
187 for (int i = 0; i < (int)ModelArray.size(); i++)
190 delete ModelArray[i];
195 for (int i = 0; i < (int)lights.size(); i++)
204 Report("deleting timers");
215 random_timer->Stop();
222 arrival_delay->Stop();
223 delete arrival_delay;
229 departure_delay->Stop();
230 delete departure_delay;
234 //delete directional indicators
236 Report("deleting interior directional indicators");
238 for (int i = 0; i < (int)DirIndicatorArray.size(); i++)
240 if (DirIndicatorArray[i])
242 DirIndicatorArray[i]->object->parent_deleting = true;
243 delete DirIndicatorArray[i];
246 DirIndicatorArray.clear();
250 Report("deleting doors");
252 if (DoorArray.size() > 0)
254 for (int i = 0; i < (int)DoorArray.size(); i++)
258 DoorArray[i]->object->parent_deleting = true;
264 //delete floor indicators
266 Report("deleting floor indicators");
268 for (int i = 0; i < (int)FloorIndicatorArray.size(); i++)
270 if (FloorIndicatorArray[i])
272 FloorIndicatorArray[i]->object->parent_deleting = true;
273 delete FloorIndicatorArray[i];
276 FloorIndicatorArray.clear();
280 Report("deleting button panels");
282 for (int i = 0; i < (int)PanelArray.size(); i++)
286 PanelArray[i]->object->parent_deleting = true;
287 delete PanelArray[i];
295 Report("deleting standard doors");
297 for (int i = 0; i < (int)StdDoorArray.size(); i++)
301 StdDoorArray[i]->object->parent_deleting = true;
302 delete StdDoorArray[i];
306 StdDoorArray.clear();
310 Report("deleting objects");
313 mainsound->object->parent_deleting = true;
319 alarm->object->parent_deleting = true;
325 floorbeep->object->parent_deleting = true;
331 floorsound->object->parent_deleting = true;
337 motorsound->object->parent_deleting = true;
343 idlesound->object->parent_deleting = true;
349 messagesnd->object->parent_deleting = true;
355 musicsound->object->parent_deleting = true;
362 Report("deleting sounds");
364 for (int i = 0; i < (int)sounds.size(); i++)
368 sounds[i]->object->parent_deleting = true;
375 //delete wall objects
376 for (int i = 0; i < (int)elevator_walls.size(); i++)
378 if (elevator_walls[i])
380 elevator_walls[i]->parent_deleting = true;
381 delete elevator_walls[i];
383 elevator_walls[i] = 0;
390 //unregister from parent
391 if (sbs->FastDelete == false)
393 if (object->parent_deleting == false)
394 sbs->RemoveElevator(this);
399 Object* Elevator::CreateElevator(bool relative, float x, float z, int floor)
401 //Creates elevator at specified location and floor
402 //x and z are the center coordinates
403 //if relative is true, then x and z coordinates are relative
404 //to the assigned shaft's center
408 ReportError("Has already been created");
412 //make sure required values are set
413 if (ElevatorSpeed <= 0)
415 ReportError("Speed not set or invalid");
418 if (Acceleration <= 0)
420 ReportError("Acceleration not set or invalid");
423 if (Deceleration <= 0)
425 ReportError("Deceleration not set or invalid");
430 ReportError("Number of doors invalid");
435 ReportError("Invalid value for AccelJerk");
440 ReportError("Invalid value for DecelJerk");
443 if (AssignedShaft <= 0)
445 ReportError("Not assigned to a shaft");
448 if (!sbs->GetShaft(AssignedShaft))
450 std::string num = Ogre::StringConverter::toString(AssignedShaft);
451 ReportError(std::string("Shaft " + num + " doesn't exist").c_str());
454 if (floor < sbs->GetShaft(AssignedShaft)->startfloor || floor > sbs->GetShaft(AssignedShaft)->endfloor)
456 std::string num = Ogre::StringConverter::toString(floor);
457 ReportError(std::string("Invalid starting floor " + num).c_str());
461 //add elevator's starting floor to serviced floor list - this also ensures that the list is populated to prevent errors
462 if (IsServicedFloor(floor) == false)
463 AddServicedFloor(floor);
466 Origin.y = sbs->GetFloor(floor)->GetBase();
467 if (relative == false)
474 Origin.x = sbs->GetShaft(AssignedShaft)->origin.x + x;
475 Origin.z = sbs->GetShaft(AssignedShaft)->origin.z + z;
479 //add elevator to associated shaft's list
480 sbs->GetShaft(AssignedShaft)->AddElevator(Number);
482 //set recall/ACP floors if not already set
483 if (RecallSet == false)
484 SetRecallFloor(GetBottomFloor());
485 if (RecallAltSet == false)
486 SetAlternateRecallFloor(GetTopFloor());
487 if (ACPFloorSet == false)
488 SetACPFloor(GetBottomFloor());
490 //create door objects
492 Report("creating doors");
495 DoorArray.resize(NumDoors);
496 for (int i = 0; i < NumDoors; i++)
497 DoorArray[i] = new ElevatorDoor(i, this);
500 //move objects to positions
502 Report("moving elevator to origin position");
503 ElevatorMesh->Move(Origin, false, false, false);
505 //create sound objects
507 Report("creating sound objects");
508 mainsound = new Sound(this->object, "Main", true);
509 mainsound->SetPosition(Origin);
510 idlesound = new Sound(this->object, "Idle", true);
511 idlesound->SetPosition(Origin);
512 idlesound->Load(CarIdleSound.c_str());
513 motorsound = new Sound(this->object, "Motor", true);
514 motorsound->SetPosition(Origin);
515 //move motor to top of shaft if location not specified, or to location
516 if (MotorPosition != Ogre::Vector3(0, 0, 0))
517 motorsound->SetPosition(Ogre::Vector3(MotorPosition.x + Origin.x, MotorPosition.y, MotorPosition.z + Origin.z));
519 motorsound->SetPositionY(sbs->GetFloor(sbs->GetShaft(AssignedShaft)->endfloor)->GetBase());
520 MotorPosition = Ogre::Vector3(motorsound->GetPosition().x - Origin.x, motorsound->GetPosition().y, motorsound->GetPosition().z - Origin.z);
521 alarm = new Sound(this->object, "Alarm", true);
522 alarm->SetPosition(Origin);
523 floorbeep = new Sound(this->object, "Floor Beep", true);
524 floorbeep->SetPosition(Origin);
525 floorsound = new Sound(this->object, "Floor Sound", true);
526 floorsound->SetPosition(Origin);
527 messagesnd = new Sound(this->object, "Message Sound", true);
528 messagesnd->SetPosition(Origin);
529 musicsound = new Sound(this->object, "Music Sound", true);
530 musicsound->SetPosition(Origin + MusicPosition);
531 musicsound->Load(Music.c_str());
533 //set elevator's floor
534 ElevatorFloor = floor;
537 //AddLight("light", 0, Ogre::Vector3(0, 6, 0), Ogre::Vector3(0, 0, 0), 1, 1, 1, 1, 1, 1, 0, 0, 0, 1000, 1, 1, 1);
541 Report("created at " + std::string(sbs->TruncateNumber(x, 4)) + ", " + std::string(sbs->TruncateNumber(x, 4)) + ", " + std::string(_itoa(floor, buffer, 12)));
545 void Elevator::AddRoute(int floor, int direction, bool change_light)
547 //Add call route to elevator routing table, in sorted order
548 //directions are either 1 for up, or -1 for down
549 //SBS_PROFILE("Elevator::AddRoute");
551 if (Running == false)
553 Report("Elevator not running");
557 //if doors are open or moving in independent service mode, quit
558 if (IndependentService == true && (AreDoorsOpen() == false || CheckOpenDoor() == true))
560 Report("floor button must be pressed before closing doors while in independent service");
564 //do not add routes if in inspection service or fire phase 1 modes
565 if (InspectionService == true)
567 Report("cannot add route while in inspection service mode");
570 if (FireServicePhase2 == 2)
572 Report("cannot add route while in held state");
579 for (int i = 0; i < (int)UpQueue.size(); i++)
581 if (UpQueue[i] == floor)
587 //exit if entry already exits
588 Report("route to floor " + std::string(_itoa(floor, intbuffer, 10)) + " (" + sbs->GetFloor(floor)->ID + ") already exists");
592 UpQueue.push_back(floor);
593 std::sort(UpQueue.begin(), UpQueue.end());
595 LastQueueFloor[0] = floor;
596 LastQueueFloor[1] = 1;
597 Report("adding route to floor " + std::string(_itoa(floor, intbuffer, 10)) + " (" + sbs->GetFloor(floor)->ID + ") direction up");
602 for (int i = 0; i < (int)DownQueue.size(); i++)
604 if (DownQueue[i] == floor)
610 //exit if entry already exits
611 Report("route to floor " + std::string(_itoa(floor, intbuffer, 10)) + " (" + sbs->GetFloor(floor)->ID + ") already exists");
615 DownQueue.push_back(floor);
616 std::sort(DownQueue.begin(), DownQueue.end());
618 LastQueueFloor[0] = floor;
619 LastQueueFloor[1] = -1;
620 Report("adding route to floor " + std::string(_itoa(floor, intbuffer, 10)) + " (" + sbs->GetFloor(floor)->ID + ") direction down");
623 //turn on button lights
624 if (change_light == true)
627 Report("AddRoute: turning on button lights for floor " + std::string(_itoa(floor, intbuffer, 10)));
628 for (int i = 0; i < (int)PanelArray.size(); i++)
629 PanelArray[i]->ChangeLight(floor, true);
632 //add ACP route recursively if mode is enabled
633 if (ACP == true && floor != ACPFloor)
635 //only add ACP route if original route will pass ACP floor
636 if ((GetFloor() < ACPFloor && floor > ACPFloor) || (GetFloor() > ACPFloor && floor < ACPFloor))
639 Report("Adding ACP route");
640 AddRoute(ACPFloor, direction, false);
645 void Elevator::DeleteRoute(int floor, int direction)
647 //Delete call route from elevator routing table
648 //directions are either 1 for up, or -1 for down
649 //SBS_PROFILE("Elevator::DeleteRoute");
651 if (Running == false)
653 Report("Elevator not running");
659 //delete floor entry from up queue
660 for (int i = 0; i < (int)UpQueue.size(); i++)
662 if (UpQueue[i] == floor)
663 UpQueue.erase(UpQueue.begin() + i);
665 Report("deleting route to floor " + std::string(_itoa(floor, intbuffer, 10)) + " (" + sbs->GetFloor(floor)->ID + ") direction up");
669 //delete floor entry from down queue
670 for (int i = 0; i < (int)DownQueue.size(); i++)
672 if (DownQueue[i] == floor)
673 DownQueue.erase(DownQueue.begin() + i);
675 Report("deleting route to floor " + std::string(_itoa(floor, intbuffer, 10)) + " (" + sbs->GetFloor(floor)->ID + ") direction down");
678 //turn off button lights
680 Report("DeleteRoute: turning off button lights for floor " + std::string(_itoa(floor, intbuffer, 10)));
681 for (int i = 0; i < (int)PanelArray.size(); i++)
682 PanelArray[i]->ChangeLight(floor, false);
685 void Elevator::CancelLastRoute()
687 //cancels the last added route
689 //LastQueueFloor holds the floor and direction of the last route; array element 0 is the floor and 1 is the direction
691 if (Running == false)
693 Report("Elevator not running");
697 if (LastQueueFloor[1] == 0)
700 Report("CancelLastRoute: route not valid");
704 Report("canceling last route");
705 DeleteRoute(LastQueueFloor[0], LastQueueFloor[1]);
706 LastQueueFloor[0] = 0;
707 LastQueueFloor[1] = 0;
710 void Elevator::Alarm()
712 //elevator alarm code
714 if (AlarmActive == false)
719 if (AlarmSound != "")
721 alarm->Load(AlarmSound.c_str());
726 if (AlarmActive == true && sbs->camera->MouseDown == false)
730 if (AlarmSound != "")
733 alarm->Load(AlarmSoundStop.c_str());
741 void Elevator::Stop(bool emergency)
743 //Tells elevator to stop moving, no matter where it is
745 //exit if in inspection mode
746 if (InspectionService == true && emergency == true)
749 Report("cannot stop while in inspection service");
753 if (IsMoving == false)
756 Report("Stop: not moving");
760 EmergencyStop = true;
762 if (emergency == true)
764 Report("emergency stop");
766 //clear elevator queues
767 ResetQueue(true, true);
770 Report("Stopping elevator");
773 void Elevator::OpenHatch()
775 //Opens the elevator's upper escape hatch, allowing access to the shaft
777 Report("opening hatch");
780 void Elevator::ProcessCallQueue()
782 //Processes the elevator's call queue, and sends elevators to called floors
783 SBS_PROFILE("Elevator::ProcessCallQueue");
785 //exit if elevator is not running
786 if (Running == false)
789 //exit if in inspection service mode
790 if (InspectionService == true)
794 if (EmergencyStop == true)
797 //if both queues are empty
798 if (UpQueue.size() == 0 && DownQueue.size() == 0)
800 int TopFloor = GetTopFloor();
801 int BottomFloor = GetBottomFloor();
803 if (DownPeak == true || UpPeak == true)
805 //if DownPeak mode is active, send elevator to the top serviced floor if not already there
806 if (GetFloor() != TopFloor && DownPeak == true && IsMoving == false)
809 Report("ProcessCallQueue: sending elevator to top floor for DownPeak mode");
810 AddRoute(TopFloor, 1, false);
813 //if UpPeak mode is active, send elevator to the bottom serviced floor if not already there
814 else if (GetFloor() != BottomFloor && UpPeak == true && IsMoving == false)
817 Report("ProcessCallQueue: sending elevator to bottom floor for UpPeak mode");
818 AddRoute(BottomFloor, -1, false);
823 if (IsIdle() == true && QueuePositionDirection != 0)
825 //set search direction to 0 if idle
827 Report("ProcessCallQueue: resetting search direction due to idle");
828 LastQueueDirection = QueuePositionDirection;
829 QueuePositionDirection = 0;
833 else if (QueuePositionDirection == 0)
835 LastQueueDirection = 0;
837 if (UpQueue.size() != 0)
840 Report("ProcessCallQueue: setting search direction to up");
841 QueuePositionDirection = 1;
843 if (DownQueue.size() != 0)
846 Report("ProcessCallQueue: setting search direction to down");
847 QueuePositionDirection = -1;
851 //set search direction to 0 if any related queue is empty, and if doors are not open or moving
852 if (AreDoorsOpen() == false && CheckOpenDoor() == false)
854 if (QueuePositionDirection == 1 && UpQueue.size() == 0)
857 Report("ProcessCallQueue: resetting search direction due to empty up queue");
858 QueuePositionDirection = 0;
859 LastQueueDirection = 1;
861 if (QueuePositionDirection == -1 && DownQueue.size() == 0)
864 Report("ProcessCallQueue: resetting search direction due to empty down queue");
865 QueuePositionDirection = 0;
866 LastQueueDirection = -1;
869 else if (UpPeak == false && DownPeak == false)
870 return; //don't process the main queue code if doors are open or moving
872 //Search through queue lists and find next valid floor call
873 if (QueuePositionDirection == 1)
875 //search through up queue
876 for (int i = 0; i < (int)UpQueue.size(); i++)
878 //if the queued floor number is a higher floor, dispatch the elevator to that floor
879 if (UpQueue[i] >= ElevatorFloor)
881 if (MoveElevator == false)
884 Report("ProcessCallQueue up: standard dispatch, floor " + std::string(_itoa(UpQueue[i], intbuffer, 10)));
885 ActiveCallFloor = UpQueue[i];
886 ActiveCallDirection = 1;
887 GotoFloor = UpQueue[i];
888 if (FireServicePhase2 == 0 || UpPeak == true || DownPeak == true)
894 LastQueueDirection = 1;
896 else if (Leveling == false && ActiveDirection == 1)
898 //if elevator is moving and not leveling, change destination floor if not beyond decel marker of that floor
899 if (GotoFloor != UpQueue[i])
901 float tmpdestination = sbs->GetFloor(UpQueue[i])->GetBase();
902 if (BeyondDecelMarker(1, tmpdestination) == false)
904 ActiveCallFloor = UpQueue[i];
905 GotoFloor = UpQueue[i];
906 Destination = tmpdestination;
907 Report("changing destination floor to " + std::string(_itoa(GotoFloor, intbuffer, 10)) + " (" + sbs->GetFloor(GotoFloor)->ID + ")");
909 else if (sbs->Verbose)
910 Report("ProcessCallQueue up: cannot change destination floor to " + std::string(_itoa(UpQueue[i], intbuffer, 10)));
915 //if the queued floor number is a lower floor
916 if (UpQueue[i] < ElevatorFloor && MoveElevator == false)
918 //dispatch elevator if it's idle
919 if (IsIdle() == true && LastQueueDirection == 0)
922 Report("ProcessCallQueue up: dispatching idle lower elevator, floor " + std::string(_itoa(UpQueue[i], intbuffer, 10)));
923 ActiveCallFloor = UpQueue[i];
924 ActiveCallDirection = 1;
925 GotoFloor = UpQueue[i];
926 if (FireServicePhase2 == 0 || UpPeak == true || DownPeak == true)
932 LastQueueDirection = 1;
935 //reset search direction or queue if it's the last entry
936 if (i == UpQueue.size() - 1)
938 if (QueueResets == true)
941 Report("ProcessCallQueue up: last entry (" + std::string(_itoa(UpQueue[i], intbuffer, 10)) + ") is lower; resetting queue");
942 ResetQueue(true, false);
945 else if (IsIdle() == true && QueuePositionDirection != 0)
947 //set search direction to 0 if idle
949 Report("ProcessCallQueue up: resetting search direction since last entry is lower");
950 LastQueueDirection = QueuePositionDirection;
951 QueuePositionDirection = 0;
955 //otherwise skip it if it's not the last entry
957 Report("ProcessCallQueue up: skipping floor entry " + std::string(_itoa(UpQueue[i], intbuffer, 10)));
961 else if (QueuePositionDirection == -1)
963 //search through down queue (search order is reversed since calls need to be processed in decending order)
964 for (int i = (int)DownQueue.size() - 1; i >= 0; i--)
966 //if the queued floor number is a lower floor, dispatch the elevator to that floor
967 if (DownQueue[i] <= ElevatorFloor)
969 if (MoveElevator == false)
972 Report("ProcessCallQueue down: standard dispatch, floor " + std::string(_itoa(DownQueue[i], intbuffer, 10)));
973 ActiveCallFloor = DownQueue[i];
974 ActiveCallDirection = -1;
975 GotoFloor = DownQueue[i];
976 if (FireServicePhase2 == 0 || UpPeak == true || DownPeak == true)
982 LastQueueDirection = -1;
984 else if (Leveling == false && ActiveDirection == -1)
986 //if elevator is moving and not leveling, change destination floor if not beyond decel marker of that floor
987 if (GotoFloor != DownQueue[i])
989 float tmpdestination = sbs->GetFloor(DownQueue[i])->GetBase();
990 if (BeyondDecelMarker(-1, tmpdestination) == false)
992 ActiveCallFloor = DownQueue[i];
993 GotoFloor = DownQueue[i];
994 Destination = tmpdestination;
995 Report("changing destination floor to " + std::string(_itoa(GotoFloor, intbuffer, 10)) + " (" + sbs->GetFloor(GotoFloor)->ID + ")");
997 else if (sbs->Verbose)
998 Report("ProcessCallQueue down: cannot change destination floor to " + std::string(_itoa(DownQueue[i], intbuffer, 10)));
1003 //if the queued floor number is an upper floor
1004 if (DownQueue[i] > ElevatorFloor && MoveElevator == false)
1006 //dispatch elevator if idle
1007 if (IsIdle() == true && LastQueueDirection == 0)
1010 Report("ProcessCallQueue down: dispatching idle higher elevator, floor " + std::string(_itoa(DownQueue[i], intbuffer, 10)));
1011 ActiveCallFloor = DownQueue[i];
1012 ActiveCallDirection = -1;
1013 GotoFloor = DownQueue[i];
1014 if (FireServicePhase2 == 0 || UpPeak == true || DownPeak == true)
1017 WaitForDoors = true;
1019 MoveElevator = true;
1020 LastQueueDirection = -1;
1023 //reset search direction or queue if it's the first entry
1026 if (QueueResets == true)
1029 Report("ProcessCallQueue down: last entry (" + std::string(_itoa(DownQueue[i], intbuffer, 10)) + ") is higher; resetting queue");
1030 ResetQueue(false, true);
1033 else if (IsIdle() == true && QueuePositionDirection != 0)
1035 //set search direction to 0 if idle
1037 Report("ProcessCallQueue down: resetting search direction since last entry is higher");
1038 LastQueueDirection = QueuePositionDirection;
1039 QueuePositionDirection = 0;
1043 //otherwise skip it if it's not the last entry
1045 Report("ProcessCallQueue down: skipping floor entry " + std::string(_itoa(DownQueue[i], intbuffer, 10)));
1051 int Elevator::GetFloor()
1053 //Determine floor that the elevator is on
1054 //SBS_PROFILE("Elevator::GetFloor");
1058 if (lastfloorset == true)
1059 newlastfloor = sbs->GetFloorNumber(GetPosition().y, lastfloor, true);
1061 newlastfloor = sbs->GetFloorNumber(GetPosition().y);
1063 lastfloor = newlastfloor;
1064 lastfloorset = true;
1068 void Elevator::MonitorLoop()
1070 //Monitors elevator and starts actions if needed
1071 SBS_PROFILE("Elevator::MonitorLoop");
1073 //make sure height value is set
1074 if (HeightSet == false)
1077 //search through mesh geometry to find actual height
1078 for (int i = 0; i < (int)ElevatorMesh->MeshGeometry.size(); i++)
1081 if (sbs->ToLocal(ElevatorMesh->MeshGeometry[i].vertex.y) > Height)
1082 Height = sbs->ToLocal(ElevatorMesh->MeshGeometry[i].vertex.y);
1087 //set random lobby level if not set
1088 if (RandomLobbySet == false)
1089 SetRandomLobby(GetBottomFloor());
1091 //perform first-run tasks
1092 if (FirstRun == true && Running == true)
1101 if (DownPeak == true)
1104 EnableDownPeak(true);
1106 if (IndependentService == true)
1108 IndependentService = false;
1109 EnableIndependentService(true);
1111 if (InspectionService == true)
1113 InspectionService = false;
1114 EnableInspectionService(true);
1116 if (FireServicePhase1 > 0)
1118 int value = FireServicePhase1;
1119 FireServicePhase1 = 0;
1120 EnableFireService1(value);
1122 if (FireServicePhase2 > 0)
1124 int value = FireServicePhase2;
1125 FireServicePhase2 = 0;
1126 EnableFireService2(value);
1139 UpdateFloorIndicators();
1142 //play idle sound if in elevator, or if doors open
1143 if (CarIdleSound != "")
1145 if (idlesound->IsPlaying() == false && Fan == true)
1147 if ((sbs->InElevator == true && sbs->ElevatorNumber == Number) || AreDoorsOpen() == true || CheckOpenDoor() == true)
1150 Report("playing idle sound");
1151 idlesound->Loop(true);
1157 if (Fan == false && idlesound->IsPlaying() == true)
1160 Report("stopping idle sound");
1163 else if ((sbs->InElevator == false || sbs->ElevatorNumber != Number) && AreDoorsOpen() == false && CheckOpenDoor() == false)
1166 Report("stopping idle sound");
1172 //play music sound if in elevator, or if doors open
1175 if (musicsound->IsPlaying() == false && MusicOn == true && ((MusicOnMove == true && IsMoving == true) || MusicOnMove == false))
1177 if (InServiceMode() == false)
1179 if ((sbs->InElevator == true && sbs->ElevatorNumber == Number) || AreDoorsOpen() == true || CheckOpenDoor() == true)
1182 Report("playing music");
1184 if (MusicPosition == Ogre::Vector3(0, 0, 0) && Height > 0)
1185 MusicPosition = Ogre::Vector3(0, Height, 0); //set default music position to elevator height
1187 musicsound->SetPosition(GetPosition() + MusicPosition);
1188 musicsound->Loop(true);
1189 musicsound->Play(false);
1195 if ((MusicOn == false || InServiceMode() == true || (MusicOnMove == true && IsMoving == false)) && musicsound->IsPlaying() == true)
1198 Report("stopping music");
1199 musicsound->Pause();
1201 else if ((sbs->InElevator == false || sbs->ElevatorNumber != Number) && AreDoorsOpen() == false && CheckOpenDoor() == false)
1204 Report("stopping music");
1205 musicsound->Pause();
1211 if (AlarmActive == true)
1214 //call queue processor
1218 for (int i = 1; i <= NumDoors; i++)
1220 ElevatorDoor *door = GetDoor(i);
1224 //reset door timer if peak mode is enabled and a movement is pending
1225 if ((UpPeak == true || DownPeak == true))
1227 if ((UpQueue.size() != 0 || DownQueue.size() != 0) && (AreDoorsOpen() == true && CheckOpenDoor() == false))
1231 if (door->TimerIsRunning() == false)
1232 door->ResetDoorTimer();
1238 //enable auto-park timer if specified
1239 if (ParkingDelay > 0 && Running == true && IsIdle() == true)
1241 if (timer->IsRunning() == false)
1242 timer->Start(ParkingDelay * 1000, true);
1245 //enable random call timer
1246 if (random_timer->IsRunning() == false && RandomActivity == true && Running == true)
1247 random_timer->Start(RandomFrequency * 1000, false);
1250 if (MoveElevator == true)
1251 MoveElevatorToFloor();
1255 void Elevator::MoveElevatorToFloor()
1257 //Main processing routine; sends elevator to floor specified in GotoFloor
1258 //if InspectionService is enabled, this function ignores GotoFloor values, since the elevator is manually moved
1259 SBS_PROFILE("Elevator::MoveElevatorToFloor");
1261 Ogre::Vector3 movement = Ogre::Vector3(0, 0, 0);
1263 //wait until doors are fully closed if WaitForDoors is true
1264 if (WaitForDoors == true)
1266 if (AreDoorsOpen() == true || CheckOpenDoor() == true)
1269 WaitForDoors = false;
1272 //exit if waiting for arrival or departure timers
1273 if (WaitForTimer == true)
1276 if (ElevatorIsRunning == false)
1278 if (Running == false)
1280 Report("Elevator not running");
1285 Report("starting elevator movement procedure");
1287 ElevatorIsRunning = true;
1288 FinishedMove = false;
1289 std::string dir_string;
1293 //get elevator's current altitude
1294 elevposition = GetPosition();
1295 ElevatorStart = elevposition.y;
1297 //get elevator's current floor
1298 ElevatorFloor = GetFloor();
1299 oldfloor = ElevatorFloor;
1301 //Determine direction
1302 if (InspectionService == false)
1304 if (GotoFloor < ElevatorFloor)
1307 dir_string = "down";
1309 if (GotoFloor > ElevatorFloor)
1317 if (Direction == -1)
1318 dir_string = "down";
1319 else if (Direction == 1)
1323 ActiveDirection = Direction;
1325 //If elevator is already on specified floor, open doors and exit
1326 if (ElevatorFloor == GotoFloor && InspectionService == false)
1328 sbs->Report("Elevator already on specified floor");
1329 DeleteActiveRoute();
1330 goto finish; //skip main processing and run cleanup section
1333 //if destination floor is not a serviced floor, reset and exit
1334 if (IsServicedFloor(GotoFloor) == false && InspectionService == false)
1336 sbs->Report("Destination floor not in ServicedFloors list");
1337 MoveElevator = false;
1338 ElevatorIsRunning = false;
1339 DeleteActiveRoute();
1343 //Determine distance to destination floor
1344 if (InspectionService == false)
1346 Destination = sbs->GetFloor(GotoFloor)->GetBase();
1347 DistanceToTravel = fabs(fabs(Destination) - fabs(ElevatorStart));
1351 //otherwise if inspection service is on, choose the altitude of the top/bottom floor
1354 Destination = sbs->GetFloor(GetTopFloor())->GetBase();
1355 if (ElevatorStart >= Destination)
1357 //don't go above top floor
1358 Report("cannot go above top floor");
1361 MoveElevator = false;
1362 ElevatorIsRunning = false;
1363 DeleteActiveRoute();
1369 Destination = sbs->GetFloor(GetBottomFloor())->GetBase();
1370 if (ElevatorStart <= Destination)
1372 //don't go below bottom floor
1373 Report("cannot go below bottom floor");
1376 MoveElevator = false;
1377 ElevatorIsRunning = false;
1378 DeleteActiveRoute();
1382 DistanceToTravel = fabs(fabs(Destination) - fabs(ElevatorStart));
1384 CalculateStoppingDistance = true;
1386 //If user is riding this elevator, then turn off objects
1387 if (sbs->ElevatorSync == true && sbs->ElevatorNumber == Number && InspectionService == false)
1390 Report("user in elevator - turning off objects");
1393 if (sbs->GetShaft(AssignedShaft)->ShowFloors == false)
1395 sbs->GetFloor(sbs->camera->CurrentFloor)->Enabled(false);
1396 sbs->GetFloor(sbs->camera->CurrentFloor)->EnableGroup(false);
1401 for (int i = 0; i < (int)sbs->GetShaft(AssignedShaft)->ShowFloorsList.size(); i++)
1403 if (sbs->GetShaft(AssignedShaft)->ShowFloorsList[i] == sbs->camera->CurrentFloor)
1409 sbs->GetFloor(sbs->camera->CurrentFloor)->Enabled(false);
1410 sbs->GetFloor(sbs->camera->CurrentFloor)->EnableGroup(false);
1414 //Turn off sky, buildings, and landscape
1415 if (sbs->GetShaft(AssignedShaft)->ShowOutside == false)
1417 sbs->EnableSkybox(false);
1418 sbs->EnableBuildings(false);
1419 sbs->EnableLandscape(false);
1420 sbs->EnableExternal(false);
1425 for (int i = 0; i < (int)sbs->GetShaft(AssignedShaft)->ShowOutsideList.size(); i++)
1427 if (sbs->GetShaft(AssignedShaft)->ShowOutsideList[i] == sbs->camera->CurrentFloor)
1432 sbs->EnableSkybox(false);
1433 sbs->EnableBuildings(false);
1434 sbs->EnableLandscape(false);
1435 sbs->EnableExternal(false);
1440 //set interior directional indicators
1441 UpdateDirectionalIndicators();
1443 //set external active-direction indicators
1444 sbs->GetFloor(sbs->camera->CurrentFloor)->UpdateDirectionalIndicators(Number);
1446 //notify about movement
1447 if (InspectionService == false)
1448 Report("moving " + dir_string + " to floor " + std::string(_itoa(GotoFloor, intbuffer, 10)) + " (" + sbs->GetFloor(GotoFloor)->ID + ")");
1450 Report("moving " + dir_string);
1453 SoundsQueued = true;
1455 //start departure timer
1456 if (DepartureDelay > 0 && WaitForTimer == false)
1459 Report("started departure delay");
1460 WaitForTimer = true;
1461 departure_delay->Start(DepartureDelay * 1000, false);
1466 if (SoundsQueued == true)
1468 SoundsQueued = false;
1470 if (DepartureDelay > 0)
1473 Report("finished departure delay");
1474 departure_delay->Stop();
1477 //Play starting sounds
1479 Report("playing starting sounds");
1481 mainsound->Load(CarStartSound.c_str());
1482 mainsound->Loop(false);
1485 motorsound->Load(MotorStartSound.c_str());
1486 motorsound->Loop(false);
1490 if (EmergencyStop == true && Brakes == false)
1494 Report("handling emergency stop");
1495 CalculateStoppingDistance = false;
1496 TempDeceleration = Deceleration;
1505 //play stopping sounds
1507 Report("playing stopping sounds");
1508 mainsound->Load(CarStopSound.c_str());
1509 mainsound->Loop(false);
1510 bool adjust = sbs->GetConfigBool("Skyscraper.SBS.Elevator.AutoAdjustSound", false);
1511 //set play position to current percent of the total speed
1513 mainsound->SetPlayPosition(1 - (ElevatorRate / ElevatorSpeed));
1516 mainsound->Play(false);
1517 motorsound->Load(MotorStopSound.c_str());
1518 motorsound->Loop(false);
1520 motorsound->SetPlayPosition(1 - (ElevatorRate / ElevatorSpeed));
1522 motorsound->Reset();
1523 motorsound->Play(false);
1526 if (mainsound->IsPlaying() == false && Brakes == false && CarMoveSound.empty() == false && CarMoveSound != "")
1530 Report("playing car movement sound");
1531 mainsound->Load(CarMoveSound.c_str());
1532 mainsound->Loop(true);
1536 if (motorsound->IsPlaying() == false && Brakes == false && MotorRunSound.empty() == false && MotorRunSound != "")
1540 Report("playing motor run sound");
1541 motorsound->Load(MotorRunSound.c_str());
1542 motorsound->Loop(true);
1546 //move elevator objects and camera
1547 movement.y = ElevatorRate * sbs->delta;
1549 ElevatorMesh->Move(Ogre::Vector3(0, movement.y, 0), true, true, true);
1550 elevposition = GetPosition();
1551 if (sbs->ElevatorSync == true && sbs->ElevatorNumber == Number)
1552 sbs->camera->SetPosition(Ogre::Vector3(sbs->camera->GetPosition().x, elevposition.y + CameraOffset, sbs->camera->GetPosition().z));
1553 MoveDoors(0, movement, true, true, true);
1554 MoveLights(movement, true, true, true);
1555 MoveModels(movement, true, true, true);
1556 for (int i = 0; i < (int)FloorIndicatorArray.size(); i++)
1558 if (FloorIndicatorArray[i])
1559 FloorIndicatorArray[i]->MovePosition(movement);
1561 for (int i = 0; i < (int)PanelArray.size(); i++)
1564 PanelArray[i]->Move(movement);
1566 for (int i = 0; i < (int)DirIndicatorArray.size(); i++)
1568 if (DirIndicatorArray[i])
1569 DirIndicatorArray[i]->Move(movement);
1571 for (int i = 0; i < (int)StdDoorArray.size(); i++)
1573 if (StdDoorArray[i])
1574 StdDoorArray[i]->Move(movement, true, true, true);
1578 mainsound->SetPosition(elevposition);
1579 idlesound->SetPosition(elevposition);
1580 MoveDoorSound(0, elevposition, false, false, false);
1581 alarm->SetPosition(elevposition);
1582 floorbeep->SetPosition(elevposition);
1583 floorsound->SetPosition(elevposition);
1584 messagesnd->SetPosition(elevposition);
1585 musicsound->SetPosition(elevposition + MusicPosition);
1586 for (int i = 0; i < (int)sounds.size(); i++)
1589 sounds[i]->SetPositionY(elevposition.y + sounds[i]->PositionOffset.y);
1592 //motion calculation
1593 if (Brakes == false)
1595 //calculate jerk rate
1598 JerkRate += AccelJerk * sbs->delta;
1599 JerkPos = ElevatorRate;
1604 if (InspectionService == false)
1605 limit = ElevatorSpeed;
1607 limit = ElevatorSpeed * 0.6;
1609 if (Direction == 1 && ElevatorRate < limit)
1610 ElevatorRate += ElevatorSpeed * ((Acceleration * JerkRate) * sbs->delta);
1611 else if (Direction == -1 && ElevatorRate > -limit)
1612 ElevatorRate -= ElevatorSpeed * ((Acceleration * JerkRate) * sbs->delta);
1614 CalculateStoppingDistance = false;
1616 else if (Leveling == false)
1620 //calculate jerk rate
1621 //check if the elevator rate is less than the amount that was stored in JerkPos
1622 //(the elevator rate at the end of the JerkRate increments), adjusted to the ratio of acceljerk to deceljerk
1624 double tmppos = JerkPos * (AccelJerk / DecelJerk);
1625 if ((Direction == -1 && ElevatorRate <= tmppos) || (Direction == 1 && ElevatorRate >= tmppos))
1627 if (tmpDecelJerk == 0)
1628 tmpDecelJerk = DecelJerk * (tmppos / ElevatorRate);
1629 JerkRate -= tmpDecelJerk * sbs->delta;
1631 //prevent jerkrate from reaching 0
1639 ElevatorRate += ElevatorSpeed * ((TempDeceleration * JerkRate) * sbs->delta);
1640 if (Direction == -1)
1641 ElevatorRate -= ElevatorSpeed * ((TempDeceleration * JerkRate) * sbs->delta);
1644 //prevent the rate from going beyond 0
1645 if (Direction == 1 && Brakes == true && ElevatorRate > 0)
1647 if (Direction == -1 && Brakes == true && ElevatorRate < 0)
1650 //get distance needed to stop elevator
1651 if (CalculateStoppingDistance == true)
1654 //stopping distance is the distance the elevator has traveled (usually to reach max speed), times
1655 //the ratio of acceleration to deceleration (so if the deceleration is half of the acceleration,
1656 //it will take twice the distance to stop)
1657 StoppingDistance = (elevposition.y - ElevatorStart) * (Acceleration / Deceleration);
1658 else if (Direction == -1)
1659 StoppingDistance = (ElevatorStart - elevposition.y) * (Acceleration / Deceleration);
1662 //Deceleration routines with floor overrun correction (there's still problems, but it works pretty good)
1663 //since this function cycles at a slower/less granular rate (cycles according to frames per sec), an error factor is present where the elevator overruns the dest floor,
1664 //even though the algorithms are all correct. Since the elevator moves by "jumping" to a new altitude every frame - and usually jumps right over the altitude value where it is supposed to
1665 //start the deceleration process, causing the elevator to decelerate too late, and end up passing/overrunning the dest floor's altitude. This code corrects this problem
1666 //by determining if the next "jump" will overrun the deceleration marker (which is Dest's Altitude minus Stopping Distance), and temporarily altering the deceleration rate according to how far off the mark it is
1667 //and then starting the deceleration process immediately.
1669 //determine if next jump altitude is over deceleration marker
1670 if (Brakes == false)
1672 if (BeyondDecelMarker(Direction, Destination) == true)
1675 Report("beyond deceleration marker - slowing down");
1680 CalculateStoppingDistance = false;
1681 //recalculate deceleration value based on distance from marker, and store result in tempdeceleration
1682 //TempDeceleration = Deceleration;
1683 TempDeceleration = Deceleration * (StoppingDistance / ((Destination - LevelingOffset) - elevposition.y));
1684 //start deceleration
1687 if (InspectionService == false)
1688 ElevatorRate -= ElevatorSpeed * ((TempDeceleration * JerkRate) * sbs->delta);
1690 ElevatorRate -= (ElevatorSpeed * 0.6) * ((TempDeceleration * JerkRate) * sbs->delta);
1693 else if (Direction == -1)
1695 CalculateStoppingDistance = false;
1696 //recalculate deceleration value based on distance from marker, and store result in tempdeceleration
1697 //TempDeceleration = Deceleration;
1698 TempDeceleration = Deceleration * (StoppingDistance / (elevposition.y - (Destination + LevelingOffset)));
1699 //start deceleration
1702 if (InspectionService == false)
1703 ElevatorRate += ElevatorSpeed * ((TempDeceleration * JerkRate) * sbs->delta);
1705 ElevatorRate += (ElevatorSpeed * 0.6) * ((TempDeceleration * JerkRate) * sbs->delta);
1711 //play elevator stopping sounds
1713 Report("playing stopping sounds");
1714 bool adjust = sbs->GetConfigBool("Skyscraper.SBS.Elevator.AutoAdjustSound", false);
1715 mainsound->Load(CarStopSound.c_str());
1716 mainsound->Loop(false);
1717 //set play position to current percent of the total speed
1719 mainsound->SetPlayPosition(1 - (ElevatorRate / ElevatorSpeed));
1722 mainsound->Play(false);
1723 motorsound->Load(MotorStopSound.c_str());
1724 motorsound->Loop(false);
1726 motorsound->SetPlayPosition(1 - (ElevatorRate / ElevatorSpeed));
1728 motorsound->Reset();
1729 motorsound->Play(false);
1731 if (NotifyEarly == 2 && Parking == false)
1732 NotifyArrival(GotoFloor);
1735 else if (Leveling == false && EmergencyStop == false)
1737 if (fabs(ElevatorRate) <= LevelingSpeed)
1739 //turn on leveling if elevator's rate is less than or equal to the leveling speed value
1741 Report("leveling enabled");
1744 if (NotifyEarly == 1 && Parking == false)
1745 NotifyArrival(GotoFloor);
1749 if (Leveling == true)
1751 //floor leveling routine
1752 if (Direction == -1 && (Destination - elevposition.y) > 0)
1753 ElevatorRate = LevelingSpeed;
1754 else if (Direction == 1 && (elevposition.y - Destination) > 0)
1755 ElevatorRate = -LevelingSpeed;
1759 Report("arrived at floor");
1760 ElevatorRate = 0; //stop if on floor
1763 //open doors if leveling open offset is not zero
1764 if (LevelingOpen > 0 && FinishedMove == false && ArrivalDelay == 0)
1766 if (Direction == -1 && (Destination - elevposition.y) < LevelingOpen)
1768 else if (Direction == 1 && (elevposition.y - Destination) < LevelingOpen)
1773 if (GetFloor() != oldfloor)
1776 Report("on floor " + std::string(_itoa(GetFloor(), intbuffer, 10)));
1778 //play floor beep sound if floor is a serviced floor
1779 if (IsServicedFloor(GetFloor()) == true)
1782 //update floor indicators
1783 UpdateFloorIndicators();
1785 //update floor indicators on current camera floor
1786 sbs->GetFloor(sbs->camera->CurrentFloor)->UpdateFloorIndicators(Number);
1789 oldfloor = GetFloor();
1791 //exit if elevator's running
1792 if (fabs(ElevatorRate) != 0)
1795 //start arrival timer
1796 if (ArrivalDelay > 0)
1798 if (WaitForTimer == false && arrival_delay->IsRunning() == false)
1801 Report("started arrival delay");
1802 WaitForTimer = true;
1803 arrival_delay->Start(ArrivalDelay * 1000, false);
1809 Report("finished arrival delay");
1810 arrival_delay->Stop();
1815 if (EmergencyStop == false)
1818 Report("storing error offset");
1820 //store error offset value
1821 if (Direction == -1)
1822 ErrorOffset = elevposition.y - Destination;
1823 else if (Direction == 1)
1824 ErrorOffset = Destination - elevposition.y;
1828 //set elevator and objects to floor altitude (corrects offset errors)
1829 //move elevator objects
1831 Report("setting elevator to floor altitude");
1832 ElevatorMesh->Move(Ogre::Vector3(elevposition.x, Destination, elevposition.z), false, false, false);
1833 if (sbs->ElevatorSync == true && sbs->ElevatorNumber == Number)
1834 sbs->camera->SetPosition(Ogre::Vector3(sbs->camera->GetPosition().x, GetPosition().y + CameraOffset, sbs->camera->GetPosition().z));
1835 MoveDoors(0, Ogre::Vector3(0, Destination, 0), true, false, true);
1836 MoveLights(Ogre::Vector3(0, Destination, 0), true, false, true);
1837 MoveModels(Ogre::Vector3(0, Destination, 0), true, false, true);
1838 for (int i = 0; i < (int)FloorIndicatorArray.size(); i++)
1840 if (FloorIndicatorArray[i])
1841 FloorIndicatorArray[i]->SetPosition(Ogre::Vector3(FloorIndicatorArray[i]->GetPosition().x, Destination, FloorIndicatorArray[i]->GetPosition().z));
1843 for (int i = 0; i < (int)PanelArray.size(); i++)
1846 PanelArray[i]->SetToElevatorAltitude();
1848 for (int i = 0; i < (int)DirIndicatorArray.size(); i++)
1850 if (DirIndicatorArray[i])
1851 DirIndicatorArray[i]->SetPosition(Ogre::Vector3(DirIndicatorArray[i]->GetPosition().x, Destination, DirIndicatorArray[i]->GetPosition().z));
1853 for (int i = 0; i < (int)StdDoorArray.size(); i++)
1855 if (StdDoorArray[i])
1856 StdDoorArray[i]->Move(Ogre::Vector3(0, GetPosition().y, 0), true, false, true);
1860 mainsound->SetPosition(GetPosition());
1861 idlesound->SetPosition(GetPosition());
1862 MoveDoorSound(0, GetPosition(), false, false, false);
1863 alarm->SetPosition(GetPosition());
1864 floorbeep->SetPosition(GetPosition());
1865 floorsound->SetPosition(GetPosition());
1866 messagesnd->SetPosition(GetPosition());
1867 musicsound->SetPosition(GetPosition() + MusicPosition);
1868 for (int i = 0; i < (int)sounds.size(); i++)
1871 sounds[i]->SetPositionY(GetPosition().y + sounds[i]->PositionOffset.y);
1875 //reset values if at destination floor
1878 Report("resetting elevator motion values");
1884 DistanceToTravel = 0;
1886 ElevatorIsRunning = false;
1887 MoveElevator = false;
1894 if (FinishedMove == false)
1898 void Elevator::FinishMove()
1900 //post-move operations, such as chimes, opening doors, indicator updates, etc
1902 if (EmergencyStop == false)
1904 //the elevator is now stopped on a valid floor; set OnFloor to true
1906 Report("arrived at floor " + std::string(_itoa(GotoFloor, intbuffer, 10)) + " (" + sbs->GetFloor(GotoFloor)->ID + ")");
1908 //dequeue floor route
1909 DeleteActiveRoute();
1912 //turn off interior directional indicators
1913 ActiveDirection = 0;
1914 UpdateDirectionalIndicators();
1916 //update external active-direction indicators
1917 sbs->GetFloor(sbs->camera->CurrentFloor)->UpdateDirectionalIndicators(Number);
1919 if (EmergencyStop == false && InspectionService == false)
1921 //update floor indicators on current camera floor
1922 sbs->GetFloor(sbs->camera->CurrentFloor)->UpdateFloorIndicators(Number);
1924 UpdateFloorIndicators();
1926 //turn on objects if user is in elevator
1927 if (sbs->ElevatorSync == true && sbs->ElevatorNumber == Number && CameraOffset < Height)
1930 Report("user in elevator - turning on objects");
1933 sbs->GetFloor(GotoFloor)->Enabled(true);
1934 sbs->GetFloor(GotoFloor)->EnableGroup(true);
1936 //Turn on sky, buildings, and landscape
1937 sbs->EnableSkybox(true);
1938 sbs->EnableBuildings(true);
1939 sbs->EnableLandscape(true);
1940 sbs->EnableExternal(true);
1943 for (int i = 1; i <= sbs->Shafts(); i++)
1945 sbs->GetShaft(i)->EnableRange(GotoFloor, sbs->ShaftDisplayRange, false, true);
1946 sbs->GetShaft(i)->EnableRange(GotoFloor, sbs->ShaftDisplayRange, true, true);
1949 else if (sbs->Verbose)
1950 Report("user not in elevator - not turning on objects");
1952 //notify arrival and disable call button light
1953 if (InServiceMode() == false)
1955 //reverse queue if at end of current queue, and if elevator was moving in the correct direction (not moving up for a down call, etc)
1956 if ((QueuePositionDirection == 1 && UpQueue.size() == 0 && ElevatorFloor < GotoFloor) || (QueuePositionDirection == -1 && DownQueue.size() == 0 && ElevatorFloor > GotoFloor))
1958 std::vector<int> buttons = sbs->GetFloor(GotoFloor)->GetCallButtons(Number);
1959 if (buttons.size() > 0)
1961 CallButton *button = sbs->GetFloor(GotoFloor)->CallButtonArray[buttons[0]];
1962 //only reverse the queue direction if no related active call is on the floor
1963 if ((button->UpStatus == false && QueuePositionDirection == 1) || (button->DownStatus == false && QueuePositionDirection == -1))
1966 Report("reversing queue search direction");
1967 LastQueueDirection = QueuePositionDirection;
1968 QueuePositionDirection = -QueuePositionDirection;
1973 if ((NotifyEarly == 0 || Notified == false) && Parking == false)
1974 NotifyArrival(GotoFloor);
1976 //disable call button lights
1977 SetCallButtons(GotoFloor, GetArrivalDirection(GotoFloor), false);
1981 //do not automatically open doors if in fire service phase 2
1982 if (FireServicePhase2 == 0)
1984 if (Parking == false)
1993 Report("stop complete");
1994 EmergencyStop = false;
1995 if (sbs->ElevatorSync == true && sbs->ElevatorNumber == Number)
1998 for (int i = 1; i <= sbs->Shafts(); i++)
2000 sbs->GetShaft(i)->EnableRange(GotoFloor, sbs->ShaftDisplayRange, false, true);
2001 sbs->GetShaft(i)->EnableRange(GotoFloor, sbs->ShaftDisplayRange, true, true);
2006 //update elevator's floor number
2007 ElevatorFloor = GotoFloor;
2010 FinishedMove = true;
2013 WallObject* Elevator::AddWall(const char *name, const char *texture, float thickness, float x1, float z1, float x2, float z2, float height1, float height2, float voffset1, float voffset2, float tw, float th)
2015 //Adds a wall with the specified dimensions
2017 WallObject *wall = ElevatorMesh->CreateWallObject(this->object, name);
2018 sbs->AddWallMain(wall, name, texture, thickness, x1, z1, x2, z2, height1, height2, voffset1, voffset2, tw, th, true);
2022 WallObject* Elevator::AddFloor(const char *name, const char *texture, float thickness, float x1, float z1, float x2, float z2, float voffset1, float voffset2, float tw, float th)
2024 //Adds a floor with the specified dimensions and vertical offset
2026 WallObject *wall = ElevatorMesh->CreateWallObject(this->object, name);
2027 sbs->AddFloorMain(wall, name, texture, thickness, x1, z1, x2, z2, voffset1, voffset2, tw, th, true);
2031 Object* Elevator::AddFloorIndicator(const char *texture_prefix, const char *direction, float CenterX, float CenterZ, float width, float height, float voffset)
2033 //Creates a floor indicator at the specified location
2035 int size = (int)FloorIndicatorArray.size();
2036 FloorIndicatorArray.resize(size + 1);
2037 FloorIndicatorArray[size] = new FloorIndicator(object, Number, texture_prefix, direction, CenterX, CenterZ, width, height, voffset, true);
2038 FloorIndicatorArray[size]->SetPosition(Origin);
2039 return FloorIndicatorArray[size]->object;
2042 const Ogre::Vector3 Elevator::GetPosition()
2044 //returns the elevator's position
2045 return ElevatorMesh->GetPosition();
2048 void Elevator::DumpQueues()
2050 //dump both (up and down) elevator queues
2052 sbs->Report("--- Elevator " + std::string(_itoa(Number, intbuffer, 10)) + " Queues ---\n");
2054 for (int i = 0; i < (int)UpQueue.size(); i++)
2055 sbs->Report(std::string(_itoa(i, intbuffer, 10)) + " - " + std::string(_itoa(UpQueue[i], intbuffer, 10)));
2056 sbs->Report("Down:");
2057 for (int i = 0; i < (int)DownQueue.size(); i++)
2058 sbs->Report(std::string(_itoa(i, intbuffer, 10)) + " - " + std::string(_itoa(DownQueue[i], intbuffer, 10)));
2061 void Elevator::Enabled(bool value)
2063 //shows/hides elevator
2065 if (IsEnabled == value)
2068 //SBS_PROFILE("Elevator::Enabled");
2072 Report("enabling elevator");
2074 Report("disabling elevator");
2077 ElevatorMesh->Enable(value);
2082 void Elevator::EnableObjects(bool value)
2084 //enable or disable interior objects, such as floor indicators and button panels
2086 //SBS_PROFILE("Elevator::EnableObjects");
2090 Report("enabling objects");
2092 Report("disabling objects");
2096 /*for (int i = 0; i < FloorIndicatorArray.size(); i++)
2098 if (FloorIndicatorArray[i])
2099 FloorIndicatorArray[i]->Enabled(value);
2102 //interior directional indicators
2103 //EnableDirectionalIndicators(value);
2106 for (size_t i = 0; i < (int)ModelArray.size(); i++)
2109 ModelArray[i]->Enable(value);
2113 for (int i = 0; i < (int)PanelArray.size(); i++)
2114 PanelArray[i]->Enabled(value);
2117 for (int i = 0; i < (int)sounds.size(); i++)
2129 bool Elevator::IsElevator(Ogre::MeshPtr test)
2131 if (test == ElevatorMesh->MeshWrapper)
2137 bool Elevator::IsInElevator(const Ogre::Vector3 &position)
2139 //determine if the given 3D position is inside the elevator
2141 //SBS_PROFILE("Elevator::IsInElevator");
2142 bool inelevator = false;
2144 //if last position is the same as new, return previous result
2145 if ((position.x >= (lastposition.x - 0.01)) &&
2146 (position.y >= (lastposition.y - 0.01)) &&
2147 (position.z >= (lastposition.z - 0.01)) &&
2148 (position.x <= (lastposition.x + 0.01)) &&
2149 (position.y <= (lastposition.y + 0.01)) &&
2150 (position.z <= (lastposition.z + 0.01)) &&
2151 checkfirstrun == false)
2152 return lastcheckresult;
2154 checkfirstrun = false;
2156 if (position.y > GetPosition().y && position.y < GetPosition().y + (Height * 2))
2158 if (ElevatorMesh->InBoundingBox(position, false) == true)
2160 if (ElevatorMesh->HitBeam(position, Ogre::Vector3::NEGATIVE_UNIT_Y, Height) >= 0)
2162 if (IsMoving == false)
2164 //store camera offset if elevator is not moving
2165 CameraOffset = position.y - GetPosition().y;
2167 else if (CameraOffset == 0)
2169 //reposition camera with a moving elevator if the offset is 0
2170 if (position.y < GetPosition().y + Height)
2171 CameraOffset = sbs->camera->GetHeight(); //if below ceiling, set to camera height
2173 CameraOffset = Height + sbs->camera->GetHeight(); //if above ceiling, set to elev height + camera height
2181 if (position.y < GetPosition().y + Height)
2184 lastcheckresult = inelevator;
2185 lastposition = position;
2192 lastcheckresult = false;
2193 lastposition = position;
2198 float Elevator::GetElevatorStart()
2200 //returns the internal elevator starting position
2201 return ElevatorStart;
2204 float Elevator::GetDestination()
2206 //returns the internal destination value
2210 float Elevator::GetStoppingDistance()
2212 //returns the internal stopping distance value
2213 return StoppingDistance;
2216 bool Elevator::GetBrakeStatus()
2218 //returns the internal brake status value
2222 bool Elevator::GetEmergencyStopStatus()
2224 //returns the internal emergency stop status
2225 return EmergencyStop;
2228 void Elevator::DumpServicedFloors()
2230 //dump serviced floors list
2232 sbs->Report("--- Elevator " + std::string(_itoa(Number, intbuffer, 10)) + "'s Serviced Floors ---\n");
2233 for (int i = 0; i < (int)ServicedFloors.size(); i++)
2234 sbs->Report(std::string(_itoa(i, intbuffer, 10)) + " - " + std::string(_itoa(ServicedFloors[i], intbuffer, 10)));
2237 bool Elevator::AddServicedFloor(int number)
2240 Report("adding serviced floor " + std::string(_itoa(number, intbuffer, 10)));
2242 //check if floor is outside valid floor range
2243 if (sbs->IsValidFloor(number) == false)
2245 std::string floor = Ogre::StringConverter::toString(number);
2246 return ReportError("AddServicedFloor: Invalid floor " + floor);
2249 if (IsServicedFloor(number) == false)
2251 ServicedFloors.push_back(number);
2252 std::sort(ServicedFloors.begin(), ServicedFloors.end());
2257 void Elevator::RemoveServicedFloor(int number)
2260 Report("removing serviced floor " + std::string(_itoa(number, intbuffer, 10)));
2261 if (IsServicedFloor(number) == true)
2263 for (int i = 0; i < (int)ServicedFloors.size(); i++)
2265 if (ServicedFloors[i] == number)
2266 ServicedFloors.erase(ServicedFloors.begin() + i);
2271 Object* Elevator::CreateButtonPanel(const char *texture, int rows, int columns, const char *direction, float CenterX, float CenterZ, float buttonwidth, float buttonheight, float spacingX, float spacingY, float voffset, float tw, float th)
2273 //create a new button panel object and store the pointer
2275 int index = (int)PanelArray.size();
2276 std::string number = Ogre::StringConverter::toString(index + 1);
2278 PanelArray.resize(index + 1);
2281 Report("creating button panel " + number);
2283 PanelArray[index] = new ButtonPanel(Number, index + 1, texture, rows, columns, direction, CenterX, CenterZ, buttonwidth, buttonheight, spacingX, spacingY, voffset, tw, th);
2284 if (PanelArray[index])
2285 return PanelArray[index]->object;
2290 void Elevator::UpdateFloorIndicators()
2292 //changes the number texture on the floor indicators to the elevator's current floor
2294 SBS_PROFILE("Elevator::UpdateFloorIndicators");
2296 if (UseFloorSkipText == true && IsServicedFloor(GetFloor()) == false)
2297 value = FloorSkipText;
2300 if (DisplayFloors.size() > 0)
2302 for (int i = 0; i < DisplayFloors.size(); i++)
2304 if (GetFloor() == DisplayFloors[i])
2305 value = sbs->GetFloor(GetFloor())->ID;
2309 value = sbs->GetFloor(GetFloor())->ID;
2316 for (int i = 0; i < (int)FloorIndicatorArray.size(); i++)
2318 if (FloorIndicatorArray[i])
2319 FloorIndicatorArray[i]->Update(value.c_str());
2323 double Elevator::GetJerkRate()
2328 double Elevator::GetJerkPosition()
2333 void Elevator::SetFloorSkipText(const char *id)
2335 //sets the text shown in the floor indicator while skipping floors (an express zone)
2338 Report("setting floor skip text to " + std::string(id));
2339 UseFloorSkipText = true;
2341 TrimString(FloorSkipText);
2344 const char* Elevator::GetFloorSkipText()
2346 //get the floor skip text
2347 return FloorSkipText.c_str();
2350 bool Elevator::IsServicedFloor(int floor)
2352 //returns true if floor is in serviced floor list, otherwise false
2354 //SBS_PROFILE("Elevator::IsServicedFloor");
2356 for (int i = 0; i < (int)ServicedFloors.size(); i++)
2358 if (ServicedFloors[i] == floor)
2364 Report("Floor " + std::string(_itoa(floor, intbuffer, 10)) + " is not a serviced floor");
2370 Report("Floor " + std::string(_itoa(floor, intbuffer, 10)) + " is a serviced floor");
2375 bool Elevator::InServiceMode()
2377 //report if an elevator is in a service mode
2378 if (IndependentService == true || InspectionService == true || FireServicePhase1 == 1 || FireServicePhase2 != 0)
2384 void Elevator::Go(int floor)
2386 //go to specified floor, bypassing the queuing system
2388 if (Running == false)
2390 Report("Elevator not running");
2394 //exit if in inspection mode
2395 if (InspectionService == true)
2398 Report("Go: in inspection mode");
2403 Report("Go: proceeding to floor " + std::string(_itoa(floor, intbuffer, 10)));
2405 WaitForDoors = true;
2407 MoveElevator = true;
2410 void Elevator::GoToRecallFloor()
2412 //for fire service modes; tells the elevator to go to the recall floor (or the alternate recall floor
2413 //if the other is not available)
2415 if (Running == false)
2417 Report("Elevator not running");
2421 //stop elevator if moving
2422 if (IsMoving == true)
2426 ResetQueue(true, true);
2428 if (RecallUnavailable == false)
2430 Report("Proceeding to recall floor");
2431 if (RecallFloor > GetFloor())
2432 AddRoute(RecallFloor, 1, false);
2434 AddRoute(RecallFloor, -1, false);
2438 Report("Proceeding to alternate recall floor");
2439 if (RecallFloor > GetFloor())
2440 AddRoute(RecallFloorAlternate, 1, false);
2442 AddRoute(RecallFloorAlternate, -1, false);
2446 void Elevator::EnableACP(bool value)
2448 //enable Anti-Crime Protection (ACP) mode
2450 if (Running == false)
2452 Report("Elevator not running");
2460 Report("EnableACP: mode is the same");
2468 EnableIndependentService(false);
2469 EnableInspectionService(false);
2470 EnableFireService1(0);
2471 EnableFireService2(0);
2472 Report("ACP mode enabled");
2475 Report("ACP mode disabled");
2479 void Elevator::EnableUpPeak(bool value)
2481 //enable Up-Peak mode
2483 if (Running == false)
2485 Report("Elevator not running");
2490 if (UpPeak == value)
2493 Report("EnableUpPeak: mode is the same");
2501 EnableDownPeak(false);
2502 EnableIndependentService(false);
2503 EnableInspectionService(false);
2504 EnableFireService1(0);
2505 EnableFireService2(0);
2506 if (IsMoving == false && GetFloor() == GetBottomFloor())
2508 sbs->GetFloor(GetFloor())->SetDirectionalIndicators(Number, true, false);
2509 SetDirectionalIndicators(true, false);
2512 Report("Up Peak mode enabled");
2517 Report("Up Peak mode disabled");
2521 void Elevator::EnableDownPeak(bool value)
2523 //enable Down-Peak mode
2525 if (Running == false)
2527 Report("Elevator not running");
2532 if (DownPeak == value)
2535 Report("EnableDownPeak: mode is the same");
2543 EnableUpPeak(false);
2544 EnableIndependentService(false);
2545 EnableInspectionService(false);
2546 EnableFireService1(0);
2547 EnableFireService2(0);
2548 if (IsMoving == false && GetFloor() == GetTopFloor())
2550 sbs->GetFloor(GetFloor())->SetDirectionalIndicators(Number, false, true);
2551 SetDirectionalIndicators(false, true);
2554 Report("Down Peak mode enabled");
2559 Report("Down Peak mode disabled");
2563 void Elevator::EnableIndependentService(bool value)
2565 //enable Independent Service (ISC) mode
2567 if (Running == false)
2569 Report("Elevator not running");
2574 if (IndependentService == value)
2577 Report("EnableIndependentService: mode is the same");
2581 IndependentService = value;
2586 EnableUpPeak(false);
2587 EnableDownPeak(false);
2588 EnableInspectionService(false);
2589 EnableFireService1(0);
2590 EnableFireService2(0);
2591 ResetQueue(true, true);
2592 EnableNudgeMode(false);
2593 if (IsMoving == false)
2595 Report("Independent Service mode enabled");
2600 Report("Independent Service mode disabled");
2604 void Elevator::EnableInspectionService(bool value)
2606 //enable Inspection Service (INS) mode
2609 if (InspectionService == value)
2612 Report("EnableInspectionService: mode is the same");
2619 EnableUpPeak(false);
2620 EnableDownPeak(false);
2621 EnableIndependentService(false);
2622 EnableFireService1(0);
2623 EnableFireService2(0);
2624 EnableNudgeMode(false);
2625 ResetQueue(true, true);
2626 if (IsMoving == true)
2628 Report("Inspection Service mode enabled");
2633 Report("Inspection Service mode disabled");
2635 UpdateFloorIndicators();
2637 //turn on objects if user is in elevator
2638 if (sbs->ElevatorSync == true && sbs->ElevatorNumber == Number && IsMoving == false)
2641 Report("user in elevator - turning on objects");
2644 sbs->GetFloor(GetFloor())->Enabled(true);
2645 sbs->GetFloor(GetFloor())->EnableGroup(true);
2647 //Turn on sky, buildings, and landscape
2648 sbs->EnableSkybox(true);
2649 sbs->EnableBuildings(true);
2650 sbs->EnableLandscape(true);
2651 sbs->EnableExternal(true);
2654 for (int i = 1; i <= sbs->Shafts(); i++)
2656 sbs->GetShaft(i)->EnableRange(GetFloor(), sbs->ShaftDisplayRange, false, true);
2657 sbs->GetShaft(i)->EnableRange(GetFloor(), sbs->ShaftDisplayRange, true, true);
2661 if (IsMoving == true)
2665 InspectionService = value;
2668 void Elevator::EnableFireService1(int value)
2670 //enable Fire Service Phase 1 mode
2671 //valid values are 0 (off), 1 (on) or 2 (bypass)
2673 if (Running == false)
2675 Report("Elevator not running");
2680 if (FireServicePhase1 == value)
2683 Report("EnableFireService1: mode is the same");
2687 if (value >= 0 && value <= 2)
2688 FireServicePhase1 = value;
2692 Report("EnableFireService1: invalid value");
2699 EnableUpPeak(false);
2700 EnableDownPeak(false);
2701 EnableIndependentService(false);
2702 EnableInspectionService(false);
2703 EnableFireService2(0);
2706 Report("Fire Service Phase 1 mode set to On");
2708 //enable nudge mode on all doors if any are open
2709 if (GetFloor() != RecallFloor)
2710 EnableNudgeMode(true);
2716 Report("Fire Service Phase 1 mode set to Bypass");
2721 Report("Fire Service Phase 1 mode set to Off");
2725 void Elevator::EnableFireService2(int value)
2727 //enable Fire Service Phase 2 mode
2728 //valid values are 0 (off), 1 (on) or 2 (hold)
2730 if (Running == false)
2732 Report("Elevator not running");
2737 if (FireServicePhase2 == value)
2740 Report("EnableFireService2: mode is the same");
2744 if (value >= 0 && value <= 2)
2745 FireServicePhase2 = value;
2749 Report("EnableFireService2: invalid value");
2756 EnableUpPeak(false);
2757 EnableDownPeak(false);
2758 EnableIndependentService(false);
2759 EnableInspectionService(false);
2760 EnableFireService1(0);
2761 EnableNudgeMode(false);
2762 ResetQueue(true, true);
2764 Report("Fire Service Phase 2 mode set to On");
2767 if (IsMoving == false)
2769 Report("Fire Service Phase 2 mode set to Hold");
2775 Report("Fire Service Phase 2 mode set to Off");
2780 bool Elevator::SetRecallFloor(int floor)
2782 //set elevator's fire recall floor
2783 if (ServicedFloors.size() == 0)
2785 ReportError("No serviced floors assigned");
2788 if (IsServicedFloor(floor) == false)
2790 ReportError("Invalid recall floor");
2795 Report("setting recall floor to " + std::string(_itoa(floor, intbuffer, 10)));
2796 RecallFloor = floor;
2801 bool Elevator::SetAlternateRecallFloor(int floor)
2803 //set elevator's alternate fire recall floor
2804 if (ServicedFloors.size() == 0)
2806 ReportError("No serviced floors assigned");
2809 if (IsServicedFloor(floor) == false)
2811 ReportError("Invalid alternate recall floor");
2816 Report("setting alternate recall floor to " + std::string(_itoa(floor, intbuffer, 10)));
2817 RecallFloorAlternate = floor;
2818 RecallAltSet = true;
2822 bool Elevator::SetACPFloor(int floor)
2824 //set elevator's ACP floor
2825 if (ServicedFloors.size() == 0)
2827 ReportError("No serviced floors assigned");
2830 if (IsServicedFloor(floor) == false)
2832 ReportError("Invalid ACP floor");
2837 Report("setting ACP floor to " + std::string(_itoa(floor, intbuffer, 10)));
2843 bool Elevator::MoveUp()
2845 if (Running == false)
2847 Report("Elevator not running");
2851 //moves elevator upwards if in Inspection Service mode
2852 if (InspectionService == false)
2854 Report("Not in inspection service mode");
2858 //make sure Go button is on
2859 if (ManualGo == false)
2862 Report("MoveUp: go button is off");
2866 if (IsMoving == true)
2869 Report("MoveUp: already moving");
2875 MoveElevator = true;
2877 Report("MoveUp: moving elevator");
2881 bool Elevator::MoveDown()
2883 if (Running == false)
2885 Report("Elevator not running");
2889 //moves elevator downwards if in Inspection Service mode
2890 if (InspectionService == false)
2892 Report("Not in inspection service mode");
2896 //make sure Go button is on
2897 if (ManualGo == false)
2900 Report("MoveDown: go button is off");
2904 if (IsMoving == true)
2907 Report("MoveDown: already moving");
2913 MoveElevator = true;
2915 Report("MoveDown: moving elevator");
2919 void Elevator::SetGoButton(bool value)
2921 //sets the value of the Go button (for Inspection Service mode)
2923 if (Running == false)
2925 Report("Elevator not running");
2929 if (InspectionService == false)
2932 if (ManualGo == true && value == false)
2940 Report("setting go button status to true");
2942 Report("setting go button status to false");
2946 int Elevator::GetTopFloor()
2948 //returns highest serviced floor
2949 return ServicedFloors[ServicedFloors.size() - 1];
2952 int Elevator::GetBottomFloor()
2954 //returns lowest serviced floor
2955 return ServicedFloors[0];
2958 void Elevator::AddDirectionalIndicators(bool relative, bool active_direction, bool single, bool vertical, const char *BackTexture, const char *uptexture, const char *uptexture_lit, const char *downtexture, const char *downtexture_lit, float CenterX, float CenterZ, float voffset, const char *direction, float BackWidth, float BackHeight, bool ShowBack, float tw, float th)
2960 //create external directional indicators on all serviced floors
2963 Report("adding directional indicators");
2965 for (size_t i = 0; i < ServicedFloors.size(); i++)
2966 sbs->GetFloor(ServicedFloors[i])->AddDirectionalIndicator(Number, relative, active_direction, single, vertical, BackTexture, uptexture, uptexture_lit, downtexture, downtexture_lit, CenterX, CenterZ, voffset, direction, BackWidth, BackHeight, ShowBack, tw, th);
2969 Object* Elevator::AddDirectionalIndicator(bool active_direction, bool single, bool vertical, const char *BackTexture, const char *uptexture, const char *uptexture_lit, const char *downtexture, const char *downtexture_lit, float CenterX, float CenterZ, float voffset, const char *direction, float BackWidth, float BackHeight, bool ShowBack, float tw, float th)
2971 //create a directional indicator inside the elevator
2974 Report("adding interior directional indicator");
2976 float x = Origin.x + CenterX;
2977 float z = Origin.z + CenterZ;
2979 int index = (int)DirIndicatorArray.size();
2980 DirIndicatorArray.resize(index + 1);
2981 DirIndicatorArray[index] = new DirectionalIndicator(object, Number, 0, active_direction, single, vertical, BackTexture, uptexture, uptexture_lit, downtexture, downtexture_lit, x, z, voffset, direction, BackWidth, BackHeight, ShowBack, tw, th, true);
2982 DirIndicatorArray[index]->SetPosition(Ogre::Vector3(DirIndicatorArray[index]->GetPosition().x, sbs->GetFloor(OriginFloor)->GetBase(), DirIndicatorArray[index]->GetPosition().z));
2983 return DirIndicatorArray[index]->object;
2986 void Elevator::SetDirectionalIndicators(bool UpLight, bool DownLight)
2988 //set light status of interior directional indicators
2990 for (int i = 0; i < (int)DirIndicatorArray.size(); i++)
2992 if (DirIndicatorArray[i])
2994 if (DirIndicatorArray[i]->ActiveDirection == false)
2996 DirIndicatorArray[i]->DownLight(DownLight);
2997 DirIndicatorArray[i]->UpLight(UpLight);
3003 void Elevator::UpdateDirectionalIndicators()
3005 //updates all interior active direction indicators
3007 for (int i = 0; i < (int)DirIndicatorArray.size(); i++)
3009 if (DirIndicatorArray[i])
3011 if (DirIndicatorArray[i]->ActiveDirection == true)
3013 if (ActiveDirection == 1)
3015 DirIndicatorArray[i]->DownLight(false);
3016 DirIndicatorArray[i]->UpLight(true);
3018 if (ActiveDirection == 0)
3020 DirIndicatorArray[i]->DownLight(false);
3021 DirIndicatorArray[i]->UpLight(false);
3023 if (ActiveDirection == -1)
3025 DirIndicatorArray[i]->DownLight(true);
3026 DirIndicatorArray[i]->UpLight(false);
3033 void Elevator::EnableDirectionalIndicators(bool value)
3035 //turn on/off all interior directional indicators
3040 Report("enabling interior directional indicators");
3042 Report("disabling interior directional indicators");
3045 for (int i = 0; i < (int)DirIndicatorArray.size(); i++)
3047 if (DirIndicatorArray[i])
3048 DirIndicatorArray[i]->Enabled(value);
3052 ElevatorDoor* Elevator::GetDoor(int number)
3054 //get elevator door object
3056 //return cached check if number is the same
3057 if (lastdoor_number == number)
3058 return lastdoor_result;
3060 if (number > 0 && number <= (int)DoorArray.size())
3062 if (DoorArray[number - 1])
3064 lastdoor_result = DoorArray[number - 1];
3065 lastdoor_number = number;
3066 return lastdoor_result;
3072 void Elevator::OpenDoorsEmergency(int number, int whichdoors, int floor)
3074 //Simulates manually prying doors open.
3075 //Slowly opens the elevator doors no matter where elevator is.
3076 //If lined up with shaft doors, then opens the shaft doors also
3078 //WhichDoors is the doors to move:
3079 //1 = both shaft and elevator doors
3080 //2 = only elevator doors
3081 //3 = only shaft doors
3083 OpenDoors(number, whichdoors, floor, true);
3086 void Elevator::CloseDoorsEmergency(int number, int whichdoors, int floor)
3088 //Simulates manually closing doors.
3089 //Slowly closes the elevator doors no matter where elevator is.
3090 //If lined up with shaft doors, then closes the shaft doors also
3092 //WhichDoors is the doors to move:
3093 //1 = both shaft and elevator doors
3094 //2 = only elevator doors
3095 //3 = only shaft doors
3097 CloseDoors(number, whichdoors, floor, true);
3100 void Elevator::OpenDoors(int number, int whichdoors, int floor, bool manual)
3102 //Opens elevator doors
3104 //if manual is true, then it simulates manually prying doors open,
3105 //Slowly opens the elevator doors no matter where elevator is,
3106 //and if lined up with shaft doors, then opens the shaft doors also
3108 //WhichDoors is the doors to move:
3109 //1 = both shaft and elevator doors
3110 //2 = only elevator doors
3111 //3 = only shaft doors
3124 for (int i = start; i <= end; i++)
3127 GetDoor(i)->OpenDoors(whichdoors, floor, manual);
3129 Report("Invalid door " + std::string(_itoa(i, intbuffer, 10)));
3133 void Elevator::CloseDoors(int number, int whichdoors, int floor, bool manual)
3135 //Closes elevator doors
3137 //WhichDoors is the doors to move:
3138 //1 = both shaft and elevator doors
3139 //2 = only elevator doors
3140 //3 = only shaft doors
3153 for (int i = start; i <= end; i++)
3156 GetDoor(i)->CloseDoors(whichdoors, floor, manual);
3158 Report("Invalid door " + std::string(_itoa(i, intbuffer, 10)));
3162 void Elevator::StopDoors(int number)
3164 //stops doors that are currently moving; can only be used for manual/emergency movements
3165 //this basically just resets the door internals
3178 for (int i = start; i <= end; i++)
3181 GetDoor(i)->StopDoors();
3183 Report("Invalid door " + std::string(_itoa(i, intbuffer, 10)));
3187 Object* Elevator::AddDoors(int number, const char *lefttexture, const char *righttexture, float thickness, float CenterX, float CenterZ, float width, float height, bool direction, float tw, float th)
3189 //adds elevator doors specified at a relative central position (off of elevator origin)
3190 //if direction is false, doors are on the left/right side; otherwise front/back
3192 if (GetDoor(number))
3193 return GetDoor(number)->AddDoors(lefttexture, righttexture, thickness, CenterX, CenterZ, width, height, direction, tw, th);
3195 ReportError("Invalid door " + std::string(_itoa(number, intbuffer, 10)));
3199 bool Elevator::AddShaftDoors(int number, const char *lefttexture, const char *righttexture, float thickness, float CenterX, float CenterZ, float tw, float th)
3201 //adds shaft's elevator doors specified at a relative central position (off of elevator origin)
3202 //uses some parameters (width, height, direction) from AddDoors function
3204 if (GetDoor(number))
3205 return GetDoor(number)->AddShaftDoors(lefttexture, righttexture, thickness, CenterX, CenterZ, tw, th);
3207 ReportError("Invalid door " + std::string(_itoa(number, intbuffer, 10)));
3211 Object* Elevator::AddShaftDoor(int floor, int number, const char *lefttexture, const char *righttexture, float tw, float th)
3213 //adds a single elevator shaft door on the specified floor, with position and thickness parameters first specified
3214 //by the SetShaftDoors command.
3217 for (int i = 0; i < (int)ServicedFloors.size(); i++)
3219 if (ServicedFloors[i] == floor)
3223 if (index != -1 && GetDoor(number))
3224 return GetDoor(number)->AddShaftDoor(floor, lefttexture, righttexture, tw, th);
3229 void Elevator::ShaftDoorsEnabled(int number, int floor, bool value)
3231 //turns shaft elevator doors on/off
3233 SBS_PROFILE("Elevator::ShaftDoorsEnabled");
3245 for (int i = start; i <= end; i++)
3247 ElevatorDoor *door = GetDoor(i);
3249 door->ShaftDoorsEnabled(floor, value);
3251 Report("Invalid door " + std::string(_itoa(i, intbuffer, 10)));
3255 void Elevator::ShaftDoorsEnabledRange(int number, int floor, int range)
3257 //turn on a range of floors
3258 //if range is 3, show shaft door on current floor (floor), and 1 floor below and above (3 total floors)
3259 //if range is 1, show door on only the current floor (floor)
3261 SBS_PROFILE("Elevator::ShaftDoorsEnabledRange");
3273 for (int i = start; i <= end; i++)
3275 ElevatorDoor *door = GetDoor(i);
3277 door->ShaftDoorsEnabledRange(floor, range);
3279 Report("Invalid door " + std::string(_itoa(i, intbuffer, 10)));
3283 bool Elevator::AreDoorsOpen(int number)
3285 //returns the internal door state
3287 SBS_PROFILE("Elevator::AreDoorsOpen");
3299 for (int i = start; i <= end; i++)
3301 ElevatorDoor *door = GetDoor(i);
3304 if (door->AreDoorsOpen() == true)
3308 Report("Invalid door " + std::string(_itoa(i, intbuffer, 10)));
3313 bool Elevator::AreShaftDoorsOpen(int number, int floor)
3315 //returns the internal shaft door state
3317 SBS_PROFILE("Elevator::AreShaftDoorsOpen");
3318 ElevatorDoor *door = GetDoor(number);
3320 return door->AreShaftDoorsOpen(floor);
3322 Report("Invalid door " + std::string(_itoa(number, intbuffer, 10)));
3326 void Elevator::Chime(int number, int floor, bool direction)
3328 //play chime sound on specified floor
3330 SBS_PROFILE("Elevator::Chime");
3342 for (int i = start; i <= end; i++)
3344 ElevatorDoor *door = GetDoor(i);
3346 door->Chime(floor, direction);
3348 Report("Invalid door " + std::string(_itoa(i, intbuffer, 10)));
3352 void Elevator::ResetDoorTimer(int number)
3354 //reset elevator door timer
3367 for (int i = start; i <= end; i++)
3369 ElevatorDoor *door = GetDoor(i);
3371 door->ResetDoorTimer();
3373 Report("Invalid door " + std::string(_itoa(i, intbuffer, 10)));
3377 bool Elevator::DoorsStopped(int number)
3390 for (int i = start; i <= end; i++)
3392 ElevatorDoor *door = GetDoor(i);
3394 return door->DoorsStopped();
3396 Report("Invalid door " + std::string(_itoa(i, intbuffer, 10)));
3401 bool Elevator::CheckOpenDoor()
3403 //check each door's OpenDoor value and return true if any are not zero, or
3404 //false if all are zero
3406 for (int i = 1; i <= NumDoors; i++)
3408 ElevatorDoor *door = GetDoor(i);
3411 if (door->OpenDoor != 0)
3418 void Elevator::MoveDoors(int number, const Ogre::Vector3 position, bool relative_x, bool relative_y, bool relative_z)
3422 SBS_PROFILE("Elevator::MoveDoors");
3425 for (int i = 1; i <= NumDoors; i++)
3428 GetDoor(i)->Move(position, relative_x, relative_y, relative_z);
3433 if (GetDoor(number))
3434 GetDoor(number)->Move(position, relative_x, relative_y, relative_z);
3438 void Elevator::EnableDoors(bool value)
3440 //enable/disable all doors
3442 SBS_PROFILE("Elevator::EnableDoors");
3446 Report("enabling doors");
3448 Report("disabling doors");
3451 for (int i = 1; i <= NumDoors; i++)
3453 ElevatorDoor *door = GetDoor(i);
3455 door->Enabled(value);
3459 void Elevator::MoveDoorSound(int number, const Ogre::Vector3 position, bool relative_x, bool relative_y, bool relative_z)
3465 for (int i = 1; i <= NumDoors; i++)
3468 GetDoor(i)->MoveSound(position, relative_x, relative_y, relative_z);
3473 if (GetDoor(number))
3474 GetDoor(number)->MoveSound(position, relative_x, relative_y, relative_z);
3478 void Elevator::SetShaftDoors(int number, float thickness, float CenterX, float CenterZ)
3482 for (int i = 1; i <= NumDoors; i++)
3485 GetDoor(i)->SetShaftDoors(thickness, CenterX, CenterZ);
3490 if (GetDoor(number))
3491 GetDoor(number)->SetShaftDoors(thickness, CenterX, CenterZ);
3495 bool Elevator::AddFloorSigns(int door_number, bool relative, const char *texture_prefix, const char *direction, float CenterX, float CenterZ, float width, float height, float voffset)
3497 //adds floor signs at the specified position and direction for each serviced floor,
3498 //depending on if the given door number services the floor or not (unless door_number is 0)
3501 if (relative == true)
3503 x = Origin.x + CenterX;
3504 z = Origin.z + CenterZ;
3512 //make sure specified door exists before continuing
3513 if (door_number != 0)
3515 if (DoorExists(door_number) == false)
3517 std::string doornum = Ogre::StringConverter::toString(door_number);
3518 ReportError("AddFloorSigns: door " + doornum + " does not exist");
3523 bool autosize_x, autosize_y;
3524 sbs->GetAutoSize(autosize_x, autosize_y);
3525 sbs->SetAutoSize(false, false);
3527 for (int i = 0; i < (int)ServicedFloors.size(); i++)
3529 bool door_result = false;
3530 if (door_number != 0)
3531 door_result = GetDoor(door_number)->ShaftDoorsExist(ServicedFloors[i]);
3533 if (door_number == 0 || door_result == true)
3535 std::string texture = texture_prefix + sbs->GetFloor(ServicedFloors[i])->ID;
3536 std::string tmpdirection = direction;
3537 SetCase(tmpdirection, false);
3539 if (tmpdirection == "front" || tmpdirection == "left")
3540 sbs->DrawWalls(true, false, false, false, false, false);
3542 sbs->DrawWalls(false, true, false, false, false, false);
3544 if (tmpdirection == "front" || tmpdirection == "back")
3545 sbs->GetFloor(ServicedFloors[i])->AddWall("Floor Sign", texture.c_str(), 0, x - (width / 2), z, x + (width / 2), z, height, height, voffset, voffset, 1, 1, false);
3547 sbs->GetFloor(ServicedFloors[i])->AddWall("Floor Sign", texture.c_str(), 0, x, z - (width / 2), x, z + (width / 2), height, height, voffset, voffset, 1, 1, false);
3551 sbs->SetAutoSize(autosize_x, autosize_y);
3555 void Elevator::SetCallButtons(int floor, bool direction, bool value)
3557 //sets light status of all associated call buttons on the specified floor
3558 //for direction, true is up and false is down
3560 //get call buttons associated with this elevator
3562 Report("SetCallButtons: getting associated call buttons");
3564 std::vector<int> buttons = sbs->GetFloor(floor)->GetCallButtons(Number);
3566 for (int i = 0; i < (int)buttons.size(); i++)
3568 CallButton *button = 0;
3569 if ((int)sbs->GetFloor(floor)->CallButtonArray.size() > buttons[i])
3570 button = sbs->GetFloor(floor)->CallButtonArray[buttons[i]];
3573 if (direction == true)
3574 button->UpLight(value);
3576 button->DownLight(value);
3582 bool Elevator::IsIdle()
3584 //return true if elevator is idle (not moving, doors are closed (unless in a peak mode) and not moving)
3585 if (MoveElevator == false && (AreDoorsOpen() == false || UpPeak == true || DownPeak == true) && CheckOpenDoor() == false && Running == true)
3591 void Elevator::ResetQueue(bool up, bool down)
3597 Report("QueueReset: resetting up queue");
3603 Report("QueueReset: resetting down queue");
3607 //turn off button lights
3609 Report("QueueReset: turning off button lights for queue reset");
3610 for (int i = 0; i < (int)ServicedFloors.size(); i++)
3612 for (int j = 0; j < (int)PanelArray.size(); j++)
3613 PanelArray[j]->ChangeLight(ServicedFloors[i], false);
3617 void Elevator::SetBeepSound(const char *filename)
3619 //set sound used for floor beeps
3621 Report("setting beep sound");
3622 BeepSound = filename;
3623 TrimString(BeepSound);
3624 UseFloorBeeps = true;
3627 void Elevator::SetFloorSound(const char *prefix)
3629 //set prefix of floor sound
3631 Report("setting floor sound");
3632 FloorSound = prefix;
3633 TrimString(FloorSound);
3634 UseFloorSounds = true;
3637 void Elevator::SetMessageSound(bool direction, const char *filename)
3639 //if direction is true, set up message sound; otherwise set down message sound
3641 if (direction == true)
3644 Report("setting up message sound");
3645 UpMessageSound = filename;
3646 TrimString(UpMessageSound);
3651 Report("setting down message sound");
3652 DownMessageSound = filename;
3653 TrimString(DownMessageSound);
3655 UseMessageSounds = true;
3658 Object* Elevator::AddSound(const char *name, const char *filename, Ogre::Vector3 position, int volume, int speed, float min_distance, float max_distance, float dir_radiation, Ogre::Vector3 direction)
3660 //create a looping sound object
3661 sounds.resize(sounds.size() + 1);
3662 Sound *sound = sounds[sounds.size() - 1];
3663 sound = new Sound(this->object, name, false);
3665 //set parameters and play sound
3666 sound->PositionOffset = position;
3667 sound->SetPosition(Origin + position);
3668 sound->SetDirection(direction);
3669 sound->SetVolume(volume);
3670 sound->SetSpeed(speed);
3671 sound->SetDistances(min_distance, max_distance);
3672 sound->SetDirection(direction);
3673 sound->SetDirectionalRadiation(dir_radiation);
3674 sound->Load(filename);
3678 return sound->object;
3681 void Elevator::DeleteActiveRoute()
3683 if (Running == false)
3685 Report("Elevator not running");
3689 //deletes the active route
3691 Report("deleting active route");
3692 DeleteRoute(ActiveCallFloor, ActiveCallDirection);
3693 ActiveCallFloor = 0;
3694 ActiveCallDirection = 0;
3697 bool Elevator::IsQueueActive()
3699 if (QueuePositionDirection != 0)
3704 bool Elevator::BeyondDecelMarker(int direction, float destination)
3706 //return true if elevator is beyond the deceleration marker for the specified direction
3707 //directions are 1 for up, -1 for down
3711 if (((GetPosition().y + (ElevatorRate * sbs->delta)) > (destination - StoppingDistance)))
3714 if (direction == -1)
3716 if (((GetPosition().y - (ElevatorRate * sbs->delta)) < (destination + StoppingDistance)))
3722 void Elevator::Report(std::string message)
3724 //general reporting function
3725 sbs->Report("Elevator " + std::string(_itoa(Number, intbuffer, 10)) + ": " + message);
3729 bool Elevator::ReportError(std::string message)
3731 //general reporting function
3732 return sbs->ReportError("Elevator " + std::string(_itoa(Number, intbuffer, 10)) + ": " + message);
3735 Object* Elevator::AddDoorComponent(int number, const char *name, const char *texture, const char *sidetexture, float thickness, const char *direction, float OpenSpeed, float CloseSpeed, float x1, float z1, float x2, float z2, float height, float voffset, float tw, float th, float side_tw, float side_th)
3737 //adds an elevator door component to the specified door at a relative central position (off of elevator origin)
3739 if (GetDoor(number))
3740 return GetDoor(number)->AddDoorComponent(name, texture, sidetexture, thickness, direction, OpenSpeed, CloseSpeed, x1, z1, x2, z2, height, voffset, tw, th, side_tw, side_th);
3742 Report("Invalid door " + std::string(_itoa(number, intbuffer, 10)));
3746 Object* Elevator::AddShaftDoorComponent(int number, int floor, const char *name, const char *texture, const char *sidetexture, float thickness, const char *direction, float OpenSpeed, float CloseSpeed, float x1, float z1, float x2, float z2, float height, float voffset, float tw, float th, float side_tw, float side_th)
3748 //adds a single elevator shaft door component on the specified floor
3751 for (int i = 0; i < (int)ServicedFloors.size(); i++)
3753 if (ServicedFloors[i] == floor)
3756 if (index != -1 && GetDoor(number))
3757 return GetDoor(number)->AddShaftDoorComponent(floor, name, texture, sidetexture, thickness, direction, OpenSpeed, CloseSpeed, x1, z1, x2, z2, height, voffset, tw, th, side_tw, side_th);
3762 void Elevator::AddShaftDoorsComponent(int number, const char *name, const char *texture, const char *sidetexture, float thickness, const char *direction, float OpenSpeed, float CloseSpeed, float x1, float z1, float x2, float z2, float height, float voffset, float tw, float th, float side_tw, float side_th)
3764 //adds shaft's elevator door components specified at a relative central position (off of elevator origin)
3766 if (GetDoor(number))
3767 GetDoor(number)->AddShaftDoorsComponent(name, texture, sidetexture, thickness, direction, OpenSpeed, CloseSpeed, x1, z1, x2, z2, height, voffset, tw, th, side_tw, side_th);
3769 Report("Invalid door " + std::string(_itoa(number, intbuffer, 10)));
3772 Object* Elevator::FinishDoors(int number)
3774 //finishes elevator door
3775 if (GetDoor(number))
3776 return GetDoor(number)->FinishDoors();
3778 Report("Invalid door " + std::string(_itoa(number, intbuffer, 10)));
3782 Object* Elevator::FinishShaftDoor(int number, int floor)
3784 //finishes a single shaft door
3787 for (int i = 0; i < (int)ServicedFloors.size(); i++)
3789 if (ServicedFloors[i] == floor)
3792 if (index != -1 && GetDoor(number))
3793 return GetDoor(number)->FinishShaftDoor(floor);
3798 bool Elevator::FinishShaftDoors(int number)
3800 //finishes all shaft doors
3801 if (GetDoor(number))
3802 return GetDoor(number)->FinishShaftDoors();
3804 ReportError("Invalid door " + std::string(_itoa(number, intbuffer, 10)));
3808 void Elevator::Timer::Notify()
3810 if (elevator->IsRunning() == false)
3813 SBS_PROFILE("Elevator::Timer::Notify");
3818 if (elevator->ParkingDelay > 0 && elevator->IsIdle() == true)
3820 int floor = elevator->GetFloor();
3821 if (elevator->ParkingFloor > floor)
3823 elevator->AddRoute(elevator->ParkingFloor, 1, false);
3824 elevator->Parking = true;
3826 else if (elevator->ParkingFloor < floor)
3828 elevator->AddRoute(elevator->ParkingFloor, -1, false);
3829 elevator->Parking = true;
3834 else if (type == 1 && elevator->RandomActivity == true)
3838 RandomGen rnd_main(time(0) + elevator->Number);
3839 RandomGen rnd_floor(sbs->GetRunTime() + elevator->Number);
3843 //get call probability
3844 if (elevator->RandomProbability > 1)
3845 num = rnd_main.Get(elevator->RandomProbability - 1);
3850 int index = rnd_floor.Get(elevator->ServicedFloors.size());
3851 floor = elevator->ServicedFloors[index];
3853 //if probability number matched, press selected floor button
3854 if (num == 0 && elevator->IsQueued(floor) == false && floor != elevator->GetFloor())
3855 elevator->SelectFloor(floor);
3859 //arrival and departure timers
3860 elevator->WaitForTimer = false;
3864 ButtonPanel* Elevator::GetPanel(int index)
3866 //get a button panel object
3868 if (index > (int)PanelArray.size() || index < 1)
3871 return PanelArray[index - 1];
3874 int Elevator::GetRandomLobby()
3876 //return random lobby floor value
3880 void Elevator::SetRandomLobby(int floor)
3882 //set random lobby floor
3883 RandomLobby = floor;
3884 RandomLobbySet = true;
3887 void Elevator::SelectFloor(int floor)
3889 //press a floor button
3891 if (Running == false)
3893 Report("Elevator not running");
3899 if (PanelArray.size() > 0)
3901 for (int i = 0; i < (int)PanelArray.size(); i++)
3903 index = PanelArray[i]->GetFloorButtonIndex(floor);
3906 PanelArray[i]->Press(index);
3913 bool Elevator::IsQueued(int floor)
3915 //return true if the given floor is in either queue
3918 for (int i = 0; i < (int)UpQueue.size(); i++)
3920 if (UpQueue[i] == floor)
3927 for (int i = 0; i < (int)DownQueue.size(); i++)
3929 if (DownQueue[i] == floor)
3937 void Elevator::HoldDoors(int number)
3939 //hold specified door, or all if "0" is given
3952 for (int i = start; i <= end; i++)
3957 Report("Invalid door " + std::string(_itoa(i, intbuffer, 10)));
3961 Object* Elevator::AddDoor(const char *open_sound, const char *close_sound, bool open_state, const char *texture, float thickness, int direction, float speed, float CenterX, float CenterZ, float width, float height, float voffset, float tw, float th)
3963 //interface to the SBS AddDoor function
3965 if (direction > 8 || direction < 1)
3967 ReportError("Door direction out of range");
3971 float x1, z1, x2, z2;
3972 //set up coordinates
3977 z1 = CenterZ - (width / 2);
3978 z2 = CenterZ + (width / 2);
3982 x1 = CenterX - (width / 2);
3983 x2 = CenterX + (width / 2);
3989 /*if (direction < 5)
3990 CutAll(Ogre::Vector3(x1 - 1, GetBase(true) + voffset, z1), Ogre::Vector3(x2 + 1, GetBase(true) + voffset + height, z2), true, false);
3992 CutAll(Ogre::Vector3(x1, GetBase(true) + voffset, z1 - 1), Ogre::Vector3(x2, GetBase(true) + voffset + height, z2 + 1), true, false);
3995 StdDoorArray.resize(StdDoorArray.size() + 1);
3996 std::string elevnum = _itoa(Number, intbuffer, 10);
3997 std::string num = _itoa((int)StdDoorArray.size() - 1, intbuffer, 10);
3998 StdDoorArray[StdDoorArray.size() - 1] = new Door(this->object, std::string("Elevator " + elevnum + ":Door " + num).c_str(), open_sound, close_sound, open_state, texture, thickness, direction, speed, GetPosition().x + CenterX, GetPosition().z + CenterZ, width, height, voffset + GetPosition().y, tw, th);
3999 return StdDoorArray[StdDoorArray.size() - 1]->object;
4002 void Elevator::OpenDoor(int number)
4005 if (number < (int)StdDoorArray.size())
4007 if (StdDoorArray[number])
4008 StdDoorArray[number]->Open();
4011 Report("Invalid door " + std::string(_itoa(number, intbuffer, 10)));
4014 void Elevator::CloseDoor(int number)
4017 if (number < (int)StdDoorArray.size())
4019 if (StdDoorArray[number])
4020 StdDoorArray[number]->Close();
4023 Report("Invalid door " + std::string(_itoa(number, intbuffer, 10)));
4026 bool Elevator::IsDoorOpen(int number)
4028 //check to see if door is open
4029 if (number < (int)StdDoorArray.size())
4031 if (StdDoorArray[number])
4032 return StdDoorArray[number]->IsOpen();
4035 Report("Invalid door " + std::string(_itoa(number, intbuffer, 10)));
4039 bool Elevator::IsDoorMoving(int number)
4041 //check to see if door is moving
4042 if (number < (int)StdDoorArray.size())
4044 if (StdDoorArray[number])
4045 return StdDoorArray[number]->IsMoving;
4048 Report("Invalid door " + std::string(_itoa(number, intbuffer, 10)));
4052 void Elevator::RemovePanel(ButtonPanel* panel)
4054 //remove a button panel reference (does not delete the object itself)
4055 for (int i = 0; i < (int)PanelArray.size(); i++)
4057 if (PanelArray[i] == panel)
4058 PanelArray.erase(PanelArray.begin() + i);
4062 void Elevator::RemoveDirectionalIndicator(DirectionalIndicator* indicator)
4064 //remove a directional indicator reference (does not delete the object itself)
4065 for (int i = 0; i < (int)DirIndicatorArray.size(); i++)
4067 if (DirIndicatorArray[i] == indicator)
4068 DirIndicatorArray.erase(DirIndicatorArray.begin() + i);
4072 void Elevator::RemoveElevatorDoor(ElevatorDoor* door)
4074 //remove an elevator door reference (does not delete the object itself)
4075 for (int i = 0; i < (int)DoorArray.size(); i++)
4077 if (DoorArray[i] == door)
4078 DoorArray.erase(DoorArray.begin() + i);
4082 void Elevator::RemoveFloorIndicator(FloorIndicator* indicator)
4084 //remove a floor indicator reference (does not delete the object itself)
4085 for (int i = 0; i < (int)FloorIndicatorArray.size(); i++)
4087 if (FloorIndicatorArray[i] == indicator)
4088 FloorIndicatorArray.erase(FloorIndicatorArray.begin() + i);
4092 void Elevator::RemoveDoor(Door* door)
4094 //remove a door reference (does not delete the object itself)
4095 for (int i = 0; i < (int)StdDoorArray.size(); i++)
4097 if (StdDoorArray[i] == door)
4098 StdDoorArray.erase(StdDoorArray.begin() + i);
4102 void Elevator::RemoveSound(Sound *sound)
4104 //remove a sound reference (does not delete the object itself)
4105 for (int i = 0; i < (int)sounds.size(); i++)
4107 if (sounds[i] == sound)
4108 sounds.erase(sounds.begin() + i);
4112 void Elevator::NotifyArrival(int floor)
4114 //notify on elevator arrival (play chime and turn on related directional indicator lantern)
4116 bool LightDirection = GetArrivalDirection(floor); //true for up, false for down
4118 //play chime sound and change indicator
4119 if (LightDirection == true)
4121 Chime(0, floor, true);
4122 sbs->GetFloor(floor)->SetDirectionalIndicators(Number, true, false);
4123 SetDirectionalIndicators(true, false);
4127 Chime(0, floor, false);
4128 sbs->GetFloor(floor)->SetDirectionalIndicators(Number, false, true);
4129 SetDirectionalIndicators(false, true);
4135 bool Elevator::GetArrivalDirection(int floor)
4137 //determine if the directional lantern should show up or down on arrival to the specified floor
4139 bool LightDirection = false; //true for up, false for down
4141 if (floor == GetTopFloor())
4142 LightDirection = false; //turn on down light if on top floor
4143 else if (floor == GetBottomFloor())
4144 LightDirection = true; //turn on up light if on bottom floor
4145 else if (QueuePositionDirection == 1)
4146 LightDirection = true; //turn on up light if queue direction is up
4147 else if (QueuePositionDirection == -1)
4148 LightDirection = false; //turn on down light if queue direction is down
4150 return LightDirection;
4153 void Elevator::SetRunState(bool value)
4155 //set elevator run state (true for run, false for stop)
4157 if (Running == value)
4160 if (value == false && IsMoving == true)
4162 if (InspectionService == true)
4169 Report("Elevator stopped");
4171 Report("Elevator running");
4176 bool Elevator::IsRunning()
4178 //return elevator running state
4182 bool Elevator::PlayFloorBeep()
4184 //play floor beep sound
4186 if (BeepSound == "" || UseFloorBeeps == false)
4190 Report("playing floor beep sound");
4192 std::string newsound = BeepSound;
4193 //change the asterisk into the current floor number
4194 ReplaceAll(newsound, "*", _itoa(GetFloor(), intbuffer, 10));
4195 TrimString(newsound);
4197 floorbeep->Load(newsound.c_str());
4198 floorbeep->Loop(false);
4203 bool Elevator::PlayFloorSound()
4207 if (FloorSound == "" || UseFloorSounds == false)
4211 Report("playing floor sound");
4213 std::string newsound = FloorSound;
4214 //change the asterisk into the current floor number
4215 ReplaceAll(newsound, "*", _itoa(GotoFloor, intbuffer, 10));
4216 TrimString(newsound);
4218 floorsound->Load(newsound.c_str());
4219 floorsound->Loop(false);
4224 bool Elevator::PlayMessageSound(bool direction)
4226 //play message sound
4227 //if direction is true, play up sound; otherwise play down sound
4229 if (UseMessageSounds == false)
4231 if (direction == true && UpMessageSound == "")
4233 if (direction == false && DownMessageSound == "")
4236 std::string newsound;
4238 if (direction == true)
4241 Report("playing up message sound");
4243 newsound = UpMessageSound;
4248 Report("playing down message sound");
4250 newsound = DownMessageSound;
4253 //change the asterisk into the current floor number
4254 ReplaceAll(newsound, "*", _itoa(GetFloor(), intbuffer, 10));
4255 TrimString(newsound);
4257 messagesnd->Load(newsound.c_str());
4258 messagesnd->Loop(false);
4263 bool Elevator::DoorExists(int number)
4265 //check if the specified door exists
4266 //if number is 0, return true if any door exists
4269 return (GetDoor(number) > 0);
4273 for (int i = 0; i < (int)DoorArray.size(); i++)
4282 bool Elevator::IsNudgeModeActive(int number)
4284 //checks doors and returns true if any (or the specified door) have nudge mode active
4286 if (number > 0 && number < (int)DoorArray.size())
4288 if (DoorArray[number])
4289 return DoorArray[number]->GetNudgeStatus();
4291 else if (number == 0)
4293 for (int i = 0; i < (int)DoorArray.size(); i++)
4295 if (DoorArray[number]->GetNudgeStatus() == true)
4302 void Elevator::EnableNudgeMode(bool value, int number)
4304 //enables nudge mode on all doors or the specified door
4306 if (number > 0 && number < (int)DoorArray.size())
4308 if (DoorArray[number])
4309 DoorArray[number]->EnableNudgeMode(value);
4311 else if (number == 0)
4313 for (int i = 0; i < (int)DoorArray.size(); i++)
4314 DoorArray[number]->EnableNudgeMode(value);
4318 Object* Elevator::AddLight(const char *name, int type, Ogre::Vector3 position, Ogre::Vector3 direction, float color_r, float color_g, float color_b, float spec_color_r, float spec_color_g, float spec_color_b, float spot_inner_angle, float spot_outer_angle, float spot_falloff, float att_range, float att_constant, float att_linear, float att_quadratic)
4320 //add a global light
4322 Light* light = new Light(name, type, position + Origin, direction, color_r, color_g, color_b, spec_color_r, spec_color_g, spec_color_b, spot_inner_angle, spot_outer_angle, spot_falloff, att_range, att_constant, att_linear, att_quadratic);
4323 lights.push_back(light);
4324 return light->object;
4327 void Elevator::MoveLights(Ogre::Vector3 position, bool relative_x, bool relative_y, bool relative_z)
4330 for (int i = 0; i < (int)lights.size(); i++)
4331 lights[i]->Move(position, relative_x, relative_y, relative_z);
4334 Object* Elevator::AddModel(const char *name, const char *filename, Ogre::Vector3 position, Ogre::Vector3 rotation, float max_render_distance, float scale_multiplier, bool enable_physics, float restitution, float friction, float mass)
4337 Model* model = new Model(name, filename, position + Origin, rotation, max_render_distance, scale_multiplier, enable_physics, restitution, friction, mass);
4338 if (model->load_error == true)
4343 ModelArray.push_back(model);
4344 return model->object;
4347 void Elevator::MoveModels(Ogre::Vector3 position, bool relative_x, bool relative_y, bool relative_z)
4350 for (int i = 0; i < (int)ModelArray.size(); i++)
4351 ModelArray[i]->Move(position, relative_x, relative_y, relative_z);
4354 void Elevator::AddDisplayFloor(int floor)
4356 //add a floor to the display floors list
4357 DisplayFloors.push_back(floor);