424 if (filename ==
"autosave.sav")
426 if (x_actors.size() > 3)
434 rapidjson::Document j_doc;
440 String scene_name = StringUtil::format(
"%s [%d]", pretty_name.c_str(), x_actors.size());
441 j_doc.AddMember(
"scene_name", rapidjson::StringRef(scene_name.c_str()), j_doc.GetAllocator());
444 j_doc.AddMember(
"terrain_name", rapidjson::StringRef(
App::sim_terrain_name->getStr().c_str()), j_doc.GetAllocator());
449 j_doc.AddMember(
"daytime",
App::GetGameContext()->GetTerrain()->getSkyManager()->GetTime(), j_doc.GetAllocator());
453 j_doc.AddMember(
"forced_awake",
m_forced_awake, j_doc.GetAllocator());
458 rapidjson::Value j_player_position(rapidjson::kArrayType);
459 j_player_position.PushBack(
App::GetGameContext()->GetPlayerCharacter()->getPosition().
x, j_doc.GetAllocator());
460 j_player_position.PushBack(
App::GetGameContext()->GetPlayerCharacter()->getPosition().
y, j_doc.GetAllocator());
461 j_player_position.PushBack(
App::GetGameContext()->GetPlayerCharacter()->getPosition().
z, j_doc.GetAllocator());
462 j_doc.AddMember(
"player_position", j_player_position, j_doc.GetAllocator());
463 j_doc.AddMember(
"player_rotation",
App::GetGameContext()->GetPlayerCharacter()->getRotation().valueRadians(), j_doc.GetAllocator());
465 std::map<int, int> vector_index_lookup;
468 vector_index_lookup[actor->ar_vector_index] = -1;
469 auto search = std::find_if(x_actors.begin(), x_actors.end(), [actor](
ActorPtr b)
470 { return actor->ar_instance_id == b->ar_instance_id; });
471 if (search != x_actors.end())
473 vector_index_lookup[actor->ar_vector_index] = std::distance(x_actors.begin(), search);
478 rapidjson::Value j_actors(rapidjson::kArrayType);
481 rapidjson::Value j_entry(rapidjson::kObjectType);
486 Ogre::StringUtil::splitFilename(actor->getUsedActorEntry()->resource_bundle_path, bname, bpath);
487 std::string bq_filename = fmt::format(
"{}:{}", bname, actor->ar_filename);
488 rapidjson::Value j_bq_filename(bq_filename.c_str(), j_doc.GetAllocator());
489 j_entry.AddMember(
"filename", j_bq_filename, j_doc.GetAllocator());
491 rapidjson::Value j_actor_position(rapidjson::kArrayType);
492 j_actor_position.PushBack(actor->ar_nodes[0].AbsPosition.x, j_doc.GetAllocator());
493 j_actor_position.PushBack(actor->ar_nodes[0].AbsPosition.y, j_doc.GetAllocator());
494 j_actor_position.PushBack(actor->ar_nodes[0].AbsPosition.z, j_doc.GetAllocator());
495 j_entry.AddMember(
"position", j_actor_position, j_doc.GetAllocator());
496 j_entry.AddMember(
"rotation", actor->getRotation(), j_doc.GetAllocator());
497 j_entry.AddMember(
"min_height", actor->getMinHeight(), j_doc.GetAllocator());
498 j_entry.AddMember(
"spawn_rotation", actor->m_spawn_rotation, j_doc.GetAllocator());
499 j_entry.AddMember(
"preloaded_with_terrain", actor->isPreloadedWithTerrain(), j_doc.GetAllocator());
500 j_entry.AddMember(
"sim_state",
static_cast<int>(actor->ar_state), j_doc.GetAllocator());
501 j_entry.AddMember(
"physics_paused", actor->ar_physics_paused, j_doc.GetAllocator());
502 j_entry.AddMember(
"player_actor", actor==
App::GetGameContext()->GetPlayerActor(), j_doc.GetAllocator());
503 j_entry.AddMember(
"prev_player_actor", actor==
App::GetGameContext()->GetPrevPlayerActor(), j_doc.GetAllocator());
505 if (actor->m_used_skin_entry)
507 j_entry.AddMember(
"skin", rapidjson::StringRef(actor->m_used_skin_entry->dname.c_str()), j_doc.GetAllocator());
510 if (actor->getWorkingTuneupDef())
513 rapidjson::Value j_tuneup_document(rapidjson::kStringType);
515 Ogre::DataStreamPtr datastream(
new Ogre::MemoryDataStream(tuneup_buf.
GetBuffer(), tuneup_buf.
GetCapacity()));
517 j_tuneup_document.SetString(datastream->getAsString().c_str(), j_doc.GetAllocator());
518 j_entry.AddMember(
"tuneup_document", j_tuneup_document, j_doc.GetAllocator());
521 j_entry.AddMember(
"section_config", rapidjson::StringRef(actor->m_section_config.c_str()), j_doc.GetAllocator());
524 if (actor->ar_engine)
526 j_entry.AddMember(
"engine_gear", actor->ar_engine->getGear(), j_doc.GetAllocator());
527 j_entry.AddMember(
"engine_rpm", actor->ar_engine->getRPM(), j_doc.GetAllocator());
528 j_entry.AddMember(
"engine_auto_mode",
static_cast<int>(actor->ar_engine->getAutoMode()), j_doc.GetAllocator());
529 j_entry.AddMember(
"engine_auto_select", actor->ar_engine->getAutoShift(), j_doc.GetAllocator());
530 j_entry.AddMember(
"engine_is_running", actor->ar_engine->isRunning(), j_doc.GetAllocator());
531 j_entry.AddMember(
"engine_has_contact", actor->ar_engine->hasContact(), j_doc.GetAllocator());
532 j_entry.AddMember(
"engine_wheel_spin", actor->ar_wheel_spin, j_doc.GetAllocator());
533 j_entry.AddMember(
"alb_mode", actor->alb_mode, j_doc.GetAllocator());
534 j_entry.AddMember(
"tc_mode", actor->tc_mode, j_doc.GetAllocator());
535 j_entry.AddMember(
"cc_mode", actor->cc_mode, j_doc.GetAllocator());
536 j_entry.AddMember(
"cc_target_rpm", actor->cc_target_rpm, j_doc.GetAllocator());
537 j_entry.AddMember(
"cc_target_speed", actor->cc_target_speed, j_doc.GetAllocator());
540 j_entry.AddMember(
"hydro_dir_state", actor->ar_hydro_dir_state, j_doc.GetAllocator());
541 j_entry.AddMember(
"hydro_aileron_state", actor->ar_hydro_aileron_state, j_doc.GetAllocator());
542 j_entry.AddMember(
"hydro_rudder_state", actor->ar_hydro_rudder_state, j_doc.GetAllocator());
543 j_entry.AddMember(
"hydro_elevator_state", actor->ar_hydro_elevator_state, j_doc.GetAllocator());
544 j_entry.AddMember(
"parking_brake", actor->ar_parking_brake, j_doc.GetAllocator());
545 j_entry.AddMember(
"trailer_parking_brake", actor->ar_trailer_parking_brake, j_doc.GetAllocator());
546 j_entry.AddMember(
"avg_wheel_speed", actor->ar_avg_wheel_speed, j_doc.GetAllocator());
547 j_entry.AddMember(
"wheel_speed", actor->ar_wheel_speed, j_doc.GetAllocator());
548 j_entry.AddMember(
"wheel_spin", actor->ar_wheel_spin, j_doc.GetAllocator());
550 j_entry.AddMember(
"custom_particles", actor->ar_cparticles_active, j_doc.GetAllocator());
553 j_entry.AddMember(
"lights", (
int)actor->getHeadlightsVisible(), j_doc.GetAllocator());
554 j_entry.AddMember(
"blink_type", (
int)actor->getBlinkType(), j_doc.GetAllocator());
557 j_entry.AddMember(
"beacon_light", actor->getBeaconMode(), j_doc.GetAllocator());
558 j_entry.AddMember(
"high_beams_on", actor->getHighBeamsVisible(), j_doc.GetAllocator());
559 j_entry.AddMember(
"fog_lights_on", actor->getFogLightsVisible(), j_doc.GetAllocator());
562 rapidjson::Value j_custom_lights(rapidjson::kArrayType);
565 j_custom_lights.PushBack(actor->getCustomLightVisible(i), j_doc.GetAllocator());
567 j_entry.AddMember(
"custom_lights", j_custom_lights, j_doc.GetAllocator());
570 if (actor->m_buoyance)
572 j_entry.AddMember(
"buoyance_sink", actor->m_buoyance->sink, j_doc.GetAllocator());
576 rapidjson::Value j_aeroengines(rapidjson::kArrayType);
577 for (
int i = 0; i < actor->ar_num_aeroengines; i++)
579 rapidjson::Value j_aeroengine(rapidjson::kObjectType);
580 j_aeroengine.AddMember(
"rpm", actor->ar_aeroengines[i]->getRPM(), j_doc.GetAllocator());
581 j_aeroengine.AddMember(
"reverse", actor->ar_aeroengines[i]->getReverse(), j_doc.GetAllocator());
582 j_aeroengine.AddMember(
"ignition", actor->ar_aeroengines[i]->getIgnition(), j_doc.GetAllocator());
583 j_aeroengine.AddMember(
"throttle", actor->ar_aeroengines[i]->getThrottle(), j_doc.GetAllocator());
584 j_aeroengines.PushBack(j_aeroengine, j_doc.GetAllocator());
586 j_entry.AddMember(
"aeroengines", j_aeroengines, j_doc.GetAllocator());
589 rapidjson::Value j_screwprops(rapidjson::kArrayType);
590 for (
int i = 0; i < actor->ar_num_screwprops; i++)
592 rapidjson::Value j_screwprop(rapidjson::kObjectType);
593 j_screwprop.AddMember(
"rudder", actor->ar_screwprops[i]->getRudder(), j_doc.GetAllocator());
594 j_screwprop.AddMember(
"throttle", actor->ar_screwprops[i]->getThrottle(), j_doc.GetAllocator());
595 j_screwprops.PushBack(j_screwprop, j_doc.GetAllocator());
597 j_entry.AddMember(
"screwprops", j_screwprops, j_doc.GetAllocator());
600 rapidjson::Value j_rotators(rapidjson::kArrayType);
601 for (
int i = 0; i < actor->ar_num_rotators; i++)
603 j_rotators.PushBack(actor->ar_rotators[i].angle, j_doc.GetAllocator());
605 j_entry.AddMember(
"rotators", j_rotators, j_doc.GetAllocator());
608 rapidjson::Value j_wheels(rapidjson::kArrayType);
609 for (
int i = 0; i < actor->ar_num_wheels; i++)
611 j_wheels.PushBack(actor->ar_wheels[i].wh_is_detached, j_doc.GetAllocator());
613 j_entry.AddMember(
"wheels", j_wheels, j_doc.GetAllocator());
616 rapidjson::Value j_wheel_diffs(rapidjson::kArrayType);
617 for (
int i = 0; i < actor->m_num_wheel_diffs; i++)
619 j_wheel_diffs.PushBack(actor->m_wheel_diffs[i]->GetActiveDiffType(), j_doc.GetAllocator());
621 j_entry.AddMember(
"wheel_diffs", j_wheel_diffs, j_doc.GetAllocator());
624 rapidjson::Value j_axle_diffs(rapidjson::kArrayType);
625 for (
int i = 0; i < actor->m_num_axle_diffs; i++)
627 j_axle_diffs.PushBack(actor->m_axle_diffs[i]->GetActiveDiffType(), j_doc.GetAllocator());
629 j_entry.AddMember(
"axle_diffs", j_axle_diffs, j_doc.GetAllocator());
632 if (actor->m_transfer_case)
634 rapidjson::Value j_transfer_case(rapidjson::kObjectType);
635 j_transfer_case.AddMember(
"4WD", actor->m_transfer_case->tr_4wd_mode, j_doc.GetAllocator());
636 j_transfer_case.AddMember(
"GearRatio", actor->m_transfer_case->tr_gear_ratios[0], j_doc.GetAllocator());
637 j_entry.AddMember(
"transfercase", j_transfer_case, j_doc.GetAllocator());
641 rapidjson::Value j_commands(rapidjson::kArrayType);
644 rapidjson::Value j_command(rapidjson::kArrayType);
645 j_command.PushBack(actor->ar_command_key[i].commandValue, j_doc.GetAllocator());
646 j_command.PushBack(actor->ar_command_key[i].triggerInputValue, j_doc.GetAllocator());
648 rapidjson::Value j_command_beams(rapidjson::kArrayType);
649 for (
int j = 0; j < (int)actor->ar_command_key[i].beams.size(); j++)
651 rapidjson::Value j_cmb(rapidjson::kArrayType);
652 auto& beam = actor->ar_command_key[i].beams[j];
653 j_cmb.PushBack(beam.cmb_state->auto_moving_mode, j_doc.GetAllocator());
654 j_cmb.PushBack(beam.cmb_state->pressed_center_mode, j_doc.GetAllocator());
655 j_command_beams.PushBack(j_cmb, j_doc.GetAllocator());
657 j_command.PushBack(j_command_beams, j_doc.GetAllocator());
659 j_commands.PushBack(j_command, j_doc.GetAllocator());
661 j_entry.AddMember(
"commands", j_commands, j_doc.GetAllocator());
664 rapidjson::Value j_hooks(rapidjson::kArrayType);
665 for (
const auto& h : actor->ar_hooks)
667 rapidjson::Value j_hook(rapidjson::kObjectType);
668 int lock_node = h.hk_lock_node ? h.hk_lock_node->pos : -1;
669 int locked_actor = h.hk_locked_actor ? vector_index_lookup[h.hk_locked_actor->ar_vector_index] : -1;
670 j_hook.AddMember(
"locked", h.hk_locked, j_doc.GetAllocator());
671 j_hook.AddMember(
"lock_node", lock_node, j_doc.GetAllocator());
672 j_hook.AddMember(
"locked_actor", locked_actor, j_doc.GetAllocator());
673 j_hooks.PushBack(j_hook, j_doc.GetAllocator());
675 j_entry.AddMember(
"hooks", j_hooks, j_doc.GetAllocator());
678 rapidjson::Value j_ropes(rapidjson::kArrayType);
679 for (
const auto& r : actor->ar_ropes)
681 rapidjson::Value j_rope(rapidjson::kObjectType);
682 int locked_ropable = r.rp_locked_ropable ? r.rp_locked_ropable->pos : -1;
683 int locked_actor = r.rp_locked_actor ? vector_index_lookup[r.rp_locked_actor->ar_vector_index] : -1;
684 j_rope.AddMember(
"locked", r.rp_locked, j_doc.GetAllocator());
685 j_rope.AddMember(
"locked_ropable", locked_ropable, j_doc.GetAllocator());
686 j_rope.AddMember(
"locked_actor", locked_actor, j_doc.GetAllocator());
687 j_ropes.PushBack(j_rope, j_doc.GetAllocator());
689 j_entry.AddMember(
"ropes", j_ropes, j_doc.GetAllocator());
692 rapidjson::Value j_ties(rapidjson::kArrayType);
693 for (
const auto& t : actor->ar_ties)
695 rapidjson::Value j_tie(rapidjson::kObjectType);
696 int locked_ropable = t.ti_locked_ropable ? t.ti_locked_ropable->pos : -1;
697 int locked_actor = t.ti_locked_actor ? vector_index_lookup[t.ti_locked_actor->ar_vector_index] : -1;
698 j_tie.AddMember(
"tied", t.ti_tied, j_doc.GetAllocator());
699 j_tie.AddMember(
"tying", t.ti_tying, j_doc.GetAllocator());
700 j_tie.AddMember(
"locked_ropable", locked_ropable, j_doc.GetAllocator());
701 j_tie.AddMember(
"locked_actor", locked_actor, j_doc.GetAllocator());
702 j_ties.PushBack(j_tie, j_doc.GetAllocator());
704 j_entry.AddMember(
"ties", j_ties, j_doc.GetAllocator());
707 rapidjson::Value j_ropables(rapidjson::kArrayType);
708 for (
const auto& r : actor->ar_ropables)
710 rapidjson::Value j_ropable(rapidjson::kObjectType);
711 j_ropable.AddMember(
"attached_ties", r.attached_ties, j_doc.GetAllocator());
712 j_ropable.AddMember(
"attached_ropes", r.attached_ropes, j_doc.GetAllocator());
713 j_ropables.PushBack(j_ropable, j_doc.GetAllocator());
715 j_entry.AddMember(
"ropables", j_ropables, j_doc.GetAllocator());
717 j_entry.AddMember(
"slidenodes_locked", actor->m_slidenodes_locked, j_doc.GetAllocator());
720 rapidjson::Value j_nodes(rapidjson::kArrayType);
721 for (
int i = 0; i < actor->ar_num_nodes; i++)
723 rapidjson::Value j_node(rapidjson::kArrayType);
726 j_node.PushBack(actor->ar_nodes[i].AbsPosition.x, j_doc.GetAllocator());
727 j_node.PushBack(actor->ar_nodes[i].AbsPosition.y, j_doc.GetAllocator());
728 j_node.PushBack(actor->ar_nodes[i].AbsPosition.z, j_doc.GetAllocator());
731 j_node.PushBack(actor->ar_nodes[i].Velocity.x, j_doc.GetAllocator());
732 j_node.PushBack(actor->ar_nodes[i].Velocity.y, j_doc.GetAllocator());
733 j_node.PushBack(actor->ar_nodes[i].Velocity.z, j_doc.GetAllocator());
736 j_node.PushBack(actor->ar_initial_node_positions[i].x, j_doc.GetAllocator());
737 j_node.PushBack(actor->ar_initial_node_positions[i].y, j_doc.GetAllocator());
738 j_node.PushBack(actor->ar_initial_node_positions[i].z, j_doc.GetAllocator());
740 j_nodes.PushBack(j_node, j_doc.GetAllocator());
742 j_entry.AddMember(
"nodes", j_nodes, j_doc.GetAllocator());
745 rapidjson::Value j_beams(rapidjson::kArrayType);
746 for (
int i = 0; i < actor->ar_num_beams; i++)
748 rapidjson::Value j_beam(rapidjson::kArrayType);
750 j_beam.PushBack(actor->ar_beams[i].maxposstress, j_doc.GetAllocator());
751 j_beam.PushBack(actor->ar_beams[i].maxnegstress, j_doc.GetAllocator());
752 j_beam.PushBack(actor->ar_beams[i].minmaxposnegstress, j_doc.GetAllocator());
753 j_beam.PushBack(actor->ar_beams[i].strength, j_doc.GetAllocator());
754 j_beam.PushBack(actor->ar_beams[i].L, j_doc.GetAllocator());
755 j_beam.PushBack(actor->ar_beams[i].bm_broken, j_doc.GetAllocator());
756 j_beam.PushBack(actor->ar_beams[i].bm_disabled, j_doc.GetAllocator());
757 j_beam.PushBack(actor->ar_beams[i].bm_inter_actor, j_doc.GetAllocator());
759 j_beam.PushBack(locked_actor ? vector_index_lookup[locked_actor->
ar_vector_index] : -1, j_doc.GetAllocator());
761 j_beams.PushBack(j_beam, j_doc.GetAllocator());
763 j_entry.AddMember(
"beams", j_beams, j_doc.GetAllocator());
765 j_actors.PushBack(j_entry, j_doc.GetAllocator());
767 j_doc.AddMember(
"actors", j_actors, j_doc.GetAllocator());
778 if (filename !=
"autosave.sav")