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 #include "ScVehicle.hpp" 11 12 #include "../ride/ScRide.hpp" 13 14 #ifdef ENABLE_SCRIPTING 15 16 namespace OpenRCT2::Scripting 17 { 18 static const DukEnumMap<Vehicle::Status> VehicleStatusMap({ 19 { "moving_to_end_of_station", Vehicle::Status::MovingToEndOfStation }, 20 { "waiting_for_passengers", Vehicle::Status::WaitingForPassengers }, 21 { "waiting_to_depart", Vehicle::Status::WaitingToDepart }, 22 { "departing", Vehicle::Status::Departing }, 23 { "travelling", Vehicle::Status::Travelling }, 24 { "arriving", Vehicle::Status::Arriving }, 25 { "unloading_passengers", Vehicle::Status::UnloadingPassengers }, 26 { "travelling_boat", Vehicle::Status::TravellingBoat }, 27 { "crashing", Vehicle::Status::Crashing }, 28 { "crashed", Vehicle::Status::Crashed }, 29 { "travelling_dodgems", Vehicle::Status::TravellingDodgems }, 30 { "swinging", Vehicle::Status::Swinging }, 31 { "rotating", Vehicle::Status::Rotating }, 32 { "ferris_wheel_rotating", Vehicle::Status::FerrisWheelRotating }, 33 { "simulator_operating", Vehicle::Status::SimulatorOperating }, 34 { "showing_film", Vehicle::Status::ShowingFilm }, 35 { "space_rings_operating", Vehicle::Status::SpaceRingsOperating }, 36 { "top_spin_operating", Vehicle::Status::TopSpinOperating }, 37 { "haunted_house_operating", Vehicle::Status::HauntedHouseOperating }, 38 { "doing_circus_show", Vehicle::Status::DoingCircusShow }, 39 { "crooked_house_operating", Vehicle::Status::CrookedHouseOperating }, 40 { "waiting_for_cable_lift", Vehicle::Status::WaitingForCableLift }, 41 { "travelling_cable_lift", Vehicle::Status::TravellingCableLift }, 42 { "stopping", Vehicle::Status::Stopping }, 43 { "waiting_for_passengers_17", Vehicle::Status::WaitingForPassengers17 }, 44 { "waiting_to_start", Vehicle::Status::WaitingToStart }, 45 { "starting", Vehicle::Status::Starting }, 46 { "operating_1a", Vehicle::Status::Operating1A }, 47 { "stopping_1b", Vehicle::Status::Stopping1B }, 48 { "unloading_passengers_1c", Vehicle::Status::UnloadingPassengers1C }, 49 { "stopped_by_block_brake", Vehicle::Status::StoppedByBlockBrakes }, 50 }); 51 ScVehicle(uint16_t id)52 ScVehicle::ScVehicle(uint16_t id) 53 : ScEntity(id) 54 { 55 } 56 Register(duk_context * ctx)57 void ScVehicle::Register(duk_context* ctx) 58 { 59 dukglue_set_base_class<ScEntity, ScVehicle>(ctx); 60 dukglue_register_property(ctx, &ScVehicle::ride_get, &ScVehicle::ride_set, "ride"); 61 dukglue_register_property(ctx, &ScVehicle::rideObject_get, &ScVehicle::rideObject_set, "rideObject"); 62 dukglue_register_property(ctx, &ScVehicle::vehicleObject_get, &ScVehicle::vehicleObject_set, "vehicleObject"); 63 dukglue_register_property(ctx, &ScVehicle::spriteType_get, &ScVehicle::spriteType_set, "spriteType"); 64 dukglue_register_property(ctx, &ScVehicle::numSeats_get, &ScVehicle::numSeats_set, "numSeats"); 65 dukglue_register_property(ctx, &ScVehicle::nextCarOnTrain_get, &ScVehicle::nextCarOnTrain_set, "nextCarOnTrain"); 66 dukglue_register_property( 67 ctx, &ScVehicle::previousCarOnRide_get, &ScVehicle::previousCarOnRide_set, "previousCarOnRide"); 68 dukglue_register_property(ctx, &ScVehicle::nextCarOnRide_get, &ScVehicle::nextCarOnRide_set, "nextCarOnRide"); 69 dukglue_register_property(ctx, &ScVehicle::currentStation_get, &ScVehicle::currentStation_set, "currentStation"); 70 dukglue_register_property(ctx, &ScVehicle::mass_get, &ScVehicle::mass_set, "mass"); 71 dukglue_register_property(ctx, &ScVehicle::acceleration_get, &ScVehicle::acceleration_set, "acceleration"); 72 dukglue_register_property(ctx, &ScVehicle::velocity_get, &ScVehicle::velocity_set, "velocity"); 73 dukglue_register_property(ctx, &ScVehicle::bankRotation_get, &ScVehicle::bankRotation_set, "bankRotation"); 74 dukglue_register_property(ctx, &ScVehicle::colours_get, &ScVehicle::colours_set, "colours"); 75 dukglue_register_property(ctx, &ScVehicle::trackLocation_get, &ScVehicle::trackLocation_set, "trackLocation"); 76 dukglue_register_property(ctx, &ScVehicle::trackProgress_get, nullptr, "trackProgress"); 77 dukglue_register_property(ctx, &ScVehicle::remainingDistance_get, nullptr, "remainingDistance"); 78 dukglue_register_property( 79 ctx, &ScVehicle::poweredAcceleration_get, &ScVehicle::poweredAcceleration_set, "poweredAcceleration"); 80 dukglue_register_property(ctx, &ScVehicle::poweredMaxSpeed_get, &ScVehicle::poweredMaxSpeed_set, "poweredMaxSpeed"); 81 dukglue_register_property(ctx, &ScVehicle::status_get, &ScVehicle::status_set, "status"); 82 dukglue_register_property(ctx, &ScVehicle::guests_get, nullptr, "peeps"); 83 dukglue_register_property(ctx, &ScVehicle::guests_get, nullptr, "guests"); 84 dukglue_register_property(ctx, &ScVehicle::gForces_get, nullptr, "gForces"); 85 dukglue_register_method(ctx, &ScVehicle::travelBy, "travelBy"); 86 } 87 GetVehicle() const88 Vehicle* ScVehicle::GetVehicle() const 89 { 90 return ::GetEntity<Vehicle>(_id); 91 } 92 rideObject_get() const93 uint8_t ScVehicle::rideObject_get() const 94 { 95 auto vehicle = GetVehicle(); 96 return vehicle != nullptr ? vehicle->ride_subtype : 0; 97 } rideObject_set(uint8_t value)98 void ScVehicle::rideObject_set(uint8_t value) 99 { 100 ThrowIfGameStateNotMutable(); 101 auto vehicle = GetVehicle(); 102 if (vehicle != nullptr) 103 { 104 vehicle->ride_subtype = value; 105 } 106 } 107 vehicleObject_get() const108 uint8_t ScVehicle::vehicleObject_get() const 109 { 110 auto vehicle = GetVehicle(); 111 return vehicle != nullptr ? vehicle->vehicle_type : 0; 112 } vehicleObject_set(uint8_t value)113 void ScVehicle::vehicleObject_set(uint8_t value) 114 { 115 ThrowIfGameStateNotMutable(); 116 auto vehicle = GetVehicle(); 117 if (vehicle != nullptr) 118 { 119 vehicle->vehicle_type = value; 120 } 121 } 122 spriteType_get() const123 uint8_t ScVehicle::spriteType_get() const 124 { 125 auto vehicle = GetVehicle(); 126 return vehicle != nullptr ? vehicle->Pitch : 0; 127 } spriteType_set(uint8_t value)128 void ScVehicle::spriteType_set(uint8_t value) 129 { 130 ThrowIfGameStateNotMutable(); 131 auto vehicle = GetVehicle(); 132 if (vehicle != nullptr) 133 { 134 vehicle->Pitch = value; 135 } 136 } 137 ride_get() const138 int32_t ScVehicle::ride_get() const 139 { 140 auto vehicle = GetVehicle(); 141 return EnumValue(vehicle != nullptr ? vehicle->ride : RIDE_ID_NULL); 142 } ride_set(int32_t value)143 void ScVehicle::ride_set(int32_t value) 144 { 145 ThrowIfGameStateNotMutable(); 146 auto vehicle = GetVehicle(); 147 if (vehicle != nullptr) 148 { 149 vehicle->ride = static_cast<ride_id_t>(value); 150 } 151 } 152 numSeats_get() const153 uint8_t ScVehicle::numSeats_get() const 154 { 155 auto vehicle = GetVehicle(); 156 return vehicle != nullptr ? vehicle->num_seats & VEHICLE_SEAT_NUM_MASK : 0; 157 } numSeats_set(uint8_t value)158 void ScVehicle::numSeats_set(uint8_t value) 159 { 160 ThrowIfGameStateNotMutable(); 161 auto vehicle = GetVehicle(); 162 if (vehicle != nullptr) 163 { 164 vehicle->num_seats &= ~VEHICLE_SEAT_NUM_MASK; 165 vehicle->num_seats |= value & VEHICLE_SEAT_NUM_MASK; 166 } 167 } 168 nextCarOnTrain_get() const169 DukValue ScVehicle::nextCarOnTrain_get() const 170 { 171 auto ctx = GetContext()->GetScriptEngine().GetContext(); 172 auto vehicle = GetVehicle(); 173 if (vehicle != nullptr) 174 { 175 if (vehicle->next_vehicle_on_train != SPRITE_INDEX_NULL) 176 { 177 return ToDuk<int32_t>(ctx, vehicle->next_vehicle_on_train); 178 } 179 } 180 return ToDuk(ctx, nullptr); 181 } nextCarOnTrain_set(DukValue value)182 void ScVehicle::nextCarOnTrain_set(DukValue value) 183 { 184 ThrowIfGameStateNotMutable(); 185 auto vehicle = GetVehicle(); 186 if (vehicle != nullptr) 187 { 188 if (value.type() == DukValue::Type::NUMBER) 189 { 190 vehicle->next_vehicle_on_train = static_cast<uint16_t>(value.as_int()); 191 } 192 else 193 { 194 vehicle->next_vehicle_on_train = SPRITE_INDEX_NULL; 195 } 196 } 197 } 198 previousCarOnRide_get() const199 uint16_t ScVehicle::previousCarOnRide_get() const 200 { 201 auto vehicle = GetVehicle(); 202 return vehicle != nullptr ? vehicle->prev_vehicle_on_ride : 0; 203 } previousCarOnRide_set(uint16_t value)204 void ScVehicle::previousCarOnRide_set(uint16_t value) 205 { 206 ThrowIfGameStateNotMutable(); 207 auto vehicle = GetVehicle(); 208 if (vehicle != nullptr) 209 { 210 vehicle->prev_vehicle_on_ride = value; 211 } 212 } 213 nextCarOnRide_get() const214 uint16_t ScVehicle::nextCarOnRide_get() const 215 { 216 auto vehicle = GetVehicle(); 217 return vehicle != nullptr ? vehicle->next_vehicle_on_ride : 0; 218 } nextCarOnRide_set(uint16_t value)219 void ScVehicle::nextCarOnRide_set(uint16_t value) 220 { 221 ThrowIfGameStateNotMutable(); 222 auto vehicle = GetVehicle(); 223 if (vehicle != nullptr) 224 { 225 vehicle->next_vehicle_on_ride = value; 226 } 227 } 228 currentStation_get() const229 StationIndex ScVehicle::currentStation_get() const 230 { 231 auto vehicle = GetVehicle(); 232 return vehicle != nullptr ? vehicle->current_station : 0; 233 } currentStation_set(StationIndex value)234 void ScVehicle::currentStation_set(StationIndex value) 235 { 236 ThrowIfGameStateNotMutable(); 237 auto vehicle = GetVehicle(); 238 if (vehicle != nullptr) 239 { 240 vehicle->current_station = value; 241 } 242 } 243 mass_get() const244 uint16_t ScVehicle::mass_get() const 245 { 246 auto vehicle = GetVehicle(); 247 return vehicle != nullptr ? vehicle->mass : 0; 248 } mass_set(uint16_t value)249 void ScVehicle::mass_set(uint16_t value) 250 { 251 ThrowIfGameStateNotMutable(); 252 auto vehicle = GetVehicle(); 253 if (vehicle != nullptr) 254 { 255 vehicle->mass = value; 256 } 257 } 258 acceleration_get() const259 int32_t ScVehicle::acceleration_get() const 260 { 261 auto vehicle = GetVehicle(); 262 return vehicle != nullptr ? vehicle->acceleration : 0; 263 } acceleration_set(int32_t value)264 void ScVehicle::acceleration_set(int32_t value) 265 { 266 ThrowIfGameStateNotMutable(); 267 auto vehicle = GetVehicle(); 268 if (vehicle != nullptr) 269 { 270 vehicle->acceleration = value; 271 } 272 } 273 velocity_get() const274 int32_t ScVehicle::velocity_get() const 275 { 276 auto vehicle = GetVehicle(); 277 return vehicle != nullptr ? vehicle->velocity : 0; 278 } velocity_set(int32_t value)279 void ScVehicle::velocity_set(int32_t value) 280 { 281 ThrowIfGameStateNotMutable(); 282 auto vehicle = GetVehicle(); 283 if (vehicle != nullptr) 284 { 285 vehicle->velocity = value; 286 } 287 } 288 bankRotation_get() const289 uint8_t ScVehicle::bankRotation_get() const 290 { 291 auto vehicle = GetVehicle(); 292 return vehicle != nullptr ? vehicle->bank_rotation : 0; 293 } bankRotation_set(uint8_t value)294 void ScVehicle::bankRotation_set(uint8_t value) 295 { 296 ThrowIfGameStateNotMutable(); 297 auto vehicle = GetVehicle(); 298 if (vehicle != nullptr) 299 { 300 vehicle->bank_rotation = value; 301 } 302 } 303 colours_get() const304 DukValue ScVehicle::colours_get() const 305 { 306 auto ctx = GetContext()->GetScriptEngine().GetContext(); 307 auto vehicle = GetVehicle(); 308 if (vehicle != nullptr) 309 { 310 VehicleColour colours; 311 colours.Body = vehicle->colours.body_colour; 312 colours.Trim = vehicle->colours.trim_colour; 313 colours.Ternary = vehicle->colours_extended; 314 return ToDuk<VehicleColour>(ctx, colours); 315 } 316 return ToDuk(ctx, nullptr); 317 } colours_set(const DukValue & value)318 void ScVehicle::colours_set(const DukValue& value) 319 { 320 ThrowIfGameStateNotMutable(); 321 auto vehicle = GetVehicle(); 322 if (vehicle != nullptr) 323 { 324 auto colours = FromDuk<VehicleColour>(value); 325 vehicle->colours.body_colour = colours.Body; 326 vehicle->colours.trim_colour = colours.Trim; 327 vehicle->colours_extended = colours.Ternary; 328 } 329 } 330 trackLocation_get() const331 DukValue ScVehicle::trackLocation_get() const 332 { 333 auto ctx = GetContext()->GetScriptEngine().GetContext(); 334 auto vehicle = GetVehicle(); 335 if (vehicle != nullptr) 336 { 337 auto coords = CoordsXYZD(vehicle->TrackLocation, vehicle->GetTrackDirection()); 338 return ToDuk<CoordsXYZD>(ctx, coords); 339 } 340 return ToDuk(ctx, nullptr); 341 } trackLocation_set(const DukValue & value)342 void ScVehicle::trackLocation_set(const DukValue& value) 343 { 344 ThrowIfGameStateNotMutable(); 345 auto vehicle = GetVehicle(); 346 if (vehicle != nullptr) 347 { 348 auto coords = FromDuk<CoordsXYZD>(value); 349 vehicle->TrackLocation = CoordsXYZ(coords.x, coords.y, coords.z); 350 vehicle->SetTrackDirection(coords.direction); 351 } 352 } 353 trackProgress_get() const354 uint16_t ScVehicle::trackProgress_get() const 355 { 356 auto vehicle = GetVehicle(); 357 return vehicle != nullptr ? vehicle->track_progress : 0; 358 } 359 remainingDistance_get() const360 int32_t ScVehicle::remainingDistance_get() const 361 { 362 auto vehicle = GetVehicle(); 363 return vehicle != nullptr ? vehicle->remaining_distance : 0; 364 } 365 poweredAcceleration_get() const366 uint8_t ScVehicle::poweredAcceleration_get() const 367 { 368 auto vehicle = GetVehicle(); 369 return vehicle != nullptr ? vehicle->powered_acceleration : 0; 370 } poweredAcceleration_set(uint8_t value)371 void ScVehicle::poweredAcceleration_set(uint8_t value) 372 { 373 ThrowIfGameStateNotMutable(); 374 auto vehicle = GetVehicle(); 375 if (vehicle != nullptr) 376 { 377 vehicle->powered_acceleration = value; 378 } 379 } 380 poweredMaxSpeed_get() const381 uint8_t ScVehicle::poweredMaxSpeed_get() const 382 { 383 auto vehicle = GetVehicle(); 384 return vehicle != nullptr ? vehicle->speed : 0; 385 } poweredMaxSpeed_set(uint8_t value)386 void ScVehicle::poweredMaxSpeed_set(uint8_t value) 387 { 388 ThrowIfGameStateNotMutable(); 389 auto vehicle = GetVehicle(); 390 if (vehicle != nullptr) 391 { 392 vehicle->speed = value; 393 } 394 } 395 status_get() const396 std::string ScVehicle::status_get() const 397 { 398 auto vehicle = GetVehicle(); 399 if (vehicle != nullptr) 400 { 401 return std::string(VehicleStatusMap[vehicle->status]); 402 } 403 return {}; 404 } status_set(const std::string & value)405 void ScVehicle::status_set(const std::string& value) 406 { 407 ThrowIfGameStateNotMutable(); 408 auto vehicle = GetVehicle(); 409 if (vehicle != nullptr) 410 { 411 vehicle->status = VehicleStatusMap[value]; 412 } 413 } 414 guests_get() const415 std::vector<DukValue> ScVehicle::guests_get() const 416 { 417 auto ctx = GetContext()->GetScriptEngine().GetContext(); 418 std::vector<DukValue> result; 419 auto vehicle = GetVehicle(); 420 if (vehicle != nullptr) 421 { 422 size_t len = 0; 423 for (size_t i = 0; i < std::size(vehicle->peep); i++) 424 { 425 auto peep = vehicle->peep[i]; 426 if (peep == SPRITE_INDEX_NULL) 427 { 428 result.push_back(ToDuk(ctx, nullptr)); 429 } 430 else 431 { 432 result.push_back(ToDuk<int32_t>(ctx, peep)); 433 len = i + 1; 434 } 435 } 436 result.resize(len); 437 } 438 return result; 439 } 440 gForces_get() const441 DukValue ScVehicle::gForces_get() const 442 { 443 auto ctx = GetContext()->GetScriptEngine().GetContext(); 444 auto vehicle = GetVehicle(); 445 if (vehicle != nullptr) 446 { 447 GForces gForces = vehicle->GetGForces(); 448 return ToDuk<GForces>(ctx, gForces); 449 } 450 return ToDuk(ctx, nullptr); 451 } 452 travelBy(int32_t value)453 void ScVehicle::travelBy(int32_t value) 454 { 455 ThrowIfGameStateNotMutable(); 456 auto vehicle = GetVehicle(); 457 if (vehicle != nullptr) 458 { 459 vehicle->MoveRelativeDistance(value); 460 } 461 } 462 463 } // namespace OpenRCT2::Scripting 464 465 #endif 466