Skyscraper 2.0
section.cpp
Go to the documentation of this file.
1/*
2 Skyscraper 2.0 Alpha - Script Processor - Script Section
3 Copyright (C)2003-2024 Ryan Thoryk
4 https://www.skyscrapersim.net
5 https://sourceforge.net/projects/skyscraper/
6 Contact - ryan@skyscrapersim.net
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21*/
22
23#include "globals.h"
24#include "sbs.h"
25#include "vm.h"
26#include "enginecontext.h"
27#include "hal.h"
28#include "floor.h"
29#include "elevator.h"
30#include "elevatorcar.h"
31#include "shaft.h"
32#include "stairs.h"
33#include "model.h"
34#include "random.h"
35#include "scriptproc.h"
36#include "section.h"
37
38using namespace SBS;
39
40namespace Skyscraper {
41
43{
44 this->parent = parent;
47 VM *vm = engine->GetVM();
48 warn_deprecated = vm->GetHAL()->GetConfigBool(vm->GetHAL()->configfile, "Skyscraper.Frontend.WarnDeprecated", false);
50}
51
52int ScriptProcessor::Section::SplitData(const std::string &string, int start, bool calc)
53{
54 //split data into separate strings starting at the "start" character
55 //delimeter is a comma ","
56 //returns the number of parameters found
57 //if calc is on, calc_skip can be used to specify an index that does not cooperate properly with calculations, such as filenames
58
59 std::string data = string;
60 std::string stringbuffer;
61
62 //verify length of input string
63 if ((int)data.size() < start)
64 return 0;
65
66 SplitString(tempdata, data.substr(start), ',');
67 if (calc == true)
68 {
69 for (size_t i = 0; i < tempdata.size(); i++)
70 {
71 stringbuffer = parent->Calc(tempdata[i]);
72 tempdata[i] = stringbuffer;
73 }
74 }
75 return (int)tempdata.size();
76}
77
78int ScriptProcessor::Section::SplitAfterEquals(const std::string &string, bool calc)
79{
80 //get and split data after equal sign
81 //returns -1 if equal sign not found
82 //returns 0 if no parameters found
83
84 std::string data = string;
85 int loc = data.find("=", 0);
86 if (loc < 0)
87 return -1;
88
89 std::string temp = data.substr(loc + 1);
90 TrimString(temp);
91
92 if (temp == "")
93 return 0;
94
95 SplitString(tempdata, temp, ',');
96 if (calc == true)
97 {
98 for (size_t i = 0; i < tempdata.size(); i++)
99 {
100 std::string buffer = parent->Calc(tempdata[i]);
101 tempdata[i] = buffer;
102 }
103 }
104 return (int)tempdata.size();
105}
106
107std::string ScriptProcessor::Section::GetAfterEquals(const std::string &string, bool &found_equals)
108{
109 //return data after equal sign
110
111 found_equals = false;
112
113 if (string.size() <= 1)
114 return "";
115
116 //find equals sign
117 int loc = string.find("=", 1);
118
119 if (loc < 0)
120 return "";
121
122 found_equals = true;
123
124 std::string temp = string.substr(loc + 1);
125 TrimString(temp);
126 return temp;
127}
128
129std::string ScriptProcessor::Section::GetBeforeEquals(const std::string &string, bool calc)
130{
131 //return data right before equal sign
132
133 if (string.size() <= 1)
134 return "";
135
136 //find equal sign
137 int equals = string.find("=", 1);
138
139 if (equals == -1)
140 return "";
141
142 std::string str = string.substr(0, equals);
143 TrimString(str);
144
145 //find space before equal sign
146 int loc = str.find_first_of(" ", 0);
147 int loc2 = -1;
148
149 //if a space is missing, find start of numeric characters
150 if (loc == -1)
151 {
152 for (int i = 0; i < (int)str.size(); i++)
153 {
154 if (IsNumeric(str[i]))
155 {
156 loc2 = i;
157 break;
158 }
159 }
160 }
161
162 std::string str2;
163
164 if (loc2 == -1)
165 str2 = str.substr(loc);
166 else
167 str2 = str.substr(loc2);
168 TrimString(str2);
169
170 if (calc == true)
171 return Calc(str2);
172
173 return str2;
174}
175
176bool ScriptProcessor::Section::GetRange(const std::string &string, int &start, int &end)
177{
178 //calculate range value, such as "1 - 3", and fill in the 'start' and 'end' values
179
180 if (string.find("-", 1) > 0)
181 {
182 //found a range marker
183 std::string str1 = string.substr(0, string.find("-", 1));
184 std::string str2 = string.substr(string.find("-", 1) + 1);
185 TrimString(str1);
186 TrimString(str2);
187 if (!IsNumeric(str1, start) || !IsNumeric(str2, end))
188 return ScriptError("Invalid value");
189 if (end < start)
190 {
191 int temp = start;
192 start = end;
193 end = temp;
194 }
195
196 return true;
197 }
198
199 return false;
200}
201
202int ScriptProcessor::Section::ScriptError(std::string message, bool warning)
203{
204 return parent->ScriptError(message, warning);
205}
206
208{
209 return parent->ScriptError();
210}
211
213{
214 return parent->ScriptWarning(message);
215}
216
217bool ScriptProcessor::Section::IfProc(const std::string &expression)
218{
219 //IF statement processor
220
221 int temp1;
222 std::string tmpcalc = expression;
223 std::string one;
224 std::string two;
225 int start, end;
226 bool check;
227
228 //first remove all whitespace from the string
229 ReplaceAll(tmpcalc, " ", "");
230
231 //first check for bad and/or character sets
232 if (int(tmpcalc.find("&&")) >= 0 || int(tmpcalc.find("||")) >= 0 || int(tmpcalc.find("==")) >= 0 || int(tmpcalc.find("!=")) >= 0)
233 {
234 ScriptError("Syntax error in IF operation: '" + tmpcalc + "' (might be nested)");
235 return false;
236 }
237
238 //find parenthesis
239 do
240 {
241 start = tmpcalc.find("(", 0);
242 if (start >= 0)
243 {
244 //find matching parenthesis
245 int match = 1;
246 int end = -1;
247 for (int i = start + 1; i < (int)tmpcalc.length(); i++)
248 {
249 char &tmpchar = tmpcalc.at(i);
250 if (tmpchar == '(')
251 match++;
252 if (tmpchar == ')')
253 match--;
254 if (match == 0)
255 {
256 end = i;
257 break;
258 }
259 }
260 if (end != -1)
261 {
262 //call function recursively
263 std::string newdata;
264 if (IfProc(tmpcalc.substr(start + 1, end - start - 1)) == true)
265 newdata = "true";
266 else
267 newdata = "false";
268 //construct new string
269 one = tmpcalc.substr(0, start);
270 if (end < (int)tmpcalc.length() - 1)
271 two = tmpcalc.substr(end + 1);
272 else
273 two = "";
274 tmpcalc = one + newdata + two;
275 }
276 else
277 {
278 ScriptError("Syntax error in IF operation: '" + tmpcalc + "' (might be nested)");
279 return false;
280 }
281 }
282 else
283 break;
284 } while (1 == 1);
285 //find number of operators and recurse if multiple found
286 int operators;
287 int operators2;
288 do
289 {
290 operators = 0;
291 operators2 = 0;
292 start = 0;
293 end = 0;
294 check = false;
295 for (int i = 1; i < (int)tmpcalc.length(); i++)
296 {
297 char &tmpchar = tmpcalc.at(i);
298 if (tmpchar == '=' || tmpchar == '!' || tmpchar == '<' || tmpchar == '>')
299 operators++;
300
301 if (tmpchar == '&' || tmpchar == '|')
302 {
303 check = true;
304 operators2++;
305 if (operators == 1 && operators2 == 2)
306 {
307 //handle 2 and/if operators
308 end = i;
309 start = 0;
310 operators = 2;
311 break;
312 }
313 if (operators == 1)
314 {
315 operators = 2;
316 end = i;
317 }
318 else if (operators == 0)
319 {
320 operators = 1;
321 start = i + 1;
322 end = (int)tmpcalc.length();
323 }
324 }
325 }
326 //return error if multiple standard operators are found, but no and/or operator (ex. if[5 = 5 = 5])
327 if (operators > 1 && check == false)
328 {
329 ScriptError("Syntax error in IF operation: '" + tmpcalc + "' (might be nested)");
330 return false;
331 }
332 if (operators > 1)
333 {
334 std::string newdata;
335 if (IfProc(tmpcalc.substr(start, end - start)) == true)
336 newdata = "true";
337 else
338 newdata = "false";
339 //construct new string
340 one = tmpcalc.substr(0, start);
341 two = tmpcalc.substr(end);
342 tmpcalc = one + newdata + two;
343 }
344 else
345 break;
346 } while (1 == 1);
347 //return value if none found
348 if (operators == 0)
349 return ToBool(tmpcalc);
350
351 //otherwise perform comparisons
352 temp1 = tmpcalc.find("=", 1);
353 if (temp1 > 0)
354 {
355 one = tmpcalc.substr(0, temp1);
356 two = tmpcalc.substr(temp1 + 1);
357 if (one == two)
358 return true;
359 else
360 return false;
361 }
362 temp1 = tmpcalc.find("!", 1);
363 if (temp1 > 0)
364 {
365 one = tmpcalc.substr(0, temp1);
366 two = tmpcalc.substr(temp1 + 1);
367 if (one != two)
368 return true;
369 else
370 return false;
371 }
372 temp1 = tmpcalc.find("<", 1);
373 if (temp1 > 0)
374 {
375 one = tmpcalc.substr(0, temp1);
376 two = tmpcalc.substr(temp1 + 1);
377 if (IsNumeric(one) == true && IsNumeric(two) == true)
378 {
379 if(ToFloat(one) < ToFloat(two))
380 return true;
381 else
382 return false;
383 }
384 else
385 return false;
386 }
387 temp1 = tmpcalc.find(">", 1);
388 if (temp1 > 0)
389 {
390 one = tmpcalc.substr(0, temp1);
391 two = tmpcalc.substr(temp1 + 1);
392 if (IsNumeric(one) == true && IsNumeric(two) == true)
393 {
394 if(ToFloat(one) > ToFloat(two))
395 return true;
396 else
397 return false;
398 }
399 else
400 return false;
401 }
402 temp1 = tmpcalc.find("&", 1);
403 if (temp1 > 0)
404 {
405 one = tmpcalc.substr(0, temp1);
406 two = tmpcalc.substr(temp1 + 1);
407 if (one == "true" && two == "true")
408 return true;
409 else
410 return false;
411 }
412 temp1 = tmpcalc.find("|", 1);
413 if (temp1 > 0)
414 {
415 one = tmpcalc.substr(0, temp1);
416 two = tmpcalc.substr(temp1 + 1);
417 if (one == "true" || two == "true")
418 return true;
419 else
420 return false;
421 }
422 return ToBool(tmpcalc);
423}
424
426{
427 parent->StoreCommand(object);
428}
429
431{
432 //functions for advanced math
433
434 int start, first, last;
435 Real value, result;
436 std::string tempdata;
437
438 int check = LineData.find("(", 0);
439
440 if (check < 0)
441 return sContinue;
442
443 //calculate cosine
444 while(true)
445 {
446 start = SetCaseCopy(LineData, false).find("cos(", 0);
447 if (start > 0)
448 {
449 //break if preceding letter is found
450 char check = LineData[start - 1];
451 if (check >= 65 && check <= 122)
452 break;
453 }
454 else if (start < 0)
455 break;
456
457 first = LineData.find("(", start);
458 last = LineData.find(")", start);
459 if (last < 0)
460 return ScriptError("Syntax error");
461
462 tempdata = Calc(LineData.substr(first + 1, last - first - 1));
463 if (!IsNumeric(tempdata, value))
464 return ScriptError("Invalid value: " + tempdata);
465
466 result = cosf(value);
467 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
468 }
469
470 //calculate sine
471 while(true)
472 {
473 start = SetCaseCopy(LineData, false).find("sin(", 0);
474 if (start > 0)
475 {
476 //break if preceding letter is found
477 char check = LineData[start - 1];
478 if (check >= 65 && check <= 122)
479 break;
480 }
481 else if (start < 0)
482 break;
483
484 first = LineData.find("(", start);
485 last = LineData.find(")", start);
486 if (last < 0)
487 return ScriptError("Syntax error");
488
489 tempdata = Calc(LineData.substr(first + 1, last - first - 1));
490 if (!IsNumeric(tempdata, value))
491 return ScriptError("Invalid value: " + tempdata);
492
493 result = sinf(value);
494 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
495 }
496
497 //calculate tangent
498 while(true)
499 {
500 start = SetCaseCopy(LineData, false).find("tan(", 0);
501 if (start > 0)
502 {
503 //break if preceding letter is found
504 char check = LineData[start - 1];
505 if (check >= 65 && check <= 122)
506 break;
507 }
508 else if (start < 0)
509 break;
510
511 first = LineData.find("(", start);
512 last = LineData.find(")", start);
513 if (last < 0)
514 return ScriptError("Syntax error");
515
516 tempdata = Calc(LineData.substr(first + 1, last - first - 1));
517 if (!IsNumeric(tempdata, value))
518 return ScriptError("Invalid value: " + tempdata);
519
520 result = tanf(value);
521 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
522 }
523
524 //calculate arc cosine
525 while(true)
526 {
527 start = SetCaseCopy(LineData, false).find("acos(", 0);
528 if (start > 0)
529 {
530 //break if preceding letter is found
531 char check = LineData[start - 1];
532 if (check >= 65 && check <= 122)
533 break;
534 }
535 else if (start < 0)
536 break;
537
538 first = LineData.find("(", start);
539 last = LineData.find(")", start);
540 if (last < 0)
541 return ScriptError("Syntax error");
542
543 tempdata = Calc(LineData.substr(first + 1, last - first - 1));
544 if (!IsNumeric(tempdata, value))
545 return ScriptError("Invalid value: " + tempdata);
546
547 if (value < -1 || value > 1)
548 return ScriptError("Invalid value: " + tempdata);
549
550 result = acosf(value);
551 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
552 }
553
554 //calculate arc sine
555 while(true)
556 {
557 start = SetCaseCopy(LineData, false).find("asin(", 0);
558 if (start > 0)
559 {
560 //break if preceding letter is found
561 char check = LineData[start - 1];
562 if (check >= 65 && check <= 122)
563 break;
564 }
565 else if (start < 0)
566 break;
567
568 first = LineData.find("(", start);
569 last = LineData.find(")", start);
570 if (last < 0)
571 return ScriptError("Syntax error");
572
573 tempdata = Calc(LineData.substr(first + 1, last - first - 1));
574 if (!IsNumeric(tempdata, value))
575 return ScriptError("Invalid value: " + tempdata);
576
577 if (value < -1 || value > 1)
578 return ScriptError("Invalid value: " + tempdata);
579
580 result = asinf(value);
581 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
582 }
583
584 //calculate arc tangent
585 while(true)
586 {
587 start = SetCaseCopy(LineData, false).find("atan(", 0);
588 if (start > 0)
589 {
590 //break if preceding letter is found
591 char check = LineData[start - 1];
592 if (check >= 65 && check <= 122)
593 break;
594 }
595 else if (start < 0)
596 break;
597
598 first = LineData.find("(", start);
599 last = LineData.find(")", start);
600 if (last < 0)
601 return ScriptError("Syntax error");
602
603 tempdata = Calc(LineData.substr(first + 1, last - first - 1));
604 if (!IsNumeric(tempdata, value))
605 return ScriptError("Invalid value: " + tempdata);
606
607 result = atanf(value);
608 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
609 }
610
611 //calculate arc tangent with 2 parameters
612 while(true)
613 {
614 start = SetCaseCopy(LineData, false).find("atan2(", 0);
615 if (start > 0)
616 {
617 //break if preceding letter is found
618 char check = LineData[start - 1];
619 if (check >= 65 && check <= 122)
620 break;
621 }
622 else if (start < 0)
623 break;
624
625 first = LineData.find("(", start);
626 int mid = LineData.find(",", first);
627 last = LineData.find(")", start);
628 if (last < 0 || mid < 0)
629 return ScriptError("Syntax error");
630
631 std::string tempdata1 = Calc(LineData.substr(first + 1, mid - first - 1));
632 std::string tempdata2 = Calc(LineData.substr(mid + 1, last - mid - 1));
633
634 Real value1, value2;
635 if (!IsNumeric(tempdata1, value1))
636 return ScriptError("Invalid value: " + tempdata1);
637 if (!IsNumeric(tempdata2, value2))
638 return ScriptError("Invalid value: " + tempdata2);
639
640 result = atan2f(value1, value2);
641 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
642 }
643
644 //calculate square root
645 while(true)
646 {
647 start = SetCaseCopy(LineData, false).find("sqrt(", 0);
648 if (start > 0)
649 {
650 //break if preceding letter is found
651 char check = LineData[start - 1];
652 if (check >= 65 && check <= 122)
653 break;
654 }
655 else if (start < 0)
656 break;
657
658 first = LineData.find("(", start);
659 last = LineData.find(")", start);
660 if (last < 0)
661 return ScriptError("Syntax error");
662
663 tempdata = Calc(LineData.substr(first + 1, last - first - 1));
664 if (!IsNumeric(tempdata, value))
665 return ScriptError("Invalid value: " + tempdata);
666
667 result = sqrtf(value);
668 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
669 }
670
671 //calculate absolute value
672 while(true)
673 {
674 start = SetCaseCopy(LineData, false).find("abs(", 0);
675 if (start > 0)
676 {
677 //break if preceding letter is found
678 char check = LineData[start - 1];
679 if (check >= 65 && check <= 122)
680 break;
681 }
682 else if (start < 0)
683 break;
684
685 first = LineData.find("(", start);
686 last = LineData.find(")", start);
687 if (last < 0)
688 return ScriptError("Syntax error");
689
690 tempdata = Calc(LineData.substr(first + 1, last - first - 1));
691 if (!IsNumeric(tempdata, value))
692 return ScriptError("Invalid value: " + tempdata);
693
694 result = std::abs(value);
695 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
696 }
697
698 //calculate exponential function
699 while(true)
700 {
701 start = SetCaseCopy(LineData, false).find("exp(", 0);
702 if (start > 0)
703 {
704 //break if preceding letter is found
705 char check = LineData[start - 1];
706 if (check >= 65 && check <= 122)
707 break;
708 }
709 else if (start < 0)
710 break;
711
712 first = LineData.find("(", start);
713 last = LineData.find(")", start);
714 if (last < 0)
715 return ScriptError("Syntax error");
716
717 tempdata = Calc(LineData.substr(first + 1, last - first - 1));
718 if (!IsNumeric(tempdata, value))
719 return ScriptError("Invalid value: " + tempdata);
720
721 result = expf(value);
722 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
723 }
724
725 //calculate natural logarithm
726 while(true)
727 {
728 start = SetCaseCopy(LineData, false).find("log(", 0);
729 if (start > 0)
730 {
731 //break if preceding letter is found
732 char check = LineData[start - 1];
733 if (check >= 65 && check <= 122)
734 break;
735 }
736 else if (start < 0)
737 break;
738
739 first = LineData.find("(", start);
740 last = LineData.find(")", start);
741 if (last < 0)
742 return ScriptError("Syntax error");
743
744 tempdata = Calc(LineData.substr(first + 1, last - first - 1));
745 if (!IsNumeric(tempdata, value))
746 return ScriptError("Invalid value: " + tempdata);
747
748 if (value <= 0)
749 return ScriptError("Invalid value: " + tempdata);
750
751 result = logf(value);
752 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
753 }
754
755 //calculate common logarithm
756 while(true)
757 {
758 start = SetCaseCopy(LineData, false).find("log10(", 0);
759 if (start > 0)
760 {
761 //break if preceding letter is found
762 char check = LineData[start - 1];
763 if (check >= 65 && check <= 122)
764 break;
765 }
766 else if (start < 0)
767 break;
768
769 first = LineData.find("(", start);
770 last = LineData.find(")", start);
771 if (last < 0)
772 return ScriptError("Syntax error");
773
774 tempdata = Calc(LineData.substr(first + 1, last - first - 1));
775 if (!IsNumeric(tempdata, value))
776 return ScriptError("Invalid value: " + tempdata);
777
778 if (value <= 0)
779 return ScriptError("Invalid value: " + tempdata);
780
781 result = log10f(value);
782 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
783 }
784
785 //calculate binary logarithm
786 while(true)
787 {
788 start = SetCaseCopy(LineData, false).find("log2(", 0);
789 if (start > 0)
790 {
791 //break if preceding letter is found
792 char check = LineData[start - 1];
793 if (check >= 65 && check <= 122)
794 break;
795 }
796 else if (start < 0)
797 break;
798
799 first = LineData.find("(", start);
800 last = LineData.find(")", start);
801 if (last < 0)
802 return ScriptError("Syntax error");
803
804 tempdata = Calc(LineData.substr(first + 1, last - first - 1));
805 if (!IsNumeric(tempdata, value))
806 return ScriptError("Invalid value: " + tempdata);
807
808 if (value <= 0)
809 return ScriptError("Invalid value: " + tempdata);
810
811 result = Log2(value);
812 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
813 }
814
815 //calculate remainder
816 while(true)
817 {
818 start = SetCaseCopy(LineData, false).find("mod(", 0);
819 if (start > 0)
820 {
821 //break if preceding letter is found
822 char check = LineData[start - 1];
823 if (check >= 65 && check <= 122)
824 break;
825 }
826 else if (start < 0)
827 break;
828
829 first = LineData.find("(", start);
830 int mid = LineData.find(",", first);
831 last = LineData.find(")", start);
832 if (last < 0 || mid < 0)
833 return ScriptError("Syntax error");
834
835 std::string tempdata1 = Calc(LineData.substr(first + 1, mid - first - 1));
836 std::string tempdata2 = Calc(LineData.substr(mid + 1, last - mid - 1));
837
838 Real value1, value2;
839 if (!IsNumeric(tempdata1, value1))
840 return ScriptError("Invalid value: " + tempdata1);
841 if (!IsNumeric(tempdata2, value2))
842 return ScriptError("Invalid value: " + tempdata2);
843
844 if (value2 == 0)
845 return ScriptError("Invalid value: " + tempdata2);
846
847 result = fmodf(value1, value2);
848 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
849 }
850
851 //calculate hypotenuse
852 while(true)
853 {
854 start = SetCaseCopy(LineData, false).find("hypot(", 0);
855 if (start > 0)
856 {
857 //break if preceding letter is found
858 char check = LineData[start - 1];
859 if (check >= 65 && check <= 122)
860 break;
861 }
862 else if (start < 0)
863 break;
864
865 first = LineData.find("(", start);
866 int mid = LineData.find(",", first);
867 last = LineData.find(")", start);
868 if (last < 0 || mid < 0)
869 return ScriptError("Syntax error");
870
871 std::string tempdata1 = Calc(LineData.substr(first + 1, mid - first - 1));
872 std::string tempdata2 = Calc(LineData.substr(mid + 1, last - mid - 1));
873
874 Real value1, value2;
875 if (!IsNumeric(tempdata1, value1))
876 return ScriptError("Invalid value: " + tempdata1);
877 if (!IsNumeric(tempdata2, value2))
878 return ScriptError("Invalid value: " + tempdata2);
879
880 if (value2 == 0)
881 return ScriptError("Invalid value: " + tempdata2);
882
883 result = sqrtf(powf(value1, 2) + powf(value2, 2));
884 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
885 }
886
887 //calculate ceiling
888 while(true)
889 {
890 start = SetCaseCopy(LineData, false).find("ceil(", 0);
891 if (start > 0)
892 {
893 //break if preceding letter is found
894 char check = LineData[start - 1];
895 if (check >= 65 && check <= 122)
896 break;
897 }
898 else if (start < 0)
899 break;
900
901 first = LineData.find("(", start);
902 last = LineData.find(")", start);
903 if (last < 0)
904 return ScriptError("Syntax error");
905
906 tempdata = Calc(LineData.substr(first + 1, last - first - 1));
907 if (!IsNumeric(tempdata, value))
908 return ScriptError("Invalid value: " + tempdata);
909
910 if (value <= 0)
911 return ScriptError("Invalid value: " + tempdata);
912
913 result = ceilf(value);
914 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
915 }
916
917 //calculate floor
918 while(true)
919 {
920 start = SetCaseCopy(LineData, false).find("flr(", 0);
921 if (start > 0)
922 {
923 //break if preceding letter is found
924 char check = LineData[start - 1];
925 if (check >= 65 && check <= 122)
926 break;
927 }
928 else if (start < 0)
929 break;
930
931 first = LineData.find("(", start);
932 last = LineData.find(")", start);
933 if (last < 0)
934 return ScriptError("Syntax error");
935
936 tempdata = Calc(LineData.substr(first + 1, last - first - 1));
937 if (!IsNumeric(tempdata, value))
938 return ScriptError("Invalid value: " + tempdata);
939
940 if (value <= 0)
941 return ScriptError("Invalid value: " + tempdata);
942
943 result = floorf(value);
944 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
945 }
946
947 //calculate random number
948 while(true)
949 {
950 start = SetCaseCopy(LineData, false).find("rnd(", 0);
951 if (start > 0)
952 {
953 //break if preceding letter is found
954 char check = LineData[start - 1];
955 if (check >= 65 && check <= 122)
956 break;
957 }
958 else if (start < 0)
959 break;
960
961 first = LineData.find("(", start);
962 last = LineData.find(")", start);
963 if (last < 0)
964 return ScriptError("Syntax error");
965
966 tempdata = Calc(LineData.substr(first + 1, last - first - 1));
967 if (!IsNumeric(tempdata, value))
968 return ScriptError("Invalid value: " + tempdata);
969
970 if (value <= 0)
971 return ScriptError("Invalid value: " + tempdata);
972
973 RandomGen rnd(time(0));
974 result = rnd.Get(value);
975 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
976 }
977
978 //round a number
979 while(true)
980 {
981 start = SetCaseCopy(LineData, false).find("round(", 0);
982 if (start > 0)
983 {
984 //break if preceding letter is found
985 char check = LineData[start - 1];
986 if (check >= 65 && check <= 122)
987 break;
988 }
989 else if (start < 0)
990 break;
991
992 first = LineData.find("(", start);
993 last = LineData.find(")", start);
994 if (last < 0)
995 return ScriptError("Syntax error");
996
997 int option = LineData.find(",", first);
998 std::string decimals;
999 int decimal = 0;
1000 if (option > 0 && option < last)
1001 {
1002 tempdata = Calc(LineData.substr(first + 1, option - first - 1));
1003 decimals = Calc(LineData.substr(option + 1, last - option - 1));
1004 }
1005 else
1006 {
1007 tempdata = Calc(LineData.substr(first + 1, last - first - 1));
1008 decimals = "0";
1009 }
1010
1011 if (!IsNumeric(tempdata, value))
1012 return ScriptError("Invalid value: " + tempdata);
1013
1014 if (!IsNumeric(decimals, decimal))
1015 return ScriptError("Invalid value: " + tempdata);
1016
1017 if (value <= 0)
1018 return ScriptError("Invalid value: " + tempdata);
1019
1020 if (decimal < 0)
1021 return ScriptError("Invalid value: " + decimals);
1022
1023 result = Round(value, decimal);
1024 LineData = LineData.substr(0, start) + ToString(result) + LineData.substr(last + 1);
1025 }
1026
1027 return sContinue;
1028}
1029
1030std::string ScriptProcessor::Section::Calc(const std::string &expression)
1031{
1032 return parent->Calc(expression);
1033}
1034
1036{
1037 //get a system mesh object, or search for a custom one by name
1038
1039 SetCase(name, false);
1040
1041 //get a system mesh object
1042 if (name == "floor")
1043 {
1044 if (config->SectionNum == 2)
1045 return Simcore->GetFloor(config->Current)->Level;
1046 return 0;
1047 }
1048 else if (name == "interfloor")
1049 {
1050 if (config->SectionNum == 2)
1052 return 0;
1053 }
1054 else if (name == "columnframe")
1055 {
1056 if (config->SectionNum == 2)
1058 return 0;
1059 }
1060 else if (name == "elevatorcar")
1061 {
1062 if (config->SectionNum == 6)
1064 return 0;
1065 }
1066 else if (name == "elevator")
1067 {
1068 if (config->SectionNum == 4)
1070 return 0;
1071 }
1072 else if (name == "external")
1073 return Simcore->External;
1074 else if (name == "landscape")
1075 return Simcore->Landscape;
1076 else if (name == "buildings")
1077 return Simcore->Buildings;
1078 else if (name.substr(0, 5) == "shaft")
1079 {
1080 if (config->SectionNum == 2)
1081 {
1082 //get a shaft mesh object, or a model in a shaft
1083
1084 std::string num, modelname;
1085 int marker = (int)name.find(":");
1086 if (marker > 0)
1087 modelname = name.substr(marker + 1);
1088
1089 if (marker > 0)
1090 num = name.substr(5, (int)name.length() - marker - 1);
1091 else
1092 num = name.substr(5);
1093
1094 TrimString(num);
1095 int number;
1096 if (!IsNumeric(num, number))
1097 return 0;
1098
1099 Shaft *shaft = Simcore->GetShaft(number);
1100 if (!shaft)
1101 return 0;
1102
1103 if (marker > 0)
1104 {
1105 Model *model = 0;
1106
1107 if (shaft->GetLevel(config->Current))
1108 model = shaft->GetLevel(config->Current)->GetModel(modelname);
1109
1110 if (model)
1111 {
1112 if (model->IsCustom() == true)
1113 return model->GetMeshObject();
1114 }
1115 return 0;
1116 }
1117 else
1118 {
1119 if (shaft->GetLevel(config->Current))
1120 return shaft->GetLevel(config->Current)->GetMeshObject();
1121 else
1122 return 0;
1123 }
1124 }
1125 return 0;
1126 }
1127 else if (name.substr(0, 9) == "stairwell")
1128 {
1129 if (config->SectionNum == 2)
1130 {
1131 //get a stairwell mesh object, or a model in a stairwell
1132
1133 std::string num, modelname;
1134 int marker = (int)name.find(":");
1135 if (marker > 0)
1136 modelname = name.substr(marker + 1);
1137
1138 if (marker > 0)
1139 num = name.substr(9, (int)name.length() - marker - 1);
1140 else
1141 num = name.substr(9);
1142
1143 TrimString(num);
1144 int number;
1145 if (!IsNumeric(num, number))
1146 return 0;
1147
1148 Stairwell *stairs = Simcore->GetStairwell(number);
1149 if (!stairs)
1150 return 0;
1151
1152 if (marker > 0)
1153 {
1154 Model *model = 0;
1155
1156 if (stairs->GetLevel(config->Current))
1157 model = stairs->GetLevel(config->Current)->GetModel(modelname);
1158
1159 if (model)
1160 {
1161 if (model->IsCustom() == true)
1162 return model->GetMeshObject();
1163 }
1164 return 0;
1165 }
1166 else
1167 {
1168 if (stairs->GetLevel(config->Current))
1169 return stairs->GetLevel(config->Current)->GetMeshObject();
1170 else
1171 return 0;
1172 }
1173 }
1174 return 0;
1175 }
1176
1177 //get a custom model mesh
1178
1179 Model* model = 0;
1180
1181 if (config->SectionNum == 2)
1182 model = Simcore->GetFloor(config->Current)->GetModel(name);
1183 else if (config->SectionNum == 4)
1184 model = Simcore->GetElevator(config->Current)->GetCar(1)->GetModel(name);
1185 else if (config->SectionNum == 6)
1187 else
1188 model = Simcore->GetModel(name);
1189
1190 if (model)
1191 {
1192 if (model->IsCustom() == true)
1193 return model->GetMeshObject();
1194 }
1195 return 0;
1196}
1197
1198bool ScriptProcessor::Section::GetElevatorCar(std::string &value, int floor, int &elevator, int &car)
1199{
1200 //returns an elevator and car number for the specified string
1201 //for example, use "1" for Elevator 1
1202 //or "1:1" for Elevator 1 Car 1
1203
1204 TrimString(value);
1205
1206 if (IsNumeric(value, elevator))
1207 {
1208 if (!Simcore->GetElevator(elevator))
1209 {
1210 ScriptError("Invalid elevator " + ToString(elevator));
1211 return false;
1212 }
1213
1214 car = 1;
1215
1216 if (Simcore->GetFloor(floor))
1217 {
1218 ElevatorCar *obj = Simcore->GetElevator(elevator)->GetCarForFloor(floor);
1219 if (obj)
1220 car = obj->Number;
1221 }
1222
1223 return true;
1224 }
1225
1226 int pos = value.find(":");
1227 if (pos == -1)
1228 {
1229 elevator = 0;
1230 car = 0;
1231 ScriptError("Invalid elevator value");
1232 return false;
1233 }
1234
1235 elevator = ToInt(value.substr(0, pos));
1236 car = ToInt(value.substr(pos + 1));
1237
1238 //verify elevator and car objects
1239 Elevator *elev = Simcore->GetElevator(elevator);
1240 if (!elev)
1241 {
1242 ScriptError("Invalid elevator " + ToString(elevator));
1243 return false;
1244 }
1245 if (!elev->GetCar(car))
1246 {
1247 ScriptError("Invalid elevator car " + ToString(car));
1248 return false;
1249 }
1250
1251 return true;
1252}
1253
1254void ScriptProcessor::Section::GetDirectionStrings(int direction, std::string &face_direction, std::string &open_direction)
1255{
1256 //direction table:
1257 //1 = faces left, opens left
1258 //2 = faces left, opens right
1259 //3 = faces right, opens right
1260 //4 = faces right, opens left
1261 //5 = faces front, opens front
1262 //6 = faces front, opens back
1263 //7 = faces back, opens back
1264 //8 = faces back, opens front
1265
1266 face_direction = "";
1267 open_direction = "";
1268
1269 if (direction == 1 || direction == 2)
1270 face_direction = "left";
1271 if (direction == 3 || direction == 4)
1272 face_direction = "right";
1273 if (direction == 5 || direction == 6)
1274 face_direction = "front";
1275 if (direction == 7 || direction == 8)
1276 face_direction = "back";
1277
1278 if (direction == 1 || direction == 4)
1279 open_direction = "left";
1280 else if (direction == 2 || direction == 3)
1281 open_direction = "right";
1282 else if (direction == 5 || direction == 8)
1283 open_direction = "front";
1284 else if (direction == 6 || direction == 7)
1285 open_direction = "back";
1286}
1287
1292
1294{
1295 //shared variables
1296 setkey = false;
1297 keyvalue = 0;
1298 lockvalue = 0;
1299 MinExtent = Vector3::ZERO;
1300 MaxExtent = Vector3::ZERO;
1301 RangeL = 0;
1302 RangeLOld = 0;
1303 RangeH = 0;
1304 RangeHOld = 0;
1305 RangeStart = 0;
1306 RangeStartOld = 0;
1307 Current = 0;
1308 CurrentOld = 0;
1309 SectionNum = 0;
1310 Context = "None";
1311 ContextOld = "";
1312 ReverseAxis = false;
1313 InWhile = false;
1314 setshaftdoors = false;
1315 CheckScript = false;
1316}
1317
1318}
Model * GetModel(std::string name)
MeshObject * Mesh
ElevatorCar * GetCar(int number)
ElevatorCar * GetCarForFloor(int number, bool report_on_failure=false)
MeshObject * ColumnFrame
Definition floor.h:34
MeshObject * Level
Definition floor.h:32
Model * GetModel(std::string name)
Definition floor.cpp:1866
MeshObject * Interfloor
Definition floor.h:33
bool IsCustom()
Definition model.h:49
MeshObject * GetMeshObject()
Definition model.h:47
float Get()
Definition random.cpp:135
Shaft * GetShaft(int number)
Definition sbs.cpp:1753
Elevator * GetElevator(int number)
Definition sbs.cpp:1746
MeshObject * External
Definition sbs.h:422
Model * GetModel(std::string name)
Definition sbs.cpp:4452
Floor * GetFloor(int number)
Definition sbs.cpp:1739
Stairwell * GetStairwell(int number)
Definition sbs.cpp:1760
MeshObject * Landscape
Definition sbs.h:423
MeshObject * Buildings
Definition sbs.h:421
Model * GetModel(std::string name)
Definition shaft.cpp:1179
MeshObject * GetMeshObject()
Definition shaft.cpp:1048
Level * GetLevel(int floor)
Definition shaft.cpp:135
MeshObject * GetMeshObject()
Definition stairs.cpp:1074
Model * GetModel(std::string name)
Definition stairs.cpp:1187
Level * GetLevel(int floor)
Definition stairs.cpp:112
bool GetConfigBool(Ogre::ConfigFile *file, const std::string &key, bool default_value)
Definition hal.cpp:299
Ogre::ConfigFile * configfile
Definition hal.h:97
std::string Calc(const std::string &expression)
Definition section.cpp:1030
int SplitData(const std::string &string, int start, bool calc=true)
Definition section.cpp:52
bool GetRange(const std::string &string, int &start, int &end)
Definition section.cpp:176
int MathFunctions(std::string &LineData)
Definition section.cpp:430
int SplitAfterEquals(const std::string &string, bool calc=true)
Definition section.cpp:78
bool GetElevatorCar(std::string &value, int floor, int &elevator, int &car)
Definition section.cpp:1198
void StoreCommand(SBS::Object *object)
Definition section.cpp:425
Section(ScriptProcessor *parent)
Definition section.cpp:42
ScriptProcessor::ConfigHandler * config
Definition section.h:58
std::string GetBeforeEquals(const std::string &string, bool calc=true)
Definition section.cpp:129
int ScriptWarning(std::string message)
Definition section.cpp:212
::SBS::MeshObject * GetMeshObject(std::string name)
Definition section.cpp:1035
void GetDirectionStrings(int direction, std::string &face_direction, std::string &open_direction)
Definition section.cpp:1254
bool IfProc(const std::string &expression)
Definition section.cpp:217
std::string GetAfterEquals(const std::string &string, bool &found_equals)
Definition section.cpp:107
static const int sContinue
Definition scriptproc.h:69
EngineContext * GetEngine()
std::string Calc(const std::string &expression)
ConfigHandler * GetConfigHandler()
HAL * GetHAL()
Definition vm.cpp:128
Ogre::Real Real
Definition globals.h:57
void SplitString(std::vector< std::string > &dest_array, const std::string &original_string, char separator)
Definition globals.cpp:242
void ReplaceAll(std::string &string, const std::string &original, const std::string &replacement)
Definition globals.cpp:201
int ToInt(const std::string &string)
Definition globals.cpp:402
void SetCase(std::string &string, bool uppercase)
Definition globals.cpp:172
std::string ToString(int number)
Definition globals.cpp:279
float Round(float number, int decimal_places)
Definition globals.cpp:346
std::string SetCaseCopy(std::string string, bool uppercase)
Definition globals.cpp:165
Real ToFloat(const std::string &string)
Definition globals.cpp:397
void TrimString(std::string &string)
Definition globals.cpp:188
bool ToBool(std::string string)
Definition globals.cpp:407
float Log2(float number)
Definition globals.cpp:336
bool IsNumeric(const wxString &string)