Skyscraper 2.0
escalator.cpp
Go to the documentation of this file.
1/*
2 Scalable Building Simulator - Escalator Object
3 The Skyscraper Project - Version 2.0
4 Copyright (C)2004-2024 Ryan Thoryk
5 https://www.skyscrapersim.net
6 https://sourceforge.net/projects/skyscraper/
7 Contact - ryan@skyscrapersim.net
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22*/
23
24#include "globals.h"
25#include "sbs.h"
26#include "camera.h"
27#include "mesh.h"
28#include "floor.h"
29#include "sound.h"
30#include "texture.h"
31#include "profiler.h"
32#include "dynamicmesh.h"
33#include "step.h"
34#include "timer.h"
35#include "random.h"
36#include "escalator.h"
37
38namespace SBS {
39
40//escalator malfunction timer
42{
43public:
45 Timer(const std::string &name, Escalator *parent) : TimerObject(parent, name)
46 {
47 escalator = parent;
48 }
49 virtual void Notify();
50};
51
52Escalator::Escalator(Object *parent, const std::string &name, int run, Real speed, const std::string &sound_file, const std::string &riser_texture, const std::string &tread_texture, const std::string &direction, Real CenterX, Real CenterZ, Real width, Real risersize, Real treadsize, int num_steps, Real voffset, Real tw, Real th) : Object(parent)
53{
54 //create a new escalator object
55 //run is either 1 for forward motion, -1 for reverse motion, 0 for stop
56 //direction is where the step base is - front, back, left, or right.
57
58 std::string Name;
59
60 //set up SBS object
61 SetValues("Escalator", "", false);
62
63 Floor *floor = dynamic_cast<Floor*>(parent);
64 if (floor)
65 Name = "Floor" + ToString(floor->Number) + ":" + name;
66 else
67 Name = name;
69
70 is_enabled = true;
71 SetRun(run);
72 Speed = speed;
73 start = Vector3::ZERO;
74 end = Vector3::ZERO;
76
77 //register with engine
79
80 RandomProbability = sbs->GetConfigInt("Skyscraper.SBS.Escalator.RandomProbability", 20);
81 RandomFrequency = sbs->GetConfigFloat("Skyscraper.SBS.Escalator.RandomFrequency", 5);
82
83 //initialize random number generators
84 rnd_time = new RandomGen((unsigned int)(time(0) + GetNumber()));
85 rnd_type = new RandomGen((unsigned int)(time(0) + GetNumber() + 1));
86
87 //create sound object
88 sound = new Sound(this, name, true);
89 sound->Load(sound_file);
90
91 //move object
92 Move(CenterX, voffset, CenterZ);
93
94 //create step meshes
95 for (int i = 0; i < num_steps; i++)
96 {
97 Step *mesh = new Step(this, "Step " + ToString(i + 1), 0, 100);
98 Steps.emplace_back(mesh);
99 }
100
101 //create malfunction timer
102 malfunction_timer = new Timer("Malfunction Timer", this);
103
104 //create steps
105 CreateSteps(riser_texture, tread_texture, direction, width, risersize, treadsize, tw, th);
106}
107
109{
110 if (sound)
111 {
112 sound->parent_deleting = true;
113 delete sound;
114 }
115 sound = 0;
116
118 {
120 delete malfunction_timer;
121 }
123
124 //delete random number generators
125 if (rnd_time)
126 delete rnd_time;
127 rnd_time = 0;
128
129 if (rnd_type)
130 delete rnd_type;
131 rnd_type = 0;
132
133 //remove step meshes
134 for (size_t i = 0; i < Steps.size(); i++)
135 {
136 if (Steps[i])
137 {
138 Steps[i]->parent_deleting = true;
139 delete Steps[i];
140 }
141 Steps[i] = 0;
142 }
143
144 //unregister from parent
145 if (sbs->FastDelete == false)
146 {
148
149 //unregister from parent
150 if (parent_deleting == false)
151 {
152 std::string type = GetParent()->GetType();
153
154 if (type == "Floor")
155 static_cast<Floor*>(GetParent())->RemoveEscalator(this);
156 }
157 }
158}
159
160void Escalator::Enabled(bool value)
161{
162 //enable or disable escalator
163
164 if (is_enabled == value)
165 return;
166
167 EnableLoop(value);
168
169 for (size_t i = 0; i < Steps.size(); i++)
170 Steps[i]->Enabled(value);
171
172 if (value == false && sound->IsPlaying() == true)
173 sound->Stop();
174
175 is_enabled = value;
176}
177
178void Escalator::SetRun(int value)
179{
180 if (value == 0)
181 {
182 for (size_t i = 0; i < Steps.size(); i++)
183 {
184 Steps[i]->vector = Vector3::ZERO;
185 Steps[i]->speed = 0;
186 }
187 }
188
189 Run = value;
190}
191
192void Escalator::Report(const std::string &message)
193{
194 //general reporting function
195 Object::Report("Escalator " + GetName() + ": " + message);
196}
197
198bool Escalator::ReportError(const std::string &message)
199{
200 //general reporting function
201 return Object::ReportError("Escalator " + GetName() + ": " + message);
202}
203
205{
206 //run loop
207
208 SBS_PROFILE("Escalator::Loop");
209
210 //only run if power is enabled
211 if (sbs->GetPower() == false)
212 {
213 sound->Stop();
214 return;
215 }
216
217 if (!IsEnabled() || Run == 0)
218 {
219 if (sound->IsPlaying() == true)
220 sound->Stop();
221 return;
222 }
223
224 if (sound->IsPlaying() == false)
225 {
226 sound->SetLoopState(true);
227 sound->Play();
228 }
229
230 MoveSteps();
231}
232
233void Escalator::CreateSteps(const std::string &riser_texture, const std::string &tread_texture, const std::string &direction, Real width, Real risersize, Real treadsize, Real tw, Real th)
234{
235 //create steps
236
237 std::string Name = GetName();
239 Direction = direction;
240 this->treadsize = treadsize;
241 this->risersize = risersize;
242 SetCase(Direction, false);
243 int num_steps = (int)Steps.size();
244
245 SetCase(Direction, false);
247
249 if (Direction == "right" || Direction == "back")
250 sbs->SetWallOrientation("right");
251 if (Direction == "left" || Direction == "front")
252 sbs->SetWallOrientation("left");
253
254 for (int i = 1; i <= num_steps; i++)
255 {
256 Real pos = 0;
257 std::string base = Name + ":" + ToString(i);
258
259 //create wall object
260 Wall *wall = Steps[i - 1]->CreateWallObject(base);
261
262 Real thickness = treadsize;
263
264 if (Direction == "right")
265 {
266 pos = ((treadsize * num_steps + 1) / 2) - (treadsize * i);
267 sbs->DrawWalls(true, true, true, true, false, true);
268 sbs->AddWallMain(wall, base + "-riser", riser_texture, thickness, treadsize, -(width / 2), treadsize, width / 2, risersize, risersize, 0, 0, tw, th, true);
269
270 sbs->DrawWalls(false, true, false, false, false, false);
271 sbs->AddFloorMain(wall, base + "-tread", tread_texture, 0, 0, -(width / 2), treadsize, width / 2, risersize, risersize, false, false, tw, th, true);
272
273 if (i < (buffer_zone_steps + 1))
274 Steps[i - 1]->Move(Vector3(pos, -risersize, 0));
275 else if (i > num_steps - buffer_zone_steps)
276 Steps[i - 1]->Move(Vector3(pos, risersize * (i - (((buffer_zone_steps * 2) + 1) - (num_steps - i))), 0));
277 else
278 Steps[i - 1]->Move(Vector3(pos, risersize * (i - (buffer_zone_steps * 2)), 0));
279 Steps[i - 1]->vector = Vector3::ZERO;
280 Steps[1 - 1]->speed = 0;
281
282 if (i == 1)
283 start = Steps[i - 1]->GetPosition();
284 if (i == num_steps)
285 end = Steps[i - 1]->GetPosition();
286 Steps[i - 1]->start = Steps[i - 1]->GetPosition();
287 }
288 if (Direction == "left")
289 {
290 pos = -((treadsize * num_steps + 1) / 2) + (treadsize * i);
291 sbs->DrawWalls(true, true, true, true, false, true);
292 sbs->AddWallMain(wall, base + "-riser", riser_texture, thickness, -treadsize, width / 2, -treadsize, -(width / 2), risersize, risersize, 0, 0, tw, th, true);
293
294 sbs->DrawWalls(false, true, false, false, false, false);
295 sbs->AddFloorMain(wall, base + "-tread", tread_texture, 0, -treadsize, -(width / 2), 0, width / 2, risersize, risersize, false, false, tw, th, true);
296
297 if (i < (buffer_zone_steps + 1))
298 Steps[i - 1]->Move(Vector3(pos, -risersize, 0));
299 else if (i > num_steps - buffer_zone_steps)
300 Steps[i - 1]->Move(Vector3(pos, risersize * (i - (((buffer_zone_steps * 2) + 1) - (num_steps - i))), 0));
301 else
302 Steps[i - 1]->Move(Vector3(pos, risersize * (i - (buffer_zone_steps * 2)), 0));
303 Steps[i - 1]->vector = Vector3::ZERO;
304 Steps[1 - 1]->speed = 0;
305
306 if (i == 1)
307 start = Steps[i - 1]->GetPosition();
308 if (i == num_steps)
309 end = Steps[i - 1]->GetPosition();
310 Steps[i - 1]->start = Steps[i - 1]->GetPosition();
311 }
312 if (Direction == "back")
313 {
314 pos = ((treadsize * num_steps + 1) / 2) - (treadsize * i);
315 sbs->DrawWalls(true, true, true, true, false, true);
316 sbs->AddWallMain(wall, base + "-riser", riser_texture, thickness, width / 2, treadsize, -(width / 2), treadsize, risersize, risersize, 0, 0, tw, th, true);
317
318 sbs->DrawWalls(false, true, false, false, false, false);
319 sbs->AddFloorMain(wall, base + "-tread", tread_texture, 0, -(width / 2), 0, width / 2, treadsize, risersize, risersize, false, false, tw, th, true);
320
321 if (i < (buffer_zone_steps + 1))
322 Steps[i - 1]->Move(Vector3(0, -risersize, pos));
323 else if (i > num_steps - buffer_zone_steps)
324 Steps[i - 1]->Move(Vector3(0, risersize * (i - (((buffer_zone_steps * 2) + 1) - (num_steps - i))), pos));
325 else
326 Steps[i - 1]->Move(Vector3(0, risersize * (i - (buffer_zone_steps * 2)), pos));
327 Steps[i - 1]->vector = Vector3::ZERO;
328 Steps[1 - 1]->speed = 0;
329
330 if (i == 1)
331 start = Steps[i - 1]->GetPosition();
332 if (i == num_steps)
333 end = Steps[i - 1]->GetPosition();
334 Steps[i - 1]->start = Steps[i - 1]->GetPosition();
335 }
336 if (Direction == "front")
337 {
338 pos = -((treadsize * num_steps + 1) / 2) + (treadsize * i);
339 sbs->DrawWalls(true, true, true, true, false, true);
340 sbs->AddWallMain(wall, base + "-riser", riser_texture, thickness, -(width / 2), -treadsize, width / 2, -treadsize, risersize, risersize, 0, 0, tw, th, true);
341
342 sbs->DrawWalls(false, true, false, false, false, false);
343 sbs->AddFloorMain(wall, base + "-tread", tread_texture, 0, -(width / 2), -treadsize, width / 2, 0, risersize, risersize, false, false, tw, th, true);
344
345 if (i < (buffer_zone_steps + 1))
346 Steps[i - 1]->Move(Vector3(0, -risersize, pos));
347 else if (i > num_steps - buffer_zone_steps)
348 Steps[i - 1]->Move(Vector3(0, risersize * (i - (((buffer_zone_steps * 2) + 1) - (num_steps - i))), pos));
349 else
350 Steps[i - 1]->Move(Vector3(0, risersize * (i - (buffer_zone_steps * 2)), pos));
351 Steps[i - 1]->vector = Vector3::ZERO;
352 Steps[1 - 1]->speed = 0;
353
354 if (i == 1)
355 start = Steps[i - 1]->GetPosition();
356 if (i == num_steps)
357 end = Steps[i - 1]->GetPosition();
358 Steps[i - 1]->start = Steps[i - 1]->GetPosition();
359 }
360 }
361 sbs->ResetWalls(true);
363}
364
366{
367 if (GetPosition().distance(sbs->camera->GetPosition()) > 100)
368 return;
369
370 for (size_t i = 0; i < Steps.size(); i++)
371 {
372 if (Run == 1)
373 {
374 if (Direction == "right")
375 {
376 Real pos = Steps[i]->GetPosition().x;
377 if (pos < end.x - treadsize)
378 Steps[i]->SetPosition(start);
379 else if (pos >= start.x - (treadsize * 2) || pos <= end.x + treadsize)
380 Steps[i]->Move(Vector3(-Run, 0, 0), Speed * sbs->delta);
381 else if (pos > end.x + treadsize)
382 Steps[i]->Move(Vector3(-Run, Run * (risersize / treadsize), 0), Speed * sbs->delta);
383 }
384 if (Direction == "left")
385 {
386 Real pos = Steps[i]->GetPosition().x;
387 if (pos > end.x + treadsize)
388 Steps[i]->SetPosition(start);
389 else if (pos <= start.x + (treadsize * 2) || pos >= end.x - treadsize)
390 Steps[i]->Move(Vector3(Run, 0, 0), Speed * sbs->delta);
391 else if (pos < end.x - treadsize)
392 Steps[i]->Move(Vector3(Run, Run * (risersize / treadsize), 0), Speed * sbs->delta);
393 }
394 if (Direction == "back")
395 {
396 Real pos = Steps[i]->GetPosition().z;
397 if (pos < end.z - treadsize)
398 Steps[i]->SetPosition(start);
399 else if (pos >= start.z - (treadsize * 2) || pos <= end.z + treadsize)
400 Steps[i]->Move(Vector3(0, 0, -Run), Speed * sbs->delta);
401 else if (pos > end.z + treadsize)
402 Steps[i]->Move(Vector3(0, Run * (risersize / treadsize), -Run), Speed * sbs->delta);
403 }
404 if (Direction == "front")
405 {
406 Real pos = Steps[i]->GetPosition().z;
407 if (pos > end.z + treadsize)
408 Steps[i]->SetPosition(start);
409 else if (pos <= start.z + (treadsize * 2) || pos >= end.z - treadsize)
410 Steps[i]->Move(Vector3(0, 0, Run), Speed * sbs->delta);
411 else if (pos < end.z - treadsize)
412 Steps[i]->Move(Vector3(0, Run * (risersize / treadsize), Run), Speed * sbs->delta);
413 }
414 }
415 else if (Run == -1)
416 {
417 if (Direction == "right")
418 {
419 Real pos = Steps[i]->GetPosition().x;
420 if (pos > start.x)
421 Steps[i]->SetPosition(Vector3(end.x - treadsize, end.y, end.z));
422 else if (pos <= end.x + treadsize || pos >= start.x - (treadsize * 2))
423 Steps[i]->Move(Vector3(-Run, 0, 0), Speed * sbs->delta);
424 else if (pos < start.x - treadsize)
425 Steps[i]->Move(Vector3(-Run, Run * (risersize / treadsize), 0), Speed * sbs->delta);
426 }
427 if (Direction == "left")
428 {
429 Real pos = Steps[i]->GetPosition().x;
430 if (pos < start.x)
431 Steps[i]->SetPosition(Vector3(end.x + treadsize, end.y, end.z));
432 else if (pos >= end.x - treadsize || pos <= start.x + (treadsize * 2))
433 Steps[i]->Move(Vector3(Run, 0, 0), Speed * sbs->delta);
434 else if (pos > start.x + treadsize)
435 Steps[i]->Move(Vector3(Run, Run * (risersize / treadsize), 0), Speed * sbs->delta);
436 }
437 if (Direction == "back")
438 {
439 Real pos = Steps[i]->GetPosition().z;
440 if (pos > start.z)
441 Steps[i]->SetPosition(Vector3(end.x, end.y, end.z - treadsize));
442 else if (pos <= end.z + treadsize || pos >= start.z - (treadsize * 2))
443 Steps[i]->Move(Vector3(0, 0, -Run), Speed * sbs->delta);
444 else if (pos < start.z - treadsize)
445 Steps[i]->Move(Vector3(0, Run * (risersize / treadsize), -Run), Speed * sbs->delta);
446 }
447 if (Direction == "front")
448 {
449 Real pos = Steps[i]->GetPosition().z;
450 if (pos < start.z)
451 Steps[i]->SetPosition(Vector3(end.x, end.y, end.z + treadsize));
452 else if (pos >= end.z - treadsize || pos <= start.z + (treadsize * 2))
453 Steps[i]->Move(Vector3(0, 0, Run), Speed * sbs->delta);
454 else if (pos > start.z + treadsize)
455 Steps[i]->Move(Vector3(0, Run * (risersize / treadsize), Run), Speed * sbs->delta);
456 }
457 }
458 }
459}
460
461void Escalator::OnClick(Vector3 &position, bool shift, bool ctrl, bool alt, bool right)
462{
463 //cycle run stages if shift-click is performed
464
465 //only run if power is enabled
466 if (sbs->GetPower() == false)
467 return;
468
469 if (shift == true)
470 {
471 if (Run == 1)
472 {
473 Run = 0;
474 for (size_t i = 0; i < Steps.size(); i++)
475 {
476 Steps[i]->vector = Vector3::ZERO;
477 Steps[i]->speed = 0;
478 }
479 }
480 else if (Run == 0)
481 Run = -1;
482 else if (Run == -1)
483 Run = 1;
484 }
485}
486
488{
489 //reset escalator state
490
491 Run = 0;
492 for (size_t i = 0; i < Steps.size(); i++)
493 {
494 Steps[i]->SetPosition(Steps[i]->start);
495 }
496}
497
499{
500 if (escalator->GetRun() == 0)
501 return;
502
503 SBS_PROFILE("Escalator::Timer::Notify");
504
505 //only run if power is enabled
506 if (sbs->GetPower() == false)
507 return;
508
509 int result = (int)escalator->rnd_time->Get(escalator->RandomProbability - 1);
510 if (result == 0)
512}
513
515{
516 //enable random malfunctions on this escalator
517
519 return;
520
521 //only run if power is enabled
522 if (sbs->GetPower() == false)
523 return;
524
525 if (value == true)
526 {
527 Report("Enabling malfunctions");
528 malfunction_timer->Start(int(RandomFrequency) * 1000, false);
529 }
530 else
531 {
532 Report("Disabling malfunctions");
534 }
535}
536
538{
539 //elevator malfunction
540
541 Report("Malfunction");
542
543 //only run if power is enabled
544 if (sbs->GetPower() == false)
545 return;
546
547 int type = (int)rnd_type->Get(1);
548 if (type == 0)
549 {
550 //stop escalator
551 SetRun(0);
552 }
553 if (type == 1)
554 {
555 if (GetRun() == -1)
556 SetRun(1);
557 else
558 SetRun(-1);
559 }
560}
561
562}
Vector3 GetPosition(bool relative=false)
Definition camera.cpp:250
Timer(const std::string &name, Escalator *parent)
Definition escalator.cpp:45
Escalator * escalator
Definition escalator.cpp:44
virtual void Notify()
RandomGen * rnd_type
Definition escalator.h:65
Timer * malfunction_timer
Definition escalator.h:62
void OnClick(Vector3 &position, bool shift, bool ctrl, bool alt, bool right)
Vector3 start
Definition escalator.h:52
RandomGen * rnd_time
Definition escalator.h:65
std::string Direction
Definition escalator.h:53
bool ReportError(const std::string &message)
void EnableMalfunctions(bool value)
void Report(const std::string &message)
Vector3 end
Definition escalator.h:52
int RandomProbability
Definition escalator.h:63
Escalator(Object *parent, const std::string &name, int run, Real speed, const std::string &sound_file, const std::string &riser_texture, const std::string &tread_texture, const std::string &direction, Real CenterX, Real CenterZ, Real width, Real risersize, Real treadsize, int num_steps, Real voffset, Real tw, Real th)
Definition escalator.cpp:52
std::vector< Step * > Steps
Definition escalator.h:58
void Enabled(bool value)
bool IsEnabled()
Definition escalator.h:40
void CreateSteps(const std::string &riser_texture, const std::string &tread_texture, const std::string &direction, Real width, Real risersize, Real treadsize, Real tw, Real th)
int buffer_zone_steps
Definition escalator.h:56
Real RandomFrequency
Definition escalator.h:64
Sound * sound
Definition escalator.h:49
void SetRun(int value)
int Number
Definition floor.h:36
std::string Name
Definition object.h:52
const std::string & GetName()
Definition object.cpp:53
virtual bool ReportError(const std::string &message)
Definition object.cpp:84
Object * GetParent()
Definition object.cpp:42
virtual void Report(const std::string &message)
Definition object.cpp:78
void SetName(const std::string &name)
Definition object.cpp:72
bool parent_deleting
Definition object.h:64
virtual void Move(const Vector3 &vector, Real speed=1.0)
Definition object.cpp:253
virtual Vector3 GetPosition(bool relative=false)
Definition object.cpp:321
int GetNumber()
Definition object.cpp:183
void SetValues(const std::string &type, const std::string &name, bool is_permanent, bool is_movable=true)
Definition object.cpp:144
void EnableLoop(bool value)
Definition object.cpp:521
const std::string & GetType()
Definition object.cpp:177
float Get()
Definition random.cpp:135
void UnregisterEscalator(Escalator *escalator)
Definition sbs.cpp:4646
bool GetPower()
Definition sbs.cpp:4701
Real GetConfigFloat(const std::string &key, Real default_value)
Definition sbs.cpp:3249
bool AddWallMain(Wall *wallobject, const std::string &name, const std::string &texture, Real thickness, Real x1, Real z1, Real x2, Real z2, Real height_in1, Real height_in2, Real altitude1, Real altitude2, Real tw, Real th, bool autosize)
Definition sbs.cpp:690
void RegisterEscalator(Escalator *escalator)
Definition sbs.cpp:4640
void ResetWalls(bool ToDefaults=false)
Definition sbs.cpp:1854
bool FastDelete
Definition sbs.h:188
TextureManager * GetTextureManager()
Definition sbs.cpp:4558
Camera * camera
Definition sbs.h:160
int GetConfigInt(const std::string &key, int default_value)
Definition sbs.cpp:3232
Real delta
Definition sbs.h:134
bool SetWallOrientation(std::string direction)
Definition sbs.cpp:1781
void DrawWalls(bool MainN, bool MainP, bool SideN, bool SideP, bool Top, bool Bottom)
Definition sbs.cpp:1833
bool AddFloorMain(Wall *wallobject, const std::string &name, const std::string &texture, Real thickness, Real x1, Real z1, Real x2, Real z2, Real altitude1, Real altitude2, bool reverse_axis, bool texture_direction, Real tw, Real th, bool autosize, bool legacy_behavior=false)
Definition sbs.cpp:921
bool Load(const std::string &filename, bool force=false)
Definition sound.cpp:386
void Stop()
Definition sound.cpp:292
bool Play(bool reset=true)
Definition sound.cpp:321
void SetLoopState(bool value)
Definition sound.cpp:204
bool IsPlaying()
Definition sound.cpp:254
void ResetTextureMapping(bool todefaults=false)
Definition texture.cpp:1444
void Start(int milliseconds=-1, bool oneshot=false)
Definition timer.cpp:49
Ogre::Vector3 Vector3
Definition globals.h:58
Ogre::Real Real
Definition globals.h:57
void SetCase(std::string &string, bool uppercase)
Definition globals.cpp:172
std::string ToString(int number)
Definition globals.cpp:279
void TrimString(std::string &string)
Definition globals.cpp:188
#define SBS_PROFILE(name)
Definition profiler.h:131