1 /***************************************************************************** 2 * Copyright (c) 2014-2021 OpenRCT2 developers 3 * 4 * For a complete list of all authors, please refer to contributors.md 5 * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 6 * 7 * OpenRCT2 is licensed under the GNU General Public License version 3. 8 *****************************************************************************/ 9 10 #ifdef ENABLE_SCRIPTING 11 12 # include "ScTileElement.hpp" 13 14 # include "../../../Context.h" 15 # include "../../../common.h" 16 # include "../../../core/Guard.hpp" 17 # include "../../../ride/Track.h" 18 # include "../../../world/Footpath.h" 19 # include "../../../world/Scenery.h" 20 # include "../../../world/Sprite.h" 21 # include "../../../world/Surface.h" 22 # include "../../Duktape.hpp" 23 # include "../../ScriptEngine.h" 24 25 # include <cstdio> 26 # include <cstring> 27 # include <utility> 28 29 namespace OpenRCT2::Scripting 30 { ScTileElement(const CoordsXY & coords,TileElement * element)31 ScTileElement::ScTileElement(const CoordsXY& coords, TileElement* element) 32 : _coords(coords) 33 , _element(element) 34 { 35 } 36 type_get() const37 std::string ScTileElement::type_get() const 38 { 39 switch (_element->GetType()) 40 { 41 case TILE_ELEMENT_TYPE_SURFACE: 42 return "surface"; 43 case TILE_ELEMENT_TYPE_PATH: 44 return "footpath"; 45 case TILE_ELEMENT_TYPE_TRACK: 46 return "track"; 47 case TILE_ELEMENT_TYPE_SMALL_SCENERY: 48 return "small_scenery"; 49 case TILE_ELEMENT_TYPE_ENTRANCE: 50 return "entrance"; 51 case TILE_ELEMENT_TYPE_WALL: 52 return "wall"; 53 case TILE_ELEMENT_TYPE_LARGE_SCENERY: 54 return "large_scenery"; 55 case TILE_ELEMENT_TYPE_BANNER: 56 return "banner"; 57 case TILE_ELEMENT_TYPE_CORRUPT: 58 return "openrct2_corrupt_deprecated"; 59 default: 60 return "unknown"; 61 } 62 } 63 type_set(std::string value)64 void ScTileElement::type_set(std::string value) 65 { 66 if (value == "surface") 67 _element->type = TILE_ELEMENT_TYPE_SURFACE; 68 else if (value == "footpath") 69 _element->type = TILE_ELEMENT_TYPE_PATH; 70 else if (value == "track") 71 _element->type = TILE_ELEMENT_TYPE_TRACK; 72 else if (value == "small_scenery") 73 _element->type = TILE_ELEMENT_TYPE_SMALL_SCENERY; 74 else if (value == "entrance") 75 _element->type = TILE_ELEMENT_TYPE_ENTRANCE; 76 else if (value == "wall") 77 _element->type = TILE_ELEMENT_TYPE_WALL; 78 else if (value == "large_scenery") 79 _element->type = TILE_ELEMENT_TYPE_LARGE_SCENERY; 80 else if (value == "banner") 81 _element->type = TILE_ELEMENT_TYPE_BANNER; 82 else 83 { 84 if (value == "openrct2_corrupt_deprecated") 85 std::puts( 86 "Creation of new corrupt elements is deprecated. To hide elements, use the 'hidden' property instead."); 87 return; 88 } 89 90 Invalidate(); 91 } 92 baseHeight_get() const93 uint8_t ScTileElement::baseHeight_get() const 94 { 95 return _element->base_height; 96 } baseHeight_set(uint8_t newBaseHeight)97 void ScTileElement::baseHeight_set(uint8_t newBaseHeight) 98 { 99 ThrowIfGameStateNotMutable(); 100 _element->base_height = newBaseHeight; 101 Invalidate(); 102 } 103 baseZ_get() const104 uint16_t ScTileElement::baseZ_get() const 105 { 106 return _element->GetBaseZ(); 107 } baseZ_set(uint16_t value)108 void ScTileElement::baseZ_set(uint16_t value) 109 { 110 ThrowIfGameStateNotMutable(); 111 _element->SetBaseZ(value); 112 Invalidate(); 113 } 114 clearanceHeight_get() const115 uint8_t ScTileElement::clearanceHeight_get() const 116 { 117 return _element->clearance_height; 118 } clearanceHeight_set(uint8_t newClearanceHeight)119 void ScTileElement::clearanceHeight_set(uint8_t newClearanceHeight) 120 { 121 ThrowIfGameStateNotMutable(); 122 _element->clearance_height = newClearanceHeight; 123 Invalidate(); 124 } 125 clearanceZ_get() const126 uint16_t ScTileElement::clearanceZ_get() const 127 { 128 return _element->GetClearanceZ(); 129 } clearanceZ_set(uint16_t value)130 void ScTileElement::clearanceZ_set(uint16_t value) 131 { 132 ThrowIfGameStateNotMutable(); 133 _element->SetClearanceZ(value); 134 Invalidate(); 135 } 136 slope_get() const137 DukValue ScTileElement::slope_get() const 138 { 139 auto ctx = GetContext()->GetScriptEngine().GetContext(); 140 switch (_element->GetType()) 141 { 142 case TILE_ELEMENT_TYPE_SURFACE: 143 { 144 auto el = _element->AsSurface(); 145 duk_push_int(ctx, el->GetSlope()); 146 break; 147 } 148 case TILE_ELEMENT_TYPE_WALL: 149 { 150 auto el = _element->AsWall(); 151 duk_push_int(ctx, el->GetSlope()); 152 break; 153 } 154 default: 155 { 156 duk_push_null(ctx); 157 break; 158 } 159 } 160 return DukValue::take_from_stack(ctx); 161 } slope_set(uint8_t value)162 void ScTileElement::slope_set(uint8_t value) 163 { 164 ThrowIfGameStateNotMutable(); 165 switch (_element->GetType()) 166 { 167 case TILE_ELEMENT_TYPE_SURFACE: 168 { 169 auto el = _element->AsSurface(); 170 el->SetSlope(value); 171 Invalidate(); 172 break; 173 } 174 case TILE_ELEMENT_TYPE_WALL: 175 { 176 auto el = _element->AsWall(); 177 el->SetSlope(value); 178 Invalidate(); 179 break; 180 } 181 } 182 } 183 waterHeight_get() const184 DukValue ScTileElement::waterHeight_get() const 185 { 186 auto ctx = GetContext()->GetScriptEngine().GetContext(); 187 auto el = _element->AsSurface(); 188 if (el != nullptr) 189 duk_push_int(ctx, el->GetWaterHeight()); 190 else 191 duk_push_null(ctx); 192 return DukValue::take_from_stack(ctx); 193 } waterHeight_set(int32_t value)194 void ScTileElement::waterHeight_set(int32_t value) 195 { 196 ThrowIfGameStateNotMutable(); 197 auto el = _element->AsSurface(); 198 if (el != nullptr) 199 { 200 el->SetWaterHeight(value); 201 Invalidate(); 202 } 203 } 204 surfaceStyle_get() const205 DukValue ScTileElement::surfaceStyle_get() const 206 { 207 auto ctx = GetContext()->GetScriptEngine().GetContext(); 208 auto el = _element->AsSurface(); 209 if (el != nullptr) 210 duk_push_int(ctx, el->GetSurfaceStyle()); 211 else 212 duk_push_null(ctx); 213 return DukValue::take_from_stack(ctx); 214 } surfaceStyle_set(uint32_t value)215 void ScTileElement::surfaceStyle_set(uint32_t value) 216 { 217 ThrowIfGameStateNotMutable(); 218 auto el = _element->AsSurface(); 219 if (el != nullptr) 220 { 221 el->SetSurfaceStyle(value); 222 Invalidate(); 223 } 224 } 225 edgeStyle_get() const226 DukValue ScTileElement::edgeStyle_get() const 227 { 228 auto ctx = GetContext()->GetScriptEngine().GetContext(); 229 auto el = _element->AsSurface(); 230 if (el != nullptr) 231 duk_push_int(ctx, el->GetEdgeStyle()); 232 else 233 duk_push_null(ctx); 234 return DukValue::take_from_stack(ctx); 235 } edgeStyle_set(uint32_t value)236 void ScTileElement::edgeStyle_set(uint32_t value) 237 { 238 ThrowIfGameStateNotMutable(); 239 auto el = _element->AsSurface(); 240 if (el != nullptr) 241 { 242 el->SetEdgeStyle(value); 243 Invalidate(); 244 } 245 } 246 grassLength_get() const247 DukValue ScTileElement::grassLength_get() const 248 { 249 auto ctx = GetContext()->GetScriptEngine().GetContext(); 250 auto el = _element->AsSurface(); 251 if (el != nullptr) 252 duk_push_int(ctx, el->GetGrassLength()); 253 else 254 duk_push_null(ctx); 255 return DukValue::take_from_stack(ctx); 256 } grassLength_set(uint8_t value)257 void ScTileElement::grassLength_set(uint8_t value) 258 { 259 ThrowIfGameStateNotMutable(); 260 auto el = _element->AsSurface(); 261 if (el != nullptr) 262 { 263 // TODO: Give warning when value > GRASS_LENGTH_CLUMPS_2 264 el->SetGrassLengthAndInvalidate(value, _coords); 265 Invalidate(); 266 } 267 } 268 hasOwnership_get() const269 DukValue ScTileElement::hasOwnership_get() const 270 { 271 auto ctx = GetContext()->GetScriptEngine().GetContext(); 272 auto el = _element->AsSurface(); 273 if (el != nullptr) 274 duk_push_boolean(ctx, el->GetOwnership() & OWNERSHIP_OWNED); 275 else 276 duk_push_null(ctx); 277 return DukValue::take_from_stack(ctx); 278 } 279 hasConstructionRights_get()280 DukValue ScTileElement::hasConstructionRights_get() 281 { 282 auto ctx = GetContext()->GetScriptEngine().GetContext(); 283 auto el = _element->AsSurface(); 284 if (el != nullptr) 285 { 286 auto ownership = el->GetOwnership(); 287 duk_push_boolean(ctx, (ownership & OWNERSHIP_OWNED) || (ownership & OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED)); 288 } 289 else 290 duk_push_null(ctx); 291 return DukValue::take_from_stack(ctx); 292 } 293 ownership_get() const294 DukValue ScTileElement::ownership_get() const 295 { 296 auto ctx = GetContext()->GetScriptEngine().GetContext(); 297 auto el = _element->AsSurface(); 298 if (el != nullptr) 299 duk_push_int(ctx, el->GetOwnership()); 300 else 301 duk_push_null(ctx); 302 return DukValue::take_from_stack(ctx); 303 } ownership_set(uint8_t value)304 void ScTileElement::ownership_set(uint8_t value) 305 { 306 ThrowIfGameStateNotMutable(); 307 auto el = _element->AsSurface(); 308 if (el != nullptr) 309 { 310 el->SetOwnership(value); 311 Invalidate(); 312 } 313 } 314 parkFences_get() const315 DukValue ScTileElement::parkFences_get() const 316 { 317 auto ctx = GetContext()->GetScriptEngine().GetContext(); 318 auto el = _element->AsSurface(); 319 if (el != nullptr) 320 duk_push_int(ctx, el->GetParkFences()); 321 else 322 duk_push_null(ctx); 323 return DukValue::take_from_stack(ctx); 324 } parkFences_set(uint8_t value)325 void ScTileElement::parkFences_set(uint8_t value) 326 { 327 ThrowIfGameStateNotMutable(); 328 auto el = _element->AsSurface(); 329 if (el != nullptr) 330 { 331 el->SetParkFences(value); 332 Invalidate(); 333 } 334 } 335 trackType_get() const336 DukValue ScTileElement::trackType_get() const 337 { 338 auto ctx = GetContext()->GetScriptEngine().GetContext(); 339 auto el = _element->AsTrack(); 340 if (el != nullptr) 341 duk_push_int(ctx, el->GetTrackType()); 342 else 343 duk_push_null(ctx); 344 return DukValue::take_from_stack(ctx); 345 } trackType_set(uint8_t value)346 void ScTileElement::trackType_set(uint8_t value) 347 { 348 ThrowIfGameStateNotMutable(); 349 auto el = _element->AsTrack(); 350 if (el != nullptr) 351 { 352 el->SetTrackType(value); 353 Invalidate(); 354 } 355 } 356 sequence_get() const357 DukValue ScTileElement::sequence_get() const 358 { 359 auto ctx = GetContext()->GetScriptEngine().GetContext(); 360 switch (_element->GetType()) 361 { 362 case TILE_ELEMENT_TYPE_LARGE_SCENERY: 363 { 364 auto el = _element->AsLargeScenery(); 365 duk_push_int(ctx, el->GetSequenceIndex()); 366 break; 367 } 368 case TILE_ELEMENT_TYPE_TRACK: 369 { 370 auto el = _element->AsTrack(); 371 if (get_ride(el->GetRideIndex())->type != RIDE_TYPE_MAZE) 372 duk_push_int(ctx, el->GetSequenceIndex()); 373 else 374 duk_push_null(ctx); 375 break; 376 } 377 case TILE_ELEMENT_TYPE_ENTRANCE: 378 { 379 auto el = _element->AsEntrance(); 380 duk_push_int(ctx, el->GetSequenceIndex()); 381 break; 382 } 383 default: 384 { 385 duk_push_null(ctx); 386 break; 387 } 388 } 389 return DukValue::take_from_stack(ctx); 390 } sequence_set(uint8_t value)391 void ScTileElement::sequence_set(uint8_t value) 392 { 393 ThrowIfGameStateNotMutable(); 394 switch (_element->GetType()) 395 { 396 case TILE_ELEMENT_TYPE_LARGE_SCENERY: 397 { 398 auto el = _element->AsLargeScenery(); 399 el->SetSequenceIndex(value); 400 Invalidate(); 401 break; 402 } 403 case TILE_ELEMENT_TYPE_TRACK: 404 { 405 auto el = _element->AsTrack(); 406 if (get_ride(el->GetRideIndex())->type != RIDE_TYPE_MAZE) 407 { 408 el->SetSequenceIndex(value); 409 Invalidate(); 410 } 411 break; 412 } 413 case TILE_ELEMENT_TYPE_ENTRANCE: 414 { 415 auto el = _element->AsEntrance(); 416 el->SetSequenceIndex(value); 417 Invalidate(); 418 break; 419 } 420 } 421 } 422 ride_get() const423 DukValue ScTileElement::ride_get() const 424 { 425 auto ctx = GetContext()->GetScriptEngine().GetContext(); 426 switch (_element->GetType()) 427 { 428 case TILE_ELEMENT_TYPE_PATH: 429 { 430 auto el = _element->AsPath(); 431 if (el->IsQueue() && el->GetRideIndex() != RIDE_ID_NULL) 432 duk_push_int(ctx, EnumValue(el->GetRideIndex())); 433 else 434 duk_push_null(ctx); 435 break; 436 } 437 case TILE_ELEMENT_TYPE_TRACK: 438 { 439 auto el = _element->AsTrack(); 440 duk_push_int(ctx, EnumValue(el->GetRideIndex())); 441 break; 442 } 443 case TILE_ELEMENT_TYPE_ENTRANCE: 444 { 445 auto el = _element->AsEntrance(); 446 duk_push_int(ctx, EnumValue(el->GetRideIndex())); 447 break; 448 } 449 default: 450 { 451 duk_push_null(ctx); 452 break; 453 } 454 } 455 return DukValue::take_from_stack(ctx); 456 } ride_set(int32_t value)457 void ScTileElement::ride_set(int32_t value) 458 { 459 ThrowIfGameStateNotMutable(); 460 switch (_element->GetType()) 461 { 462 case TILE_ELEMENT_TYPE_PATH: 463 { 464 auto el = _element->AsPath(); 465 if (!el->HasAddition()) 466 { 467 el->SetRideIndex(static_cast<ride_id_t>(value)); 468 Invalidate(); 469 } 470 break; 471 } 472 case TILE_ELEMENT_TYPE_TRACK: 473 { 474 auto el = _element->AsTrack(); 475 el->SetRideIndex(static_cast<ride_id_t>(value)); 476 Invalidate(); 477 break; 478 } 479 case TILE_ELEMENT_TYPE_ENTRANCE: 480 { 481 auto el = _element->AsEntrance(); 482 el->SetRideIndex(static_cast<ride_id_t>(value)); 483 Invalidate(); 484 break; 485 } 486 } 487 } 488 station_get() const489 DukValue ScTileElement::station_get() const 490 { 491 auto ctx = GetContext()->GetScriptEngine().GetContext(); 492 switch (_element->GetType()) 493 { 494 case TILE_ELEMENT_TYPE_PATH: 495 { 496 auto el = _element->AsPath(); 497 if (el->IsQueue() && el->GetRideIndex() != RIDE_ID_NULL) 498 duk_push_int(ctx, el->GetStationIndex()); 499 else 500 duk_push_null(ctx); 501 break; 502 } 503 case TILE_ELEMENT_TYPE_TRACK: 504 { 505 auto el = _element->AsTrack(); 506 if (el->IsStation()) 507 duk_push_int(ctx, el->GetStationIndex()); 508 else 509 duk_push_null(ctx); 510 break; 511 } 512 case TILE_ELEMENT_TYPE_ENTRANCE: 513 { 514 auto el = _element->AsEntrance(); 515 duk_push_int(ctx, el->GetStationIndex()); 516 break; 517 } 518 default: 519 { 520 duk_push_null(ctx); 521 break; 522 } 523 } 524 return DukValue::take_from_stack(ctx); 525 } station_set(uint8_t value)526 void ScTileElement::station_set(uint8_t value) 527 { 528 ThrowIfGameStateNotMutable(); 529 switch (_element->GetType()) 530 { 531 case TILE_ELEMENT_TYPE_PATH: 532 { 533 auto el = _element->AsPath(); 534 el->SetStationIndex(value); 535 Invalidate(); 536 break; 537 } 538 case TILE_ELEMENT_TYPE_TRACK: 539 { 540 auto el = _element->AsTrack(); 541 el->SetStationIndex(value); 542 Invalidate(); 543 break; 544 } 545 case TILE_ELEMENT_TYPE_ENTRANCE: 546 { 547 auto el = _element->AsEntrance(); 548 el->SetStationIndex(value); 549 Invalidate(); 550 break; 551 } 552 } 553 } 554 hasChainLift_get() const555 DukValue ScTileElement::hasChainLift_get() const 556 { 557 auto ctx = GetContext()->GetScriptEngine().GetContext(); 558 auto el = _element->AsTrack(); 559 if (el != nullptr) 560 duk_push_boolean(ctx, el->HasChain()); 561 else 562 duk_push_null(ctx); 563 return DukValue::take_from_stack(ctx); 564 } hasChainLift_set(bool value)565 void ScTileElement::hasChainLift_set(bool value) 566 { 567 ThrowIfGameStateNotMutable(); 568 auto el = _element->AsTrack(); 569 if (el != nullptr) 570 { 571 el->SetHasChain(value); 572 Invalidate(); 573 } 574 } 575 mazeEntry_get() const576 DukValue ScTileElement::mazeEntry_get() const 577 { 578 auto ctx = GetContext()->GetScriptEngine().GetContext(); 579 auto el = _element->AsTrack(); 580 if (el != nullptr && get_ride(el->GetRideIndex())->type == RIDE_TYPE_MAZE) 581 duk_push_int(ctx, el->GetMazeEntry()); 582 else 583 duk_push_null(ctx); 584 return DukValue::take_from_stack(ctx); 585 } mazeEntry_set(uint16_t value)586 void ScTileElement::mazeEntry_set(uint16_t value) 587 { 588 ThrowIfGameStateNotMutable(); 589 auto el = _element->AsTrack(); 590 if (el != nullptr) 591 if (get_ride(el->GetRideIndex())->type == RIDE_TYPE_MAZE) 592 { 593 el->SetMazeEntry(value); 594 Invalidate(); 595 } 596 } 597 colourScheme_get() const598 DukValue ScTileElement::colourScheme_get() const 599 { 600 auto ctx = GetContext()->GetScriptEngine().GetContext(); 601 auto el = _element->AsTrack(); 602 if (el != nullptr && get_ride(el->GetRideIndex())->type != RIDE_TYPE_MAZE) 603 duk_push_int(ctx, el->GetColourScheme()); 604 else 605 duk_push_null(ctx); 606 return DukValue::take_from_stack(ctx); 607 } colourScheme_set(uint8_t value)608 void ScTileElement::colourScheme_set(uint8_t value) 609 { 610 ThrowIfGameStateNotMutable(); 611 auto el = _element->AsTrack(); 612 if (el != nullptr) 613 if (get_ride(el->GetRideIndex())->type != RIDE_TYPE_MAZE) 614 { 615 el->SetColourScheme(value); 616 Invalidate(); 617 } 618 } 619 seatRotation_get() const620 DukValue ScTileElement::seatRotation_get() const 621 { 622 auto ctx = GetContext()->GetScriptEngine().GetContext(); 623 auto el = _element->AsTrack(); 624 if (el != nullptr && get_ride(el->GetRideIndex())->type != RIDE_TYPE_MAZE) 625 duk_push_int(ctx, el->GetSeatRotation()); 626 else 627 duk_push_null(ctx); 628 return DukValue::take_from_stack(ctx); 629 } seatRotation_set(uint8_t value)630 void ScTileElement::seatRotation_set(uint8_t value) 631 { 632 ThrowIfGameStateNotMutable(); 633 auto el = _element->AsTrack(); 634 if (el != nullptr) 635 if (get_ride(el->GetRideIndex())->type != RIDE_TYPE_MAZE) 636 { 637 el->SetSeatRotation(value); 638 Invalidate(); 639 } 640 } 641 brakeBoosterSpeed_get() const642 DukValue ScTileElement::brakeBoosterSpeed_get() const 643 { 644 auto ctx = GetContext()->GetScriptEngine().GetContext(); 645 auto el = _element->AsTrack(); 646 if (el != nullptr && TrackTypeHasSpeedSetting(el->GetTrackType())) 647 duk_push_int(ctx, el->GetBrakeBoosterSpeed()); 648 else 649 duk_push_null(ctx); 650 return DukValue::take_from_stack(ctx); 651 } brakeBoosterSpeed_set(uint8_t value)652 void ScTileElement::brakeBoosterSpeed_set(uint8_t value) 653 { 654 ThrowIfGameStateNotMutable(); 655 auto el = _element->AsTrack(); 656 if (el != nullptr) 657 if (TrackTypeHasSpeedSetting(el->GetTrackType())) 658 { 659 el->SetBrakeBoosterSpeed(value); 660 Invalidate(); 661 } 662 } 663 isInverted_get() const664 DukValue ScTileElement::isInverted_get() const 665 { 666 auto ctx = GetContext()->GetScriptEngine().GetContext(); 667 auto el = _element->AsTrack(); 668 if (el != nullptr) 669 duk_push_boolean(ctx, el->IsInverted()); 670 else 671 duk_push_null(ctx); 672 return DukValue::take_from_stack(ctx); 673 } isInverted_set(bool value)674 void ScTileElement::isInverted_set(bool value) 675 { 676 ThrowIfGameStateNotMutable(); 677 auto el = _element->AsTrack(); 678 if (el != nullptr) 679 { 680 el->SetInverted(value); 681 Invalidate(); 682 } 683 } 684 hasCableLift_get() const685 DukValue ScTileElement::hasCableLift_get() const 686 { 687 auto ctx = GetContext()->GetScriptEngine().GetContext(); 688 auto el = _element->AsTrack(); 689 if (el != nullptr) 690 duk_push_boolean(ctx, el->HasCableLift()); 691 else 692 duk_push_null(ctx); 693 return DukValue::take_from_stack(ctx); 694 } hasCableLift_set(bool value)695 void ScTileElement::hasCableLift_set(bool value) 696 { 697 ThrowIfGameStateNotMutable(); 698 auto el = _element->AsTrack(); 699 if (el != nullptr) 700 { 701 el->SetHasCableLift(value); 702 Invalidate(); 703 } 704 } 705 object_get() const706 DukValue ScTileElement::object_get() const 707 { 708 auto ctx = GetContext()->GetScriptEngine().GetContext(); 709 switch (_element->GetType()) 710 { 711 case TILE_ELEMENT_TYPE_PATH: 712 { 713 auto el = _element->AsPath(); 714 duk_push_int(ctx, el->GetLegacyPathEntryIndex()); 715 break; 716 } 717 case TILE_ELEMENT_TYPE_SMALL_SCENERY: 718 { 719 auto el = _element->AsSmallScenery(); 720 duk_push_int(ctx, el->GetEntryIndex()); 721 break; 722 } 723 case TILE_ELEMENT_TYPE_LARGE_SCENERY: 724 { 725 auto el = _element->AsLargeScenery(); 726 duk_push_int(ctx, el->GetEntryIndex()); 727 break; 728 } 729 case TILE_ELEMENT_TYPE_WALL: 730 { 731 auto el = _element->AsWall(); 732 duk_push_int(ctx, el->GetEntryIndex()); 733 break; 734 } 735 case TILE_ELEMENT_TYPE_ENTRANCE: 736 { 737 auto el = _element->AsEntrance(); 738 duk_push_int(ctx, el->GetEntranceType()); 739 break; 740 } 741 default: 742 { 743 duk_push_null(ctx); 744 break; 745 } 746 } 747 return DukValue::take_from_stack(ctx); 748 } object_set(uint32_t value)749 void ScTileElement::object_set(uint32_t value) 750 { 751 ThrowIfGameStateNotMutable(); 752 switch (_element->GetType()) 753 { 754 case TILE_ELEMENT_TYPE_PATH: 755 { 756 auto el = _element->AsPath(); 757 el->SetLegacyPathEntryIndex(value & 0xFF); 758 Invalidate(); 759 break; 760 } 761 case TILE_ELEMENT_TYPE_SMALL_SCENERY: 762 { 763 auto el = _element->AsSmallScenery(); 764 el->SetEntryIndex(value & 0xFF); 765 Invalidate(); 766 break; 767 } 768 case TILE_ELEMENT_TYPE_LARGE_SCENERY: 769 { 770 auto el = _element->AsLargeScenery(); 771 el->SetEntryIndex(value); 772 Invalidate(); 773 break; 774 } 775 case TILE_ELEMENT_TYPE_WALL: 776 { 777 auto el = _element->AsWall(); 778 el->SetEntryIndex(value & 0xFFFF); 779 Invalidate(); 780 break; 781 } 782 case TILE_ELEMENT_TYPE_ENTRANCE: 783 { 784 auto el = _element->AsEntrance(); 785 el->SetEntranceType(value & 0xFF); 786 Invalidate(); 787 break; 788 } 789 } 790 } 791 isHidden_get() const792 bool ScTileElement::isHidden_get() const 793 { 794 // TODO: Simply return the 'hidden' field once corrupt elements are superseded. 795 const TileElement* element = map_get_first_element_at(_coords); 796 bool previousElementWasUsefulCorrupt = false; 797 do 798 { 799 if (element == _element) 800 return previousElementWasUsefulCorrupt; 801 802 if (element->GetType() == TILE_ELEMENT_TYPE_CORRUPT) 803 previousElementWasUsefulCorrupt = !previousElementWasUsefulCorrupt; 804 else 805 previousElementWasUsefulCorrupt = false; 806 } while (!(element++)->IsLastForTile()); 807 808 Guard::Assert(false); 809 return false; 810 } isHidden_set(bool hide)811 void ScTileElement::isHidden_set(bool hide) 812 { 813 // TODO: Simply update the 'hidden' field once corrupt elements are superseded. 814 ThrowIfGameStateNotMutable(); 815 const bool isHidden = isHidden_get(); 816 if (hide == isHidden) 817 return; 818 819 if (hide) 820 { 821 // Get index of our current element (has to be done now before inserting the corrupt element) 822 const auto elementIndex = _element - map_get_first_element_at(_coords); 823 824 // Insert corrupt element at the end of the list for this tile 825 // Note: Z = MAX_ELEMENT_HEIGHT to guarantee this 826 TileElement* insertedElement = tile_element_insert( 827 { _coords, MAX_ELEMENT_HEIGHT * COORDS_Z_STEP }, 0, TileElementType::Corrupt); 828 if (insertedElement == nullptr) 829 { 830 // TODO: Show error 831 return; 832 } 833 834 // Since inserting a new element may move the tile elements in memory, we have to update the local pointer 835 _element = map_get_first_element_at(_coords) + elementIndex; 836 837 // Move the corrupt element down in the list until it's right under our element 838 while (insertedElement > _element) 839 { 840 std::swap<TileElement>(*insertedElement, *(insertedElement - 1)); 841 insertedElement--; 842 843 // Un-swap the last-for-tile flag 844 if (insertedElement->IsLastForTile()) 845 { 846 insertedElement->SetLastForTile(false); 847 (insertedElement + 1)->SetLastForTile(true); 848 } 849 } 850 851 // Now the corrupt element took the hidden element's place, increment it by one 852 _element++; 853 854 // Update base and clearance heights of inserted corrupt element to match the element to hide 855 insertedElement->base_height = insertedElement->clearance_height = _element->base_height; 856 } 857 else 858 { 859 TileElement* const elementToRemove = _element - 1; 860 Guard::Assert(elementToRemove->GetType() == TILE_ELEMENT_TYPE_CORRUPT); 861 tile_element_remove(elementToRemove); 862 _element--; 863 } 864 865 Invalidate(); 866 } 867 age_get() const868 DukValue ScTileElement::age_get() const 869 { 870 auto ctx = GetContext()->GetScriptEngine().GetContext(); 871 auto el = _element->AsSmallScenery(); 872 if (el != nullptr) 873 duk_push_int(ctx, el->GetAge()); 874 else 875 duk_push_null(ctx); 876 return DukValue::take_from_stack(ctx); 877 } age_set(uint8_t value)878 void ScTileElement::age_set(uint8_t value) 879 { 880 ThrowIfGameStateNotMutable(); 881 auto el = _element->AsSmallScenery(); 882 if (el != nullptr) 883 { 884 el->SetAge(value); 885 Invalidate(); 886 } 887 } 888 quadrant_get() const889 DukValue ScTileElement::quadrant_get() const 890 { 891 auto ctx = GetContext()->GetScriptEngine().GetContext(); 892 auto el = _element->AsSmallScenery(); 893 if (el != nullptr) 894 duk_push_int(ctx, el->GetSceneryQuadrant()); 895 else 896 duk_push_null(ctx); 897 return DukValue::take_from_stack(ctx); 898 } quadrant_set(uint8_t value)899 void ScTileElement::quadrant_set(uint8_t value) 900 { 901 ThrowIfGameStateNotMutable(); 902 auto el = _element->AsSmallScenery(); 903 if (el != nullptr) 904 { 905 el->SetSceneryQuadrant(value); 906 Invalidate(); 907 } 908 } 909 occupiedQuadrants_get() const910 uint8_t ScTileElement::occupiedQuadrants_get() const 911 { 912 return _element->GetOccupiedQuadrants(); 913 } occupiedQuadrants_set(uint8_t value)914 void ScTileElement::occupiedQuadrants_set(uint8_t value) 915 { 916 ThrowIfGameStateNotMutable(); 917 _element->SetOccupiedQuadrants(value); 918 Invalidate(); 919 } 920 isGhost_get() const921 bool ScTileElement::isGhost_get() const 922 { 923 return _element->IsGhost(); 924 } isGhost_set(bool value)925 void ScTileElement::isGhost_set(bool value) 926 { 927 ThrowIfGameStateNotMutable(); 928 _element->SetGhost(value); 929 Invalidate(); 930 } 931 primaryColour_get() const932 DukValue ScTileElement::primaryColour_get() const 933 { 934 auto ctx = GetContext()->GetScriptEngine().GetContext(); 935 switch (_element->GetType()) 936 { 937 case TILE_ELEMENT_TYPE_SMALL_SCENERY: 938 { 939 auto el = _element->AsSmallScenery(); 940 duk_push_int(ctx, el->GetPrimaryColour()); 941 break; 942 } 943 case TILE_ELEMENT_TYPE_LARGE_SCENERY: 944 { 945 auto el = _element->AsLargeScenery(); 946 duk_push_int(ctx, el->GetPrimaryColour()); 947 break; 948 } 949 case TILE_ELEMENT_TYPE_WALL: 950 { 951 auto el = _element->AsWall(); 952 duk_push_int(ctx, el->GetPrimaryColour()); 953 break; 954 } 955 default: 956 { 957 duk_push_null(ctx); 958 break; 959 } 960 } 961 return DukValue::take_from_stack(ctx); 962 } primaryColour_set(uint8_t value)963 void ScTileElement::primaryColour_set(uint8_t value) 964 { 965 ThrowIfGameStateNotMutable(); 966 switch (_element->GetType()) 967 { 968 case TILE_ELEMENT_TYPE_SMALL_SCENERY: 969 { 970 auto el = _element->AsSmallScenery(); 971 el->SetPrimaryColour(value); 972 Invalidate(); 973 break; 974 } 975 case TILE_ELEMENT_TYPE_LARGE_SCENERY: 976 { 977 auto el = _element->AsLargeScenery(); 978 el->SetPrimaryColour(value); 979 Invalidate(); 980 break; 981 } 982 case TILE_ELEMENT_TYPE_WALL: 983 { 984 auto el = _element->AsWall(); 985 el->SetPrimaryColour(value); 986 Invalidate(); 987 break; 988 } 989 } 990 } 991 secondaryColour_get() const992 DukValue ScTileElement::secondaryColour_get() const 993 { 994 auto ctx = GetContext()->GetScriptEngine().GetContext(); 995 switch (_element->GetType()) 996 { 997 case TILE_ELEMENT_TYPE_SMALL_SCENERY: 998 { 999 auto el = _element->AsSmallScenery(); 1000 duk_push_int(ctx, el->GetSecondaryColour()); 1001 break; 1002 } 1003 case TILE_ELEMENT_TYPE_LARGE_SCENERY: 1004 { 1005 auto el = _element->AsLargeScenery(); 1006 duk_push_int(ctx, el->GetSecondaryColour()); 1007 break; 1008 } 1009 case TILE_ELEMENT_TYPE_WALL: 1010 { 1011 auto el = _element->AsWall(); 1012 duk_push_int(ctx, el->GetSecondaryColour()); 1013 break; 1014 } 1015 default: 1016 { 1017 duk_push_null(ctx); 1018 break; 1019 } 1020 } 1021 return DukValue::take_from_stack(ctx); 1022 } secondaryColour_set(uint8_t value)1023 void ScTileElement::secondaryColour_set(uint8_t value) 1024 { 1025 ThrowIfGameStateNotMutable(); 1026 switch (_element->GetType()) 1027 { 1028 case TILE_ELEMENT_TYPE_SMALL_SCENERY: 1029 { 1030 auto el = _element->AsSmallScenery(); 1031 el->SetSecondaryColour(value); 1032 Invalidate(); 1033 break; 1034 } 1035 case TILE_ELEMENT_TYPE_LARGE_SCENERY: 1036 { 1037 auto el = _element->AsLargeScenery(); 1038 el->SetSecondaryColour(value); 1039 Invalidate(); 1040 break; 1041 } 1042 case TILE_ELEMENT_TYPE_WALL: 1043 { 1044 auto el = _element->AsWall(); 1045 el->SetSecondaryColour(value); 1046 Invalidate(); 1047 break; 1048 } 1049 } 1050 } 1051 tertiaryColour_get() const1052 DukValue ScTileElement::tertiaryColour_get() const 1053 { 1054 auto ctx = GetContext()->GetScriptEngine().GetContext(); 1055 auto el = _element->AsWall(); 1056 if (el != nullptr) 1057 duk_push_int(ctx, el->GetTertiaryColour()); 1058 else 1059 duk_push_null(ctx); 1060 return DukValue::take_from_stack(ctx); 1061 } tertiaryColour_set(uint8_t value)1062 void ScTileElement::tertiaryColour_set(uint8_t value) 1063 { 1064 ThrowIfGameStateNotMutable(); 1065 auto el = _element->AsWall(); 1066 if (el != nullptr) 1067 { 1068 el->SetTertiaryColour(value); 1069 Invalidate(); 1070 } 1071 } 1072 bannerIndex_get() const1073 DukValue ScTileElement::bannerIndex_get() const 1074 { 1075 auto ctx = GetContext()->GetScriptEngine().GetContext(); 1076 BannerIndex idx = _element->GetBannerIndex(); 1077 if (idx == BANNER_INDEX_NULL) 1078 duk_push_null(ctx); 1079 else 1080 duk_push_int(ctx, idx); 1081 return DukValue::take_from_stack(ctx); 1082 } bannerIndex_set(uint16_t value)1083 void ScTileElement::bannerIndex_set(uint16_t value) 1084 { 1085 ThrowIfGameStateNotMutable(); 1086 switch (_element->GetType()) 1087 { 1088 case TILE_ELEMENT_TYPE_LARGE_SCENERY: 1089 { 1090 auto el = _element->AsLargeScenery(); 1091 el->SetBannerIndex(value); 1092 Invalidate(); 1093 break; 1094 } 1095 case TILE_ELEMENT_TYPE_WALL: 1096 { 1097 auto el = _element->AsWall(); 1098 el->SetBannerIndex(value); 1099 Invalidate(); 1100 break; 1101 } 1102 case TILE_ELEMENT_TYPE_BANNER: 1103 { 1104 auto el = _element->AsBanner(); 1105 el->SetIndex(value); 1106 Invalidate(); 1107 break; 1108 } 1109 } 1110 } 1111 1112 // Deprecated in favor of seperate 'edges' and 'corners' properties, 1113 // left here to maintain compatibility with older plugins. 1114 /** @deprecated */ edgesAndCorners_get() const1115 uint8_t ScTileElement::edgesAndCorners_get() const 1116 { 1117 auto el = _element->AsPath(); 1118 return el != nullptr ? el->GetEdgesAndCorners() : 0; 1119 } 1120 /** @deprecated */ edgesAndCorners_set(uint8_t value)1121 void ScTileElement::edgesAndCorners_set(uint8_t value) 1122 { 1123 ThrowIfGameStateNotMutable(); 1124 auto el = _element->AsPath(); 1125 if (el != nullptr) 1126 { 1127 el->SetEdgesAndCorners(value); 1128 Invalidate(); 1129 } 1130 } 1131 edges_get() const1132 DukValue ScTileElement::edges_get() const 1133 { 1134 auto ctx = GetContext()->GetScriptEngine().GetContext(); 1135 auto el = _element->AsPath(); 1136 if (el != nullptr) 1137 duk_push_int(ctx, el->GetEdges()); 1138 else 1139 duk_push_null(ctx); 1140 return DukValue::take_from_stack(ctx); 1141 } edges_set(uint8_t value)1142 void ScTileElement::edges_set(uint8_t value) 1143 { 1144 ThrowIfGameStateNotMutable(); 1145 auto el = _element->AsPath(); 1146 if (el != nullptr) 1147 { 1148 el->SetEdges(value); 1149 Invalidate(); 1150 } 1151 } 1152 corners_get() const1153 DukValue ScTileElement::corners_get() const 1154 { 1155 auto ctx = GetContext()->GetScriptEngine().GetContext(); 1156 auto el = _element->AsPath(); 1157 if (el != nullptr) 1158 duk_push_int(ctx, el->GetCorners()); 1159 else 1160 duk_push_null(ctx); 1161 return DukValue::take_from_stack(ctx); 1162 } corners_set(uint8_t value)1163 void ScTileElement::corners_set(uint8_t value) 1164 { 1165 ThrowIfGameStateNotMutable(); 1166 auto el = _element->AsPath(); 1167 if (el != nullptr) 1168 { 1169 el->SetCorners(value); 1170 Invalidate(); 1171 } 1172 } 1173 slopeDirection_get() const1174 DukValue ScTileElement::slopeDirection_get() const 1175 { 1176 auto ctx = GetContext()->GetScriptEngine().GetContext(); 1177 auto el = _element->AsPath(); 1178 if (el != nullptr && el->IsSloped()) 1179 duk_push_int(ctx, el->GetSlopeDirection()); 1180 else 1181 duk_push_null(ctx); 1182 return DukValue::take_from_stack(ctx); 1183 } slopeDirection_set(const DukValue & value)1184 void ScTileElement::slopeDirection_set(const DukValue& value) 1185 { 1186 ThrowIfGameStateNotMutable(); 1187 auto el = _element->AsPath(); 1188 if (el != nullptr) 1189 { 1190 if (value.type() == DukValue::Type::NUMBER) 1191 { 1192 el->SetSloped(true); 1193 el->SetSlopeDirection(value.as_int()); 1194 } 1195 else 1196 { 1197 el->SetSloped(false); 1198 el->SetSlopeDirection(0); 1199 } 1200 Invalidate(); 1201 } 1202 } 1203 isQueue_get() const1204 DukValue ScTileElement::isQueue_get() const 1205 { 1206 auto ctx = GetContext()->GetScriptEngine().GetContext(); 1207 auto el = _element->AsPath(); 1208 if (el != nullptr) 1209 duk_push_boolean(ctx, el->IsQueue()); 1210 else 1211 duk_push_null(ctx); 1212 return DukValue::take_from_stack(ctx); 1213 } isQueue_set(bool value)1214 void ScTileElement::isQueue_set(bool value) 1215 { 1216 ThrowIfGameStateNotMutable(); 1217 auto el = _element->AsPath(); 1218 if (el != nullptr) 1219 { 1220 el->SetIsQueue(value); 1221 Invalidate(); 1222 } 1223 } 1224 queueBannerDirection_get() const1225 DukValue ScTileElement::queueBannerDirection_get() const 1226 { 1227 auto ctx = GetContext()->GetScriptEngine().GetContext(); 1228 auto el = _element->AsPath(); 1229 if (el != nullptr && el->HasQueueBanner()) 1230 duk_push_int(ctx, el->GetQueueBannerDirection()); 1231 else 1232 duk_push_null(ctx); 1233 return DukValue::take_from_stack(ctx); 1234 } queueBannerDirection_set(const DukValue & value)1235 void ScTileElement::queueBannerDirection_set(const DukValue& value) 1236 { 1237 ThrowIfGameStateNotMutable(); 1238 auto el = _element->AsPath(); 1239 if (el != nullptr) 1240 { 1241 if (value.type() == DukValue::Type::NUMBER) 1242 { 1243 el->SetHasQueueBanner(true); 1244 el->SetQueueBannerDirection(value.as_int()); 1245 } 1246 else 1247 { 1248 el->SetHasQueueBanner(false); 1249 el->SetQueueBannerDirection(0); 1250 } 1251 Invalidate(); 1252 } 1253 } 1254 isBlockedByVehicle_get() const1255 DukValue ScTileElement::isBlockedByVehicle_get() const 1256 { 1257 auto ctx = GetContext()->GetScriptEngine().GetContext(); 1258 auto el = _element->AsPath(); 1259 if (el != nullptr) 1260 duk_push_boolean(ctx, el->IsBlockedByVehicle()); 1261 else 1262 duk_push_null(ctx); 1263 return DukValue::take_from_stack(ctx); 1264 } isBlockedByVehicle_set(bool value)1265 void ScTileElement::isBlockedByVehicle_set(bool value) 1266 { 1267 ThrowIfGameStateNotMutable(); 1268 auto el = _element->AsPath(); 1269 if (el != nullptr) 1270 { 1271 el->SetIsBlockedByVehicle(value); 1272 Invalidate(); 1273 } 1274 } 1275 isWide_get() const1276 DukValue ScTileElement::isWide_get() const 1277 { 1278 auto ctx = GetContext()->GetScriptEngine().GetContext(); 1279 auto el = _element->AsPath(); 1280 if (el != nullptr) 1281 duk_push_boolean(ctx, el->IsWide()); 1282 else 1283 duk_push_null(ctx); 1284 return DukValue::take_from_stack(ctx); 1285 } isWide_set(bool value)1286 void ScTileElement::isWide_set(bool value) 1287 { 1288 ThrowIfGameStateNotMutable(); 1289 auto el = _element->AsPath(); 1290 if (el != nullptr) 1291 { 1292 el->SetWide(value); 1293 Invalidate(); 1294 } 1295 } 1296 addition_get() const1297 DukValue ScTileElement::addition_get() const 1298 { 1299 auto ctx = GetContext()->GetScriptEngine().GetContext(); 1300 auto el = _element->AsPath(); 1301 if (el != nullptr && el->HasAddition()) 1302 duk_push_int(ctx, el->GetAddition() - 1); 1303 else 1304 duk_push_null(ctx); 1305 return DukValue::take_from_stack(ctx); 1306 } addition_set(const DukValue & value)1307 void ScTileElement::addition_set(const DukValue& value) 1308 { 1309 ThrowIfGameStateNotMutable(); 1310 auto el = _element->AsPath(); 1311 if (el != nullptr) 1312 { 1313 if (value.type() == DukValue::Type::NUMBER) 1314 { 1315 auto addition = value.as_int(); 1316 if (addition >= 0 && addition <= 254) 1317 { 1318 el->SetAddition(addition + 1); 1319 } 1320 } 1321 else 1322 { 1323 el->SetAddition(0); 1324 } 1325 Invalidate(); 1326 } 1327 } 1328 additionStatus_get() const1329 DukValue ScTileElement::additionStatus_get() const 1330 { 1331 auto ctx = GetContext()->GetScriptEngine().GetContext(); 1332 auto el = _element->AsPath(); 1333 if (el != nullptr && el->HasAddition()) 1334 duk_push_int(ctx, el->GetAdditionStatus()); 1335 else 1336 duk_push_null(ctx); 1337 return DukValue::take_from_stack(ctx); 1338 } additionStatus_set(uint8_t value)1339 void ScTileElement::additionStatus_set(uint8_t value) 1340 { 1341 ThrowIfGameStateNotMutable(); 1342 auto el = _element->AsPath(); 1343 if (el != nullptr) 1344 if (el->HasAddition()) 1345 { 1346 el->SetAdditionStatus(value); 1347 Invalidate(); 1348 } 1349 } 1350 isAdditionBroken_get() const1351 DukValue ScTileElement::isAdditionBroken_get() const 1352 { 1353 auto ctx = GetContext()->GetScriptEngine().GetContext(); 1354 auto el = _element->AsPath(); 1355 if (el != nullptr && el->HasAddition()) 1356 duk_push_boolean(ctx, el->IsBroken()); 1357 else 1358 duk_push_null(ctx); 1359 return DukValue::take_from_stack(ctx); 1360 } isAdditionBroken_set(bool value)1361 void ScTileElement::isAdditionBroken_set(bool value) 1362 { 1363 ThrowIfGameStateNotMutable(); 1364 auto el = _element->AsPath(); 1365 if (el != nullptr) 1366 { 1367 el->SetIsBroken(value); 1368 Invalidate(); 1369 } 1370 } 1371 isAdditionGhost_get() const1372 DukValue ScTileElement::isAdditionGhost_get() const 1373 { 1374 auto ctx = GetContext()->GetScriptEngine().GetContext(); 1375 auto el = _element->AsPath(); 1376 if (el != nullptr && el->HasAddition()) 1377 duk_push_boolean(ctx, el->AdditionIsGhost()); 1378 else 1379 duk_push_null(ctx); 1380 return DukValue::take_from_stack(ctx); 1381 } isAdditionGhost_set(bool value)1382 void ScTileElement::isAdditionGhost_set(bool value) 1383 { 1384 ThrowIfGameStateNotMutable(); 1385 auto el = _element->AsPath(); 1386 if (el != nullptr) 1387 { 1388 el->SetAdditionIsGhost(value); 1389 Invalidate(); 1390 } 1391 } 1392 footpathObject_get() const1393 DukValue ScTileElement::footpathObject_get() const 1394 { 1395 auto ctx = GetContext()->GetScriptEngine().GetContext(); 1396 auto el = _element->AsEntrance(); 1397 if (el != nullptr) 1398 duk_push_int(ctx, el->GetLegacyPathEntryIndex()); 1399 else 1400 duk_push_null(ctx); 1401 return DukValue::take_from_stack(ctx); 1402 } footpathObject_set(uint8_t value)1403 void ScTileElement::footpathObject_set(uint8_t value) 1404 { 1405 ThrowIfGameStateNotMutable(); 1406 auto el = _element->AsEntrance(); 1407 if (el != nullptr) 1408 { 1409 el->SetLegacyPathEntryIndex(value); 1410 Invalidate(); 1411 } 1412 } 1413 direction_get() const1414 DukValue ScTileElement::direction_get() const 1415 { 1416 auto ctx = GetContext()->GetScriptEngine().GetContext(); 1417 switch (_element->GetType()) 1418 { 1419 case TILE_ELEMENT_TYPE_BANNER: 1420 { 1421 auto el = _element->AsBanner(); 1422 duk_push_int(ctx, el->GetPosition()); 1423 break; 1424 } 1425 case TILE_ELEMENT_TYPE_PATH: 1426 case TILE_ELEMENT_TYPE_SURFACE: 1427 { 1428 duk_push_null(ctx); 1429 break; 1430 } 1431 default: 1432 { 1433 duk_push_int(ctx, _element->GetDirection()); 1434 break; 1435 } 1436 } 1437 return DukValue::take_from_stack(ctx); 1438 } direction_set(uint8_t value)1439 void ScTileElement::direction_set(uint8_t value) 1440 { 1441 ThrowIfGameStateNotMutable(); 1442 switch (_element->GetType()) 1443 { 1444 case TILE_ELEMENT_TYPE_BANNER: 1445 { 1446 auto el = _element->AsBanner(); 1447 el->SetPosition(value); 1448 Invalidate(); 1449 break; 1450 } 1451 case TILE_ELEMENT_TYPE_PATH: 1452 case TILE_ELEMENT_TYPE_SURFACE: 1453 { 1454 break; 1455 } 1456 default: 1457 { 1458 _element->SetDirection(value); 1459 Invalidate(); 1460 } 1461 } 1462 } 1463 Invalidate()1464 void ScTileElement::Invalidate() 1465 { 1466 map_invalidate_tile_full(_coords); 1467 } 1468 Register(duk_context * ctx)1469 void ScTileElement::Register(duk_context* ctx) 1470 { 1471 // All 1472 dukglue_register_property(ctx, &ScTileElement::type_get, &ScTileElement::type_set, "type"); 1473 dukglue_register_property(ctx, &ScTileElement::baseHeight_get, &ScTileElement::baseHeight_set, "baseHeight"); 1474 dukglue_register_property(ctx, &ScTileElement::baseZ_get, &ScTileElement::baseZ_set, "baseZ"); 1475 dukglue_register_property( 1476 ctx, &ScTileElement::clearanceHeight_get, &ScTileElement::clearanceHeight_set, "clearanceHeight"); 1477 dukglue_register_property(ctx, &ScTileElement::clearanceZ_get, &ScTileElement::clearanceZ_set, "clearanceZ"); 1478 dukglue_register_property( 1479 ctx, &ScTileElement::occupiedQuadrants_get, &ScTileElement::occupiedQuadrants_set, "occupiedQuadrants"); 1480 dukglue_register_property(ctx, &ScTileElement::isGhost_get, &ScTileElement::isGhost_set, "isGhost"); 1481 dukglue_register_property(ctx, &ScTileElement::isHidden_get, &ScTileElement::isHidden_set, "isHidden"); 1482 1483 // Track | Small Scenery | Wall | Entrance | Large Scenery | Banner 1484 dukglue_register_property(ctx, &ScTileElement::direction_get, &ScTileElement::direction_set, "direction"); 1485 1486 // Path | Small Scenery | Wall | Entrance | Large Scenery 1487 dukglue_register_property(ctx, &ScTileElement::object_get, &ScTileElement::object_set, "object"); 1488 1489 // Small Scenery | Wall | Large Scenery 1490 dukglue_register_property(ctx, &ScTileElement::primaryColour_get, &ScTileElement::primaryColour_set, "primaryColour"); 1491 dukglue_register_property( 1492 ctx, &ScTileElement::secondaryColour_get, &ScTileElement::secondaryColour_set, "secondaryColour"); 1493 1494 // Wall | Large Scenery | Banner 1495 dukglue_register_property(ctx, &ScTileElement::bannerIndex_get, &ScTileElement::bannerIndex_set, "bannerIndex"); 1496 1497 // Path | Track | Entrance 1498 dukglue_register_property(ctx, &ScTileElement::ride_get, &ScTileElement::ride_set, "ride"); 1499 dukglue_register_property(ctx, &ScTileElement::station_get, &ScTileElement::station_set, "station"); 1500 1501 // Track | Entrance | Large Scenery 1502 dukglue_register_property(ctx, &ScTileElement::sequence_get, &ScTileElement::sequence_set, "sequence"); 1503 1504 // Surface | Wall 1505 dukglue_register_property(ctx, &ScTileElement::slope_get, &ScTileElement::slope_set, "slope"); 1506 1507 // Surface only 1508 dukglue_register_property(ctx, &ScTileElement::waterHeight_get, &ScTileElement::waterHeight_set, "waterHeight"); 1509 dukglue_register_property(ctx, &ScTileElement::surfaceStyle_get, &ScTileElement::surfaceStyle_set, "surfaceStyle"); 1510 dukglue_register_property(ctx, &ScTileElement::edgeStyle_get, &ScTileElement::edgeStyle_set, "edgeStyle"); 1511 dukglue_register_property(ctx, &ScTileElement::grassLength_get, &ScTileElement::grassLength_set, "grassLength"); 1512 dukglue_register_property(ctx, &ScTileElement::hasOwnership_get, nullptr, "hasOwnership"); 1513 dukglue_register_property(ctx, &ScTileElement::hasConstructionRights_get, nullptr, "hasConstructionRights"); 1514 dukglue_register_property(ctx, &ScTileElement::ownership_get, &ScTileElement::ownership_set, "ownership"); 1515 dukglue_register_property(ctx, &ScTileElement::parkFences_get, &ScTileElement::parkFences_set, "parkFences"); 1516 1517 // Footpath only 1518 dukglue_register_property( 1519 ctx, &ScTileElement::edgesAndCorners_get, &ScTileElement::edgesAndCorners_set, "edgesAndCorners"); 1520 dukglue_register_property(ctx, &ScTileElement::edges_get, &ScTileElement::edges_set, "edges"); 1521 dukglue_register_property(ctx, &ScTileElement::corners_get, &ScTileElement::corners_set, "corners"); 1522 dukglue_register_property( 1523 ctx, &ScTileElement::slopeDirection_get, &ScTileElement::slopeDirection_set, "slopeDirection"); 1524 dukglue_register_property(ctx, &ScTileElement::isQueue_get, &ScTileElement::isQueue_set, "isQueue"); 1525 dukglue_register_property( 1526 ctx, &ScTileElement::queueBannerDirection_get, &ScTileElement::queueBannerDirection_set, "queueBannerDirection"); 1527 dukglue_register_property(ctx, &ScTileElement::queueBannerDirection_get, &ScTileElement::edges_set, "test"); 1528 1529 dukglue_register_property( 1530 ctx, &ScTileElement::isBlockedByVehicle_get, &ScTileElement::isBlockedByVehicle_set, "isBlockedByVehicle"); 1531 dukglue_register_property(ctx, &ScTileElement::isWide_get, &ScTileElement::isWide_set, "isWide"); 1532 1533 dukglue_register_property(ctx, &ScTileElement::addition_get, &ScTileElement::addition_set, "addition"); 1534 dukglue_register_property( 1535 ctx, &ScTileElement::additionStatus_get, &ScTileElement::additionStatus_set, "additionStatus"); 1536 dukglue_register_property( 1537 ctx, &ScTileElement::isAdditionBroken_get, &ScTileElement::isAdditionBroken_set, "isAdditionBroken"); 1538 dukglue_register_property( 1539 ctx, &ScTileElement::isAdditionGhost_get, &ScTileElement::isAdditionGhost_set, "isAdditionGhost"); 1540 1541 // Track only 1542 dukglue_register_property(ctx, &ScTileElement::trackType_get, &ScTileElement::trackType_set, "trackType"); 1543 dukglue_register_property(ctx, &ScTileElement::mazeEntry_get, &ScTileElement::mazeEntry_set, "mazeEntry"); 1544 dukglue_register_property(ctx, &ScTileElement::colourScheme_get, &ScTileElement::colourScheme_set, "colourScheme"); 1545 dukglue_register_property(ctx, &ScTileElement::seatRotation_get, &ScTileElement::seatRotation_set, "seatRotation"); 1546 dukglue_register_property( 1547 ctx, &ScTileElement::brakeBoosterSpeed_get, &ScTileElement::brakeBoosterSpeed_set, "brakeBoosterSpeed"); 1548 dukglue_register_property(ctx, &ScTileElement::hasChainLift_get, &ScTileElement::hasChainLift_set, "hasChainLift"); 1549 dukglue_register_property(ctx, &ScTileElement::isInverted_get, &ScTileElement::isInverted_set, "isInverted"); 1550 dukglue_register_property(ctx, &ScTileElement::hasCableLift_get, &ScTileElement::hasCableLift_set, "hasCableLift"); 1551 1552 // Small Scenery only 1553 dukglue_register_property(ctx, &ScTileElement::age_get, &ScTileElement::age_set, "age"); 1554 dukglue_register_property(ctx, &ScTileElement::quadrant_get, &ScTileElement::quadrant_set, "quadrant"); 1555 1556 // Wall only 1557 dukglue_register_property( 1558 ctx, &ScTileElement::tertiaryColour_get, &ScTileElement::tertiaryColour_set, "tertiaryColour"); 1559 1560 // Entrance only 1561 dukglue_register_property( 1562 ctx, &ScTileElement::footpathObject_get, &ScTileElement::footpathObject_set, "footpathObject"); 1563 } 1564 1565 } // namespace OpenRCT2::Scripting 1566 1567 #endif 1568